Skip to content

Commit

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

Rollup of 7 pull requests

Successful merges:

 - rust-lang#111659 (suggest `Option::as_deref(_mut)` on type mismatch in option combinator if it passes typeck)
 - rust-lang#111702 (Option::map_or_else: Show an example of integrating with Result)
 - rust-lang#111878 (Fix codegen test suite for bare-metal-like targets)
 - rust-lang#111969 (bootstrap: Make `clean` respect `dry-run`)
 - rust-lang#111998 (Add other workspaces to `linkedProjects` in rust_analyzer_settings)
 - rust-lang#112215 (only suppress coercion error if type is definitely unsized)
 - rust-lang#112231 (Make sure the build.rustc version is either the same or 1 apart (revised))

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 3, 2023
2 parents 2f5e6bb + d4f87d1 commit 398fa21
Show file tree
Hide file tree
Showing 40 changed files with 586 additions and 80 deletions.
30 changes: 19 additions & 11 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1595,7 +1595,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
Some(blk_id),
);
if !fcx.tcx.features().unsized_locals {
unsized_return = self.is_return_ty_unsized(fcx, blk_id);
unsized_return = self.is_return_ty_definitely_unsized(fcx);
}
if let Some(expression) = expression
&& let hir::ExprKind::Loop(loop_blk, ..) = expression.kind {
Expand All @@ -1614,8 +1614,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
None,
);
if !fcx.tcx.features().unsized_locals {
let id = fcx.tcx.hir().parent_id(id);
unsized_return = self.is_return_ty_unsized(fcx, id);
unsized_return = self.is_return_ty_definitely_unsized(fcx);
}
}
_ => {
Expand Down Expand Up @@ -1896,15 +1895,24 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
err.help("you could instead create a new `enum` with a variant for each returned type");
}

fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
if let Some((_, fn_decl, _)) = fcx.get_fn_decl(blk_id)
&& let hir::FnRetTy::Return(ty) = fn_decl.output
&& let ty = fcx.astconv().ast_ty_to_ty( ty)
&& let ty::Dynamic(..) = ty.kind()
{
return true;
/// 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.
fn is_return_ty_definitely_unsized(&self, fcx: &FnCtxt<'_, 'tcx>) -> bool {
if let Some(sig) = fcx.body_fn_sig() {
!fcx.predicate_may_hold(&Obligation::new(
fcx.tcx,
ObligationCause::dummy(),
fcx.param_env,
ty::TraitRef::new(
fcx.tcx,
fcx.tcx.require_lang_item(hir::LangItem::Sized, None),
[sig.output()],
),
))
} else {
false
}
false
}

pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder,
ErrorGuaranteed, MultiSpan, Style,
ErrorGuaranteed, MultiSpan, Style, SuggestionStyle,
};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
Expand Down Expand Up @@ -362,6 +362,15 @@ pub trait TypeErrCtxtExt<'tcx> {
err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
);

fn suggest_option_method_if_applicable(
&self,
failed_pred: ty::Predicate<'tcx>,
param_env: ty::ParamEnv<'tcx>,
err: &mut Diagnostic,
expr: &hir::Expr<'_>,
);

fn note_function_argument_obligation(
&self,
body_id: LocalDefId,
Expand Down Expand Up @@ -3521,15 +3530,92 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.replace_span_with(path.ident.span, true);
}
}
if let Some(Node::Expr(hir::Expr {
kind:
hir::ExprKind::Call(hir::Expr { span, .. }, _)
| hir::ExprKind::MethodCall(hir::PathSegment { ident: Ident { span, .. }, .. }, ..),
..
})) = hir.find(call_hir_id)

if let Some(Node::Expr(expr)) = hir.find(call_hir_id) {
if let hir::ExprKind::Call(hir::Expr { span, .. }, _)
| hir::ExprKind::MethodCall(
hir::PathSegment { ident: Ident { span, .. }, .. },
..,
) = expr.kind
{
if Some(*span) != err.span.primary_span() {
err.span_label(*span, "required by a bound introduced by this call");
}
}

if let hir::ExprKind::MethodCall(_, expr, ..) = expr.kind {
self.suggest_option_method_if_applicable(failed_pred, param_env, err, expr);
}
}
}

fn suggest_option_method_if_applicable(
&self,
failed_pred: ty::Predicate<'tcx>,
param_env: ty::ParamEnv<'tcx>,
err: &mut Diagnostic,
expr: &hir::Expr<'_>,
) {
let tcx = self.tcx;
let infcx = self.infcx;
let Some(typeck_results) = self.typeck_results.as_ref() else { return };

// Make sure we're dealing with the `Option` type.
let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else { return };
if !tcx.is_diagnostic_item(sym::Option, option_ty_adt.did()) {
return;
}

// Given the predicate `fn(&T): FnOnce<(U,)>`, extract `fn(&T)` and `(U,)`,
// then suggest `Option::as_deref(_mut)` if `U` can deref to `T`
if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate { trait_ref, .. }))
= failed_pred.kind().skip_binder()
&& tcx.is_fn_trait(trait_ref.def_id)
&& let [self_ty, found_ty] = trait_ref.substs.as_slice()
&& let Some(fn_ty) = self_ty.as_type().filter(|ty| ty.is_fn())
&& let fn_sig @ ty::FnSig {
abi: abi::Abi::Rust,
c_variadic: false,
unsafety: hir::Unsafety::Normal,
..
} = fn_ty.fn_sig(tcx).skip_binder()

// Extract first param of fn sig with peeled refs, e.g. `fn(&T)` -> `T`
&& let Some(&ty::Ref(_, target_ty, needs_mut)) = fn_sig.inputs().first().map(|t| t.kind())
&& !target_ty.has_escaping_bound_vars()

// Extract first tuple element out of fn trait, e.g. `FnOnce<(U,)>` -> `U`
&& let Some(ty::Tuple(tys)) = found_ty.as_type().map(Ty::kind)
&& let &[found_ty] = tys.as_slice()
&& !found_ty.has_escaping_bound_vars()

// Extract `<U as Deref>::Target` assoc type and check that it is `T`
&& let Some(deref_target_did) = tcx.lang_items().deref_target()
&& let projection = tcx.mk_projection(deref_target_did, tcx.mk_substs(&[ty::GenericArg::from(found_ty)]))
&& let Ok(deref_target) = tcx.try_normalize_erasing_regions(param_env, projection)
&& deref_target == target_ty
{
if Some(*span) != err.span.primary_span() {
err.span_label(*span, "required by a bound introduced by this call");
let help = if let hir::Mutability::Mut = needs_mut
&& let Some(deref_mut_did) = tcx.lang_items().deref_mut_trait()
&& infcx
.type_implements_trait(deref_mut_did, iter::once(found_ty), param_env)
.must_apply_modulo_regions()
{
Some(("call `Option::as_deref_mut()` first", ".as_deref_mut()"))
} else if let hir::Mutability::Not = needs_mut {
Some(("call `Option::as_deref()` first", ".as_deref()"))
} else {
None
};

if let Some((msg, sugg)) = help {
err.span_suggestion_with_style(
expr.span.shrink_to_hi(),
msg,
sugg,
Applicability::MaybeIncorrect,
SuggestionStyle::ShowAlways
);
}
}
}
Expand Down
21 changes: 20 additions & 1 deletion library/core/src/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,7 @@ impl<T> Option<T> {
/// Computes a default function result (if none), or
/// applies a different function to the contained value (if any).
///
/// # Examples
/// # Basic examples
///
/// ```
/// let k = 21;
Expand All @@ -1149,6 +1149,25 @@ impl<T> Option<T> {
/// let x: Option<&str> = None;
/// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
/// ```
///
/// # Handling a Result-based fallback
///
/// A somewhat common occurrence when dealing with optional values
/// in combination with [`Result<T, E>`] is the case where one wants to invoke
/// a fallible fallback if the option is not present. This example
/// parses a command line argument (if present), or the contents of a file to
/// an integer. However, unlike accessing the command line argument, reading
/// the file is fallible, so it must be wrapped with `Ok`.
///
/// ```no_run
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let v: u64 = std::env::args()
/// .nth(1)
/// .map_or_else(|| std::fs::read_to_string("/etc/someconfig.conf"), Ok)?
/// .parse()?;
/// # Ok(())
/// # }
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
Expand Down
7 changes: 7 additions & 0 deletions src/bootstrap/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dependencies = [
"once_cell",
"opener",
"pretty_assertions",
"semver",
"serde",
"serde_derive",
"serde_json",
Expand Down Expand Up @@ -645,6 +646,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"

[[package]]
name = "semver"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"

[[package]]
name = "serde"
version = "1.0.160"
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ walkdir = "2"
sysinfo = { version = "0.26.0", optional = true }
clap = { version = "4.2.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
clap_complete = "4.2.2"
semver = "1.0.17"

# Solaris doesn't support flock() and thus fd-lock is not option now
[target.'cfg(not(target_os = "solaris"))'.dependencies]
Expand Down
4 changes: 4 additions & 0 deletions src/bootstrap/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ clean_crate_tree! {
}

fn clean_default(build: &Build, all: bool) {
if build.config.dry_run() {
return;
}

rm_rf("tmp".as_ref());

if all {
Expand Down
45 changes: 43 additions & 2 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::flags::{Color, Flags, Warnings};
use crate::util::{exe, output, t};
use build_helper::detail_exit_macro;
use once_cell::sync::OnceCell;
use semver::Version;
use serde::{Deserialize, Deserializer};
use serde_derive::Deserialize;

Expand Down Expand Up @@ -1114,10 +1115,14 @@ impl Config {
config.out = crate::util::absolute(&config.out);
}

config.initial_rustc = build.rustc.map(PathBuf::from).unwrap_or_else(|| {
config.initial_rustc = if let Some(rustc) = build.rustc {
config.check_build_rustc_version(&rustc);
PathBuf::from(rustc)
} else {
config.download_beta_toolchain();
config.out.join(config.build.triple).join("stage0/bin/rustc")
});
};

config.initial_cargo = build
.cargo
.map(|cargo| {
Expand Down Expand Up @@ -1779,6 +1784,42 @@ impl Config {
self.rust_codegen_backends.get(0).cloned()
}

pub fn check_build_rustc_version(&self, rustc_path: &str) {
if self.dry_run() {
return;
}

// check rustc version is same or lower with 1 apart from the building one
let mut cmd = Command::new(rustc_path);
cmd.arg("--version");
let rustc_output = output(&mut cmd)
.lines()
.next()
.unwrap()
.split(' ')
.nth(1)
.unwrap()
.split('-')
.next()
.unwrap()
.to_owned();
let rustc_version = Version::parse(&rustc_output.trim()).unwrap();
let source_version =
Version::parse(&fs::read_to_string(self.src.join("src/version")).unwrap().trim())
.unwrap();
if !(source_version == rustc_version
|| (source_version.major == rustc_version.major
&& source_version.minor == rustc_version.minor + 1))
{
let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1);
eprintln!(
"Unexpected rustc version: {}, we should use {}/{} to build source with {}",
rustc_version, prev_version, source_version, source_version
);
detail_exit_macro!(1);
}
}

/// Returns the commit to download, or `None` if we shouldn't download CI artifacts.
fn download_ci_rustc_commit(&self, download_rustc: Option<StringOrBool>) -> Option<String> {
// If `download-rustc` is not set, default to rebuilding.
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static SETTINGS_HASHES: &[&str] = &[
"ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
"56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922",
"af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
];
static RUST_ANALYZER_SETTINGS: &str = include_str!("../etc/rust_analyzer_settings.json");

Expand Down
9 changes: 8 additions & 1 deletion src/etc/rust_analyzer_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@
"check",
"--json-output"
],
"rust-analyzer.linkedProjects": ["src/bootstrap/Cargo.toml", "Cargo.toml"],
"rust-analyzer.linkedProjects": [
"Cargo.toml",
"src/tools/x/Cargo.toml",
"src/bootstrap/Cargo.toml",
"src/tools/rust-analyzer/Cargo.toml",
"compiler/rustc_codegen_cranelift/Cargo.toml",
"compiler/rustc_codegen_gcc/Cargo.toml"
],
"rust-analyzer.rustfmt.overrideCommand": [
"./build/host/rustfmt/bin/rustfmt",
"--edition=2021"
Expand Down
4 changes: 3 additions & 1 deletion src/tools/x/Cargo.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3

[[package]]
name = "x"
version = "0.1.0"
version = "0.1.1"
2 changes: 1 addition & 1 deletion tests/codegen/box-maybe-uninit-llvm14.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
// Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc
// from the CHECK-NOT above. We don't check the attributes here because we can't rely
// on all of them being set until LLVM 15.
// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)
// CHECK: declare {{(dso_local )?}}noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)
4 changes: 2 additions & 2 deletions tests/codegen/box-maybe-uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {

// Hide the `allocalign` attribute in the declaration of __rust_alloc
// from the CHECK-NOT above, and also verify the attributes got set reasonably.
// CHECK: declare noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
// CHECK: declare {{(dso_local )?}}noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]

// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} }
2 changes: 1 addition & 1 deletion tests/codegen/call-metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#![crate_type = "lib"]

pub fn test() {
// CHECK: call noundef i8 @some_true(), !range [[R0:![0-9]+]]
// CHECK: call noundef i8 @some_true(){{( #[0-9]+)?}}, !range [[R0:![0-9]+]]
// CHECK: [[R0]] = !{i8 0, i8 3}
some_true();
}
Expand Down
4 changes: 2 additions & 2 deletions tests/codegen/debug-column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
fn main() {
unsafe {
// Column numbers are 1-based. Regression test for #65437.
// CHECK: call void @giraffe(), !dbg [[A:!.*]]
// CHECK: call void @giraffe(){{( #[0-9]+)?}}, !dbg [[A:!.*]]
giraffe();

// Column numbers use byte offests. Regression test for #67360
// CHECK: call void @turtle(), !dbg [[B:!.*]]
// CHECK: call void @turtle(){{( #[0-9]+)?}}, !dbg [[B:!.*]]
/* ż */ turtle();

// CHECK: [[A]] = !DILocation(line: 10, column: 9,
Expand Down
1 change: 1 addition & 0 deletions tests/codegen/drop.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// ignore-wasm32-bare compiled with panic=abort by default
// needs-unwind - this test verifies the amount of drop calls when unwinding is used
// compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]
Expand Down
Loading

0 comments on commit 398fa21

Please sign in to comment.