Skip to content

Commit

Permalink
Auto merge of rust-lang#112530 - matthiaskrgr:rollup-qee1kc1, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 3 pull requests

Successful merges:

 - rust-lang#112487 (Update documentation for `tools` defaults)
 - rust-lang#112513 (Dont compute `opt_suggest_box_span` span for TAIT)
 - rust-lang#112528 (bootstrap: Don't override `debuginfo-level = 1` to mean `line-tables-only`)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 11, 2023
2 parents 81c02da + c1f2da5 commit 37998ab
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 130 deletions.
8 changes: 8 additions & 0 deletions compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
..
} = self.type_var_origin(expected)? else { return None; };

let Some(rpit_local_def_id) = rpit_def_id.as_local() else { return None; };
if !matches!(
self.tcx.hir().expect_item(rpit_local_def_id).expect_opaque_ty().origin,
hir::OpaqueTyOrigin::FnReturn(..)
) {
return None;
}

let sig = self.body_fn_sig()?;

let substs = sig.output().walk().find_map(|arg| {
Expand Down
113 changes: 4 additions & 109 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@
//! ```

use crate::FnCtxt;
use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
};
use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
Expand All @@ -58,7 +56,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TypeAndMut};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{self, BytePos, DesugaringKind, Span};
use rustc_span::{self, DesugaringKind};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
Expand Down Expand Up @@ -1702,9 +1700,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err);

let mut pointing_at_return_type = false;
let mut fn_output = None;

let parent_id = fcx.tcx.hir().parent_id(id);
let parent = fcx.tcx.hir().get(parent_id);
if let Some(expr) = expression
Expand All @@ -1717,7 +1712,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
// label pointing out the cause for the type coercion will be wrong
// as prior return coercions would not be relevant (#57664).
let fn_decl = if let (Some(expr), Some(blk_id)) = (expression, blk_id) {
pointing_at_return_type =
let pointing_at_return_type =
fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id);
if let (Some(cond_expr), true, false) = (
fcx.tcx.hir().get_if_cause(expr.hir_id),
Expand Down Expand Up @@ -1749,7 +1744,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {

if let Some((fn_id, fn_decl, can_suggest)) = fn_decl {
if blk_id.is_none() {
pointing_at_return_type |= fcx.suggest_missing_return_type(
fcx.suggest_missing_return_type(
&mut err,
&fn_decl,
expected,
Expand All @@ -1758,9 +1753,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
fn_id,
);
}
if !pointing_at_return_type {
fn_output = Some(&fn_decl.output); // `impl Trait` return type
}
}

let parent_id = fcx.tcx.hir().get_parent_item(id);
Expand Down Expand Up @@ -1795,106 +1787,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
);
}

if let (Some(sp), Some(fn_output)) = (ret_coercion_span, fn_output) {
self.add_impl_trait_explanation(&mut err, cause, fcx, expected, sp, fn_output);
}

err
}

fn add_impl_trait_explanation<'a>(
&self,
err: &mut Diagnostic,
cause: &ObligationCause<'tcx>,
fcx: &FnCtxt<'a, 'tcx>,
expected: Ty<'tcx>,
sp: Span,
fn_output: &hir::FnRetTy<'_>,
) {
let return_sp = fn_output.span();
err.span_label(return_sp, "expected because this return type...");
err.span_label(
sp,
format!("...is found to be `{}` here", fcx.resolve_vars_with_obligations(expected)),
);
let impl_trait_msg = "for information on `impl Trait`, see \
<https://doc.rust-lang.org/book/ch10-02-traits.html\
#returning-types-that-implement-traits>";
let trait_obj_msg = "for information on trait objects, see \
<https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
#using-trait-objects-that-allow-for-values-of-different-types>";
err.note("to return `impl Trait`, all returned values must be of the same type");
err.note(impl_trait_msg);
let snippet = fcx
.tcx
.sess
.source_map()
.span_to_snippet(return_sp)
.unwrap_or_else(|_| "dyn Trait".to_string());
let mut snippet_iter = snippet.split_whitespace();
let has_impl = snippet_iter.next().is_some_and(|s| s == "impl");
// Only suggest `Box<dyn Trait>` if `Trait` in `impl Trait` is object safe.
let mut is_object_safe = false;
if let hir::FnRetTy::Return(ty) = fn_output
// Get the return type.
&& let hir::TyKind::OpaqueDef(..) = ty.kind
{
let ty = fcx.astconv().ast_ty_to_ty( ty);
// Get the `impl Trait`'s `DefId`.
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind()
// Get the `impl Trait`'s `Item` so that we can get its trait bounds and
// get the `Trait`'s `DefId`.
&& let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
fcx.tcx.hir().expect_item(def_id.expect_local()).kind
{
// Are of this `impl Trait`'s traits object safe?
is_object_safe = bounds.iter().all(|bound| {
bound
.trait_ref()
.and_then(|t| t.trait_def_id())
.is_some_and(|def_id| {
fcx.tcx.check_is_object_safe(def_id)
})
})
}
};
if has_impl {
if is_object_safe {
err.multipart_suggestion(
"you could change the return type to be a boxed trait object",
vec![
(return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
(return_sp.shrink_to_hi(), ">".to_string()),
],
Applicability::MachineApplicable,
);
let sugg = [sp, cause.span]
.into_iter()
.flat_map(|sp| {
[
(sp.shrink_to_lo(), "Box::new(".to_string()),
(sp.shrink_to_hi(), ")".to_string()),
]
.into_iter()
})
.collect::<Vec<_>>();
err.multipart_suggestion(
"if you change the return type to expect trait objects, box the returned \
expressions",
sugg,
Applicability::MaybeIncorrect,
);
} else {
err.help(format!(
"if the trait `{}` were object safe, you could return a boxed trait object",
&snippet[5..]
));
}
err.note(trait_obj_msg);
}
err.help("you could instead create a new `enum` with a variant for each returned type");
}

/// Checks whether the return type is unsized via an obligation, which makes
/// sure we consider `dyn Trait: Sized` where clauses, which are trivially
/// false but technically valid for typeck.
Expand Down
20 changes: 19 additions & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
) {
err.subdiagnostic(subdiag);
}
if let Some(ret_sp) = opt_suggest_box_span {
// don't suggest wrapping either blocks in `if .. {} else {}`
let is_empty_arm = |id| {
let hir::Node::Block(blk) = self.tcx.hir().get(id)
else {
return false;
};
if blk.expr.is_some() || !blk.stmts.is_empty() {
return false;
}
let Some((_, hir::Node::Expr(expr))) = self.tcx.hir().parent_iter(id).nth(1)
else {
return false;
};
matches!(expr.kind, hir::ExprKind::If(..))
};
if let Some(ret_sp) = opt_suggest_box_span
&& !is_empty_arm(then_id)
&& !is_empty_arm(else_id)
{
self.suggest_boxing_for_return_impl_trait(
err,
ret_sp,
Expand Down
7 changes: 1 addition & 6 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1649,12 +1649,7 @@ impl<'a> Builder<'a> {
self.config.rust_debuginfo_level_tools
}
};
if debuginfo_level == 1 {
// Use less debuginfo than the default to save on disk space.
cargo.env(profile_var("DEBUG"), "line-tables-only");
} else {
cargo.env(profile_var("DEBUG"), debuginfo_level.to_string());
};
cargo.env(profile_var("DEBUG"), debuginfo_level.to_string());
if self.cc[&target].args().iter().any(|arg| arg == "-gz") {
rustflags.arg("-Clink-arg=-gz");
}
Expand Down
86 changes: 72 additions & 14 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::cell::{Cell, RefCell};
use std::cmp;
use std::collections::{HashMap, HashSet};
use std::env;
use std::fmt;
use std::fmt::{self, Display};
use std::fs;
use std::io::IsTerminal;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -50,6 +50,57 @@ pub enum DryRun {
UserSelected,
}

#[derive(Copy, Clone, Default)]
pub enum DebuginfoLevel {
#[default]
None,
LineTablesOnly,
Limited,
Full,
}

// NOTE: can't derive(Deserialize) because the intermediate trip through toml::Value only
// deserializes i64, and derive() only generates visit_u64
impl<'de> Deserialize<'de> for DebuginfoLevel {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error;

Ok(match Deserialize::deserialize(deserializer)? {
StringOrInt::String("none") | StringOrInt::Int(0) => DebuginfoLevel::None,
StringOrInt::String("line-tables-only") => DebuginfoLevel::LineTablesOnly,
StringOrInt::String("limited") | StringOrInt::Int(1) => DebuginfoLevel::Limited,
StringOrInt::String("full") | StringOrInt::Int(2) => DebuginfoLevel::Full,
StringOrInt::Int(n) => {
let other = serde::de::Unexpected::Signed(n);
return Err(D::Error::invalid_value(other, &"expected 0, 1, or 2"));
}
StringOrInt::String(s) => {
let other = serde::de::Unexpected::Str(s);
return Err(D::Error::invalid_value(
other,
&"expected none, line-tables-only, limited, or full",
));
}
})
}
}

/// Suitable for passing to `-C debuginfo`
impl Display for DebuginfoLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use DebuginfoLevel::*;
f.write_str(match self {
None => "0",
LineTablesOnly => "line-tables-only",
Limited => "1",
Full => "2",
})
}
}

/// Global configuration for the entire build and/or bootstrap.
///
/// This structure is parsed from `config.toml`, and some of the fields are inferred from `git` or build-time parameters.
Expand Down Expand Up @@ -159,10 +210,10 @@ pub struct Config {
pub rust_overflow_checks: bool,
pub rust_overflow_checks_std: bool,
pub rust_debug_logging: bool,
pub rust_debuginfo_level_rustc: u32,
pub rust_debuginfo_level_std: u32,
pub rust_debuginfo_level_tools: u32,
pub rust_debuginfo_level_tests: u32,
pub rust_debuginfo_level_rustc: DebuginfoLevel,
pub rust_debuginfo_level_std: DebuginfoLevel,
pub rust_debuginfo_level_tools: DebuginfoLevel,
pub rust_debuginfo_level_tests: DebuginfoLevel,
pub rust_split_debuginfo: SplitDebuginfo,
pub rust_rpath: bool,
pub rustc_parallel: bool,
Expand Down Expand Up @@ -810,6 +861,13 @@ impl Default for StringOrBool {
}
}

#[derive(Deserialize)]
#[serde(untagged)]
enum StringOrInt<'a> {
String(&'a str),
Int(i64),
}

define_config! {
/// TOML representation of how the Rust build is configured.
struct Rust {
Expand All @@ -822,11 +880,11 @@ define_config! {
overflow_checks: Option<bool> = "overflow-checks",
overflow_checks_std: Option<bool> = "overflow-checks-std",
debug_logging: Option<bool> = "debug-logging",
debuginfo_level: Option<u32> = "debuginfo-level",
debuginfo_level_rustc: Option<u32> = "debuginfo-level-rustc",
debuginfo_level_std: Option<u32> = "debuginfo-level-std",
debuginfo_level_tools: Option<u32> = "debuginfo-level-tools",
debuginfo_level_tests: Option<u32> = "debuginfo-level-tests",
debuginfo_level: Option<DebuginfoLevel> = "debuginfo-level",
debuginfo_level_rustc: Option<DebuginfoLevel> = "debuginfo-level-rustc",
debuginfo_level_std: Option<DebuginfoLevel> = "debuginfo-level-std",
debuginfo_level_tools: Option<DebuginfoLevel> = "debuginfo-level-tools",
debuginfo_level_tests: Option<DebuginfoLevel> = "debuginfo-level-tests",
split_debuginfo: Option<String> = "split-debuginfo",
run_dsymutil: Option<bool> = "run-dsymutil",
backtrace: Option<bool> = "backtrace",
Expand Down Expand Up @@ -1478,17 +1536,17 @@ impl Config {

config.rust_debug_logging = debug_logging.unwrap_or(config.rust_debug_assertions);

let with_defaults = |debuginfo_level_specific: Option<u32>| {
let with_defaults = |debuginfo_level_specific: Option<_>| {
debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {
1
DebuginfoLevel::Limited
} else {
0
DebuginfoLevel::None
})
};
config.rust_debuginfo_level_rustc = with_defaults(debuginfo_level_rustc);
config.rust_debuginfo_level_std = with_defaults(debuginfo_level_std);
config.rust_debuginfo_level_tools = with_defaults(debuginfo_level_tools);
config.rust_debuginfo_level_tests = debuginfo_level_tests.unwrap_or(0);
config.rust_debuginfo_level_tests = debuginfo_level_tests.unwrap_or(DebuginfoLevel::None);

let download_rustc = config.download_rustc_commit.is_some();
// See https://github.com/rust-lang/compiler-team/issues/326
Expand Down
2 changes: 2 additions & 0 deletions src/bootstrap/defaults/config.tools.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ debug-logging = true
incremental = true
# Download rustc from CI instead of building it from source.
# This cuts compile times by almost 60x, but means you can't modify the compiler.
# Using these defaults will download the stage2 compiler (see `download-rustc`
# setting) and the stage2 toolchain should therefore be used for these defaults.
download-rustc = "if-unchanged"

[build]
Expand Down
8 changes: 8 additions & 0 deletions src/bootstrap/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ pub fn setup(config: &Config, profile: Profile) {
);
}

if profile == Profile::Tools {
eprintln!();
eprintln!(
"note: the `tools` profile sets up the `stage2` toolchain (use \
`rustup toolchain link 'name' host/build/stage2` to use rustc)"
)
}

let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
setup_config_toml(path, profile, config);
}
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/impl-trait/dont-suggest-box-on-empty-else-arm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn test() -> impl std::fmt::Debug {
if true {
"boo2"
} else {
//~^ ERROR `if` and `else` have incompatible types
}
}

fn main() {}
Loading

0 comments on commit 37998ab

Please sign in to comment.