From b142720322155ddb5aa4cac8b01ab5633b4cc854 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Wed, 9 Mar 2022 13:53:16 -0800 Subject: [PATCH 001/267] Document NonZeroXxx layout guarantees Document that `NonZeroXxx` has the same layout and bit validity as `Xxx` with the exception of `0`. --- library/core/src/num/nonzero.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1ebd1c58f2b5..8b247daf8a7a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -34,6 +34,11 @@ macro_rules! nonzero_integers { /// use std::mem::size_of; #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] /// ``` + /// + /// # Layout + /// + #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`"] + /// with the exception that `0` is not a valid instance. #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] From 7f88cd20ff5d3616b7bab5a4b3b0c942e91904a9 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Wed, 9 Mar 2022 14:00:08 -0800 Subject: [PATCH 002/267] Add missing closing parenthesis --- library/core/src/num/nonzero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 8b247daf8a7a..1e5cfdd56cac 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -37,7 +37,7 @@ macro_rules! nonzero_integers { /// /// # Layout /// - #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`"] + #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] /// with the exception that `0` is not a valid instance. #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] From 7d4e9b3637320be8d4f2efe350cd71b9312e9d83 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Wed, 5 Oct 2022 09:40:50 -0700 Subject: [PATCH 003/267] Update library/core/src/num/nonzero.rs Co-authored-by: Josh Triplett --- library/core/src/num/nonzero.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1e5cfdd56cac..df438f88ceea 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -39,6 +39,8 @@ macro_rules! nonzero_integers { /// #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] /// with the exception that `0` is not a valid instance. + #[doc = concat!("`Option<", stringify!($Ty), "` is guaranteed to be compatible with `", stringify!($Int), "`," + /// including in FFI. #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] From 8323d6abfca91c73217adf13d6313dbad7adfd69 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Wed, 5 Oct 2022 09:41:57 -0700 Subject: [PATCH 004/267] Fix typo (missing `>`) --- library/core/src/num/nonzero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index df438f88ceea..c45eb66b0e9d 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -39,7 +39,7 @@ macro_rules! nonzero_integers { /// #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] /// with the exception that `0` is not a valid instance. - #[doc = concat!("`Option<", stringify!($Ty), "` is guaranteed to be compatible with `", stringify!($Int), "`," + #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`," /// including in FFI. #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] From 9a3346bcdd23d299f9b45236cfda7d4de0ea640a Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Wed, 5 Oct 2022 10:07:26 -0700 Subject: [PATCH 005/267] Add missing trailing `)]` --- library/core/src/num/nonzero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index c45eb66b0e9d..e011a0945e2c 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -39,7 +39,7 @@ macro_rules! nonzero_integers { /// #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] /// with the exception that `0` is not a valid instance. - #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`," + #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] /// including in FFI. #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] From b7a5f3a41c6613033f0e6be9307c40e3174a9381 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 7 Mar 2023 05:40:55 +0000 Subject: [PATCH 006/267] Instantiate instead of erasing binder when probing param methods --- compiler/rustc_hir_typeck/src/method/probe.rs | 27 ++++++++++++------- .../non_lifetime_binders/method-probe.rs | 16 +++++++++++ .../non_lifetime_binders/method-probe.stderr | 11 ++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 tests/ui/traits/non_lifetime_binders/method-probe.rs create mode 100644 tests/ui/traits/non_lifetime_binders/method-probe.stderr diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 3bef5cfcd780..2c8c9ed69d31 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -792,6 +792,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // a `&self` method will wind up with an argument type like `&dyn Trait`. let trait_ref = principal.with_self_ty(self.tcx, self_ty); self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| { + if new_trait_ref.has_non_region_late_bound() { + this.tcx.sess.delay_span_bug( + this.span, + "tried to select method from HRTB with non-lifetime bound vars", + ); + return; + } + let new_trait_ref = this.erase_late_bound_regions(new_trait_ref); let (xform_self_ty, xform_ret_ty) = @@ -842,18 +850,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }); self.elaborate_bounds(bounds, |this, poly_trait_ref, item| { - let trait_ref = this.erase_late_bound_regions(poly_trait_ref); + let trait_ref = this.instantiate_binder_with_fresh_vars( + this.span, + infer::LateBoundRegionConversionTime::FnCall, + poly_trait_ref, + ); let (xform_self_ty, xform_ret_ty) = this.xform_self_ty(item, trait_ref.self_ty(), trait_ref.substs); - // Because this trait derives from a where-clause, it - // should not contain any inference variables or other - // artifacts. This means it is safe to put into the - // `WhereClauseCandidate` and (eventually) into the - // `WhereClausePick`. - assert!(!trait_ref.substs.needs_infer()); - this.push_candidate( Candidate { xform_self_ty, @@ -963,7 +968,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { bound_trait_ref.def_id(), )); } else { - let new_trait_ref = self.erase_late_bound_regions(bound_trait_ref); + let new_trait_ref = self.instantiate_binder_with_fresh_vars( + self.span, + infer::LateBoundRegionConversionTime::FnCall, + bound_trait_ref, + ); let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.substs); diff --git a/tests/ui/traits/non_lifetime_binders/method-probe.rs b/tests/ui/traits/non_lifetime_binders/method-probe.rs new file mode 100644 index 000000000000..8df240c2082b --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/method-probe.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Foo: for Bar {} + +trait Bar { + fn method() -> T; +} + +fn x() { + let _: i32 = T::method(); +} + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/method-probe.stderr b/tests/ui/traits/non_lifetime_binders/method-probe.stderr new file mode 100644 index 000000000000..8f61792e6ce7 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/method-probe.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/method-probe.rs:3:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + From a860a720baa508aa28d44f4d277814a086d6bd9d Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 20 Mar 2023 22:48:26 +0800 Subject: [PATCH 007/267] Fix issue when there are multiple candidates for edit_distance_with_substrings --- compiler/rustc_span/src/edit_distance.rs | 24 ++++++++++++++++++++---- tests/ui/suggestions/issue-109291.rs | 4 ++++ tests/ui/suggestions/issue-109291.stderr | 12 ++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 tests/ui/suggestions/issue-109291.rs create mode 100644 tests/ui/suggestions/issue-109291.stderr diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs index 89f0386e3e97..40d36578350a 100644 --- a/compiler/rustc_span/src/edit_distance.rs +++ b/compiler/rustc_span/src/edit_distance.rs @@ -174,10 +174,10 @@ pub fn find_best_match_for_name( fn find_best_match_for_name_impl( use_substring_score: bool, candidates: &[Symbol], - lookup: Symbol, + lookup_symbol: Symbol, dist: Option, ) -> Option { - let lookup = lookup.as_str(); + let lookup = lookup_symbol.as_str(); let lookup_uppercase = lookup.to_uppercase(); // Priority of matches: @@ -190,6 +190,7 @@ fn find_best_match_for_name_impl( let mut dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3); let mut best = None; + let mut next_candidates = vec![]; for c in candidates { match if use_substring_score { edit_distance_with_substrings(lookup, c.as_str(), dist) @@ -198,12 +199,27 @@ fn find_best_match_for_name_impl( } { Some(0) => return Some(*c), Some(d) => { - dist = d - 1; - best = Some(*c); + if use_substring_score { + dist = d; + next_candidates.push(*c); + best = Some(*c); + } else { + dist = d - 1; + best = Some(*c); + } } None => {} } } + + if next_candidates.len() > 1 { + best = find_best_match_for_name_impl( + false, + &next_candidates, + lookup_symbol, + Some(lookup.len()), + ); + } if best.is_some() { return best; } diff --git a/tests/ui/suggestions/issue-109291.rs b/tests/ui/suggestions/issue-109291.rs new file mode 100644 index 000000000000..1947b16a32e6 --- /dev/null +++ b/tests/ui/suggestions/issue-109291.rs @@ -0,0 +1,4 @@ +fn main() { + println!("Custom backtrace: {}", std::backtrace::Backtrace::forced_capture()); + //~^ ERROR no function or associated item name +} diff --git a/tests/ui/suggestions/issue-109291.stderr b/tests/ui/suggestions/issue-109291.stderr new file mode 100644 index 000000000000..4ef5948d9bf2 --- /dev/null +++ b/tests/ui/suggestions/issue-109291.stderr @@ -0,0 +1,12 @@ +error[E0599]: no function or associated item named `forced_capture` found for struct `Backtrace` in the current scope + --> $DIR/issue-109291.rs:2:65 + | +LL | println!("Custom backtrace: {}", std::backtrace::Backtrace::forced_capture()); + | ^^^^^^^^^^^^^^ + | | + | function or associated item not found in `Backtrace` + | help: there is an associated function with a similar name: `force_capture` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 2005e300c0266a6527dbfcb573a86c65d043f72f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 25 Mar 2023 09:23:05 -0700 Subject: [PATCH 008/267] tests: make directory for use redundant lint --- tests/ui/lint/{ => use-redundant}/use-redundant.rs | 0 tests/ui/lint/{ => use-redundant}/use-redundant.stderr | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/lint/{ => use-redundant}/use-redundant.rs (100%) rename tests/ui/lint/{ => use-redundant}/use-redundant.stderr (100%) diff --git a/tests/ui/lint/use-redundant.rs b/tests/ui/lint/use-redundant/use-redundant.rs similarity index 100% rename from tests/ui/lint/use-redundant.rs rename to tests/ui/lint/use-redundant/use-redundant.rs diff --git a/tests/ui/lint/use-redundant.stderr b/tests/ui/lint/use-redundant/use-redundant.stderr similarity index 100% rename from tests/ui/lint/use-redundant.stderr rename to tests/ui/lint/use-redundant/use-redundant.stderr From 7b4f436a30f00c8b8bf533b92592385cba2ea5f1 Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 26 Mar 2023 12:03:25 +0800 Subject: [PATCH 009/267] add comments and cleanup --- compiler/rustc_span/src/edit_distance.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs index 40d36578350a..19c4aae97efe 100644 --- a/compiler/rustc_span/src/edit_distance.rs +++ b/compiler/rustc_span/src/edit_distance.rs @@ -190,6 +190,7 @@ fn find_best_match_for_name_impl( let mut dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3); let mut best = None; + // store the candidates with the same distance, only for `use_substring_score` current. let mut next_candidates = vec![]; for c in candidates { match if use_substring_score { @@ -200,19 +201,25 @@ fn find_best_match_for_name_impl( Some(0) => return Some(*c), Some(d) => { if use_substring_score { - dist = d; + if d < dist { + dist = d; + next_candidates.clear(); + } else { + // `d == dist` here, we need to store the candidates with the same distance + // so we won't decrease the distance in the next loop. + } next_candidates.push(*c); - best = Some(*c); } else { dist = d - 1; - best = Some(*c); } + best = Some(*c); } None => {} } } if next_candidates.len() > 1 { + debug_assert!(use_substring_score); best = find_best_match_for_name_impl( false, &next_candidates, From 47d7dd0c0ca1f72d702220ed227cd2167ab814b0 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sat, 4 Feb 2023 20:34:26 -0800 Subject: [PATCH 010/267] Add QNX 7.0 x86 target --- .../src/spec/aarch64_unknown_nto_qnx_710.rs | 1 + .../src/spec/i586_pc_nto_qnx700.rs | 24 +++++++++++++++++++ compiler/rustc_target/src/spec/mod.rs | 1 + .../rustc_target/src/spec/nto_qnx_base.rs | 1 - .../src/spec/x86_64_pc_nto_qnx710.rs | 1 + src/doc/rustc/src/platform-support.md | 1 + src/doc/rustc/src/platform-support/nto-qnx.md | 15 +++++++++--- 7 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs index 8c1126ae6d1c..630642dcd33a 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs @@ -23,6 +23,7 @@ pub fn target() -> Target { LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Vgcc_ntoaarch64le_cxx"], ), + env: "nto71".into(), ..nto_qnx_base::opts() }, } diff --git a/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs new file mode 100644 index 000000000000..68afa7fe4012 --- /dev/null +++ b/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs @@ -0,0 +1,24 @@ +use super::nto_qnx_base; +use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "i586-pc-unknown".into(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ + f64:32:64-f80:32-n8:16:32-S128" + .into(), + arch: "x86".into(), + options: TargetOptions { + cpu: "pentium4".into(), + max_atomic_width: Some(64), + pre_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-Vgcc_ntox86_cxx"], + ), + env: "nto70".into(), + stack_probes: StackProbeType::X86, + ..nto_qnx_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index bb45fb125b24..62c58c204e09 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1261,6 +1261,7 @@ supported_targets! { ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx_710), ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710), + ("i586-pc-nto-qnx700", i586_pc_nto_qnx700), ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos), ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos), diff --git a/compiler/rustc_target/src/spec/nto_qnx_base.rs b/compiler/rustc_target/src/spec/nto_qnx_base.rs index 6fb581ef5ce3..f1405e9b4466 100644 --- a/compiler/rustc_target/src/spec/nto_qnx_base.rs +++ b/compiler/rustc_target/src/spec/nto_qnx_base.rs @@ -4,7 +4,6 @@ pub fn opts() -> TargetOptions { TargetOptions { crt_static_respected: true, dynamic_linking: true, - env: "nto71".into(), executables: true, families: cvs!["unix"], has_rpath: true, diff --git a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs index e9b3acee2e7f..6fb2dfd807a0 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs @@ -15,6 +15,7 @@ pub fn target() -> Target { LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Vgcc_ntox86_64_cxx"], ), + env: "nto71".into(), ..nto_qnx_base::opts() }, } diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 5c18a38ddab9..67fe2a610c22 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -257,6 +257,7 @@ target | std | host | notes `bpfel-unknown-none` | * | | BPF (little endian) `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS +[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS | `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+) `i686-pc-windows-msvc` | * | | 32-bit Windows XP support `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 38198fe6c3a0..0d815c9b5980 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -16,10 +16,18 @@ and [Blackberry QNX][BlackBerry]. ## Requirements -Currently, only cross-compilation for QNX Neutrino on AArch64 and x86_64 are supported (little endian). +Currently, the following QNX Neutrino versions and compilation targets are supported: + +| QNX Neutrino Version | Target Architecture | Full support | `no_std` support | +|----------------------|---------------------|:------------:|:----------------:| +| 7.1 | AArch64 | ✓ | ✓ | +| 7.1 | x86_64 | ✓ | ✓ | +| 7.0 | x86 | | ✓ | + Adding other architectures that are supported by QNX Neutrino is possible. -The standard library, including `core` and `alloc` (with default allocator) are supported. +In the table above, 'full support' indicates support for building Rust applications with the full standard library. +'`no_std` support' indicates that only `core` and `alloc` are available. For building or using the Rust toolchain for QNX Neutrino, the [QNX Software Development Platform (SDP)](https://blackberry.qnx.com/en/products/foundation-software/qnx-software-development-platform) @@ -70,7 +78,7 @@ fn panic(_panic: &PanicInfo<'_>) -> ! { pub extern "C" fn rust_eh_personality() {} ``` -The QNX Neutrino support of Rust has been tested with QNX Neutrino 7.1. +The QNX Neutrino support of Rust has been tested with QNX Neutrino 7.0 and 7.1. There are no further known requirements. @@ -80,6 +88,7 @@ For conditional compilation, following QNX Neutrino specific attributes are defi - `target_os` = `"nto"` - `target_env` = `"nto71"` (for QNX Neutrino 7.1) +- `target_env` = `"nto70"` (for QNX Neutrino 7.0) ## Building the target From ccc563a7d7ab6addb8df453df760da685e53d737 Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Thu, 30 Mar 2023 10:19:54 +0800 Subject: [PATCH 011/267] AIX uses gmake for GNU style Makefile --- src/tools/compiletest/src/runtest.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a40030723105..b1cb947ef88f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2996,6 +2996,7 @@ impl<'test> TestCx<'test> { || host.contains("freebsd") || host.contains("netbsd") || host.contains("openbsd") + || host.contains("aix") { "gmake" } else { From 3b38dd91126a647334af07d772ad809422918e5a Mon Sep 17 00:00:00 2001 From: Maciej Wasilewski <52935969+MaciejWas@users.noreply.github.com> Date: Thu, 30 Mar 2023 10:35:06 +0200 Subject: [PATCH 012/267] better diagnostics for pattern matching tuple structs Better diagnostic message when trying to pattern match a tuple struct with a struct pattern. --- compiler/rustc_hir_typeck/src/pat.rs | 23 +++++++++++++++++-- tests/ui/structs/struct-tuple-field-names.rs | 3 +++ .../structs/struct-tuple-field-names.stderr | 20 ++++++++++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 11ff65d0c373..0160bce86042 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -36,6 +36,10 @@ pointers. If you encounter this error you should try to avoid dereferencing the You can read more about trait objects in the Trait Objects section of the Reference: \ https://doc.rust-lang.org/reference/types.html#trait-objects"; +fn is_number(text: &str) -> bool { + text.chars().all(|c: char| c.is_digit(10)) +} + /// Information about the expected type at the top level of type checking a pattern. /// /// **NOTE:** This is only for use by diagnostics. Do NOT use for type checking logic! @@ -1671,7 +1675,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fields: &'tcx [hir::PatField<'tcx>], variant: &ty::VariantDef, ) -> Option> { - if let (Some(CtorKind::Fn), PatKind::Struct(qpath, ..)) = (variant.ctor_kind(), &pat.kind) { + if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) = + (variant.ctor_kind(), &pat.kind) + { + let is_tuple_struct_match = !pattern_fields.is_empty() + && pattern_fields.iter().map(|field| field.ident.name.as_str()).all(is_number); + if is_tuple_struct_match { + return None; + } + let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| { s.print_qpath(qpath, false) }); @@ -1893,7 +1905,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { prefix, unmentioned_fields .iter() - .map(|(_, name)| name.to_string()) + .map(|(_, name)| { + let field_name = name.to_string(); + if is_number(&field_name) { + format!("{}: _", field_name) + } else { + field_name + } + }) .collect::>() .join(", "), if have_inaccessible_fields { ", .." } else { "" }, diff --git a/tests/ui/structs/struct-tuple-field-names.rs b/tests/ui/structs/struct-tuple-field-names.rs index 7bd54af1dbee..33f264aa2509 100644 --- a/tests/ui/structs/struct-tuple-field-names.rs +++ b/tests/ui/structs/struct-tuple-field-names.rs @@ -12,4 +12,7 @@ fn main() { match y { S { } => {} //~ ERROR: tuple variant `S` written as struct variant [E0769] } + + if let E::S { 0: a } = x { //~ ERROR: pattern does not mention field `1` + } } diff --git a/tests/ui/structs/struct-tuple-field-names.stderr b/tests/ui/structs/struct-tuple-field-names.stderr index 5494c29a6fd2..0b837a47a825 100644 --- a/tests/ui/structs/struct-tuple-field-names.stderr +++ b/tests/ui/structs/struct-tuple-field-names.stderr @@ -20,6 +20,22 @@ help: use the tuple variant pattern syntax instead LL | S(_, _) => {} | ~~~~~~ -error: aborting due to 2 previous errors +error[E0027]: pattern does not mention field `1` + --> $DIR/struct-tuple-field-names.rs:16:12 + | +LL | if let E::S { 0: a } = x { + | ^^^^^^^^^^^^^ missing field `1` + | +help: include the missing field in the pattern + | +LL | if let E::S { 0: a, 1: _ } = x { + | ~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | if let E::S { 0: a, .. } = x { + | ~~~~~~ -For more information about this error, try `rustc --explain E0769`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0027, E0769. +For more information about an error, try `rustc --explain E0027`. From b85fcf51d2a08a362fbcca69b9d61316873a3171 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Mar 2023 13:28:41 +0200 Subject: [PATCH 013/267] Remove mention of `missing_doc_code_examples` lint from rustdoc book --- src/doc/rustdoc/src/unstable-features.md | 9 +++++++++ .../rustdoc/src/write-documentation/what-to-include.md | 4 +--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index b8b5014ab42e..1f9133aef122 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -38,6 +38,15 @@ future. Attempting to use these error numbers on stable will result in the code sample being interpreted as plain text. +### `missing_doc_code_examples` lint + +This lint will emit a warning if an item doesn't have a code example in its documentation. +It can be enabled using: + +```rust,ignore (nightly) +#![deny(rustdoc::missing_doc_code_examples)] +``` + ## Extensions to the `#[doc]` attribute These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler diff --git a/src/doc/rustdoc/src/write-documentation/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md index cf1e6a8d3ca4..16457ed0ff82 100644 --- a/src/doc/rustdoc/src/write-documentation/what-to-include.md +++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md @@ -39,9 +39,7 @@ warning: 1 warning emitted As a library author, adding the lint `#![deny(missing_docs)]` is a great way to ensure the project does not drift away from being documented well, and `#![warn(missing_docs)]` is a good way to move towards comprehensive -documentation. In addition to docs, `#![deny(rustdoc::missing_doc_code_examples)]` -ensures each function contains a usage example. In our example above, the -warning is resolved by adding crate level documentation. +documentation. There are more lints in the upcoming chapter [Lints][rustdoc-lints]. From 6975b77e3b170902e66bfd2b411624b1b1ba23e9 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 30 Mar 2023 17:09:24 +0000 Subject: [PATCH 014/267] Add a test for issue 109396 --- tests/ui/argument-suggestions/issue-109425.rs | 18 ++++ .../argument-suggestions/issue-109425.stderr | 98 +++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 tests/ui/argument-suggestions/issue-109425.rs create mode 100644 tests/ui/argument-suggestions/issue-109425.stderr diff --git a/tests/ui/argument-suggestions/issue-109425.rs b/tests/ui/argument-suggestions/issue-109425.rs new file mode 100644 index 000000000000..2b92b6dccd7b --- /dev/null +++ b/tests/ui/argument-suggestions/issue-109425.rs @@ -0,0 +1,18 @@ +fn f() {} +fn i(_: u32) {} +fn is(_: u32, _: &str) {} +fn s(_: &str) {} + +fn main() { + // code expected suggestion + f(0, 1,); // f() + //~^ error: this function takes 0 arguments but 2 arguments were supplied + i(0, 1, 2,); // i(0,) + //~^ error: this function takes 1 argument but 3 arguments were supplied + i(0, 1, 2); // i(0) + //~^ error: this function takes 1 argument but 3 arguments were supplied + is(0, 1, 2, ""); // is(0, "") + //~^ error: this function takes 2 arguments but 4 arguments were supplied + s(0, 1, ""); // s("") + //~^ error: this function takes 1 argument but 3 arguments were supplied +} diff --git a/tests/ui/argument-suggestions/issue-109425.stderr b/tests/ui/argument-suggestions/issue-109425.stderr new file mode 100644 index 000000000000..59febb682220 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-109425.stderr @@ -0,0 +1,98 @@ +error[E0061]: this function takes 0 arguments but 2 arguments were supplied + --> $DIR/issue-109425.rs:8:5 + | +LL | f(0, 1,); // f() + | ^ - - unexpected argument of type `{integer}` + | | + | unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/issue-109425.rs:1:4 + | +LL | fn f() {} + | ^ +help: remove the extra arguments + | +LL - f(0, 1,); // f() +LL + f(,); // f() + | + +error[E0061]: this function takes 1 argument but 3 arguments were supplied + --> $DIR/issue-109425.rs:10:5 + | +LL | i(0, 1, 2,); // i(0,) + | ^ - - unexpected argument of type `{integer}` + | | + | unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/issue-109425.rs:2:4 + | +LL | fn i(_: u32) {} + | ^ ------ +help: remove the extra arguments + | +LL - i(0, 1, 2,); // i(0,) +LL + i(0,); // i(0,) + | + +error[E0061]: this function takes 1 argument but 3 arguments were supplied + --> $DIR/issue-109425.rs:12:5 + | +LL | i(0, 1, 2); // i(0) + | ^ - - unexpected argument of type `{integer}` + | | + | unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/issue-109425.rs:2:4 + | +LL | fn i(_: u32) {} + | ^ ------ +help: remove the extra arguments + | +LL - i(0, 1, 2); // i(0) +LL + i(0); // i(0) + | + +error[E0061]: this function takes 2 arguments but 4 arguments were supplied + --> $DIR/issue-109425.rs:14:5 + | +LL | is(0, 1, 2, ""); // is(0, "") + | ^^ - - unexpected argument of type `{integer}` + | | + | unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/issue-109425.rs:3:4 + | +LL | fn is(_: u32, _: &str) {} + | ^^ ------ ------- +help: remove the extra arguments + | +LL - is(0, 1, 2, ""); // is(0, "") +LL + is(0, ""); // is(0, "") + | + +error[E0061]: this function takes 1 argument but 3 arguments were supplied + --> $DIR/issue-109425.rs:16:5 + | +LL | s(0, 1, ""); // s("") + | ^ - - unexpected argument of type `{integer}` + | | + | unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/issue-109425.rs:4:4 + | +LL | fn s(_: &str) {} + | ^ ------- +help: remove the extra arguments + | +LL - s(0, 1, ""); // s("") +LL + s(, ""); // s("") + | + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0061`. From b9d5a6b709be1e21961f2a867d6e6542ffa557f2 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 30 Mar 2023 17:11:06 +0000 Subject: [PATCH 015/267] Don't leave a comma at the start of argument list when removing arguments --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 44 ++++++++++++++++--- .../argument-suggestions/issue-109425.fixed | 20 +++++++++ tests/ui/argument-suggestions/issue-109425.rs | 2 + .../argument-suggestions/issue-109425.stderr | 24 +++++----- tests/ui/suggestions/issue-109396.stderr | 2 +- 5 files changed, 73 insertions(+), 19 deletions(-) create mode 100644 tests/ui/argument-suggestions/issue-109425.fixed diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 61338ac613ae..bb1063538b41 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -21,7 +21,7 @@ use rustc_hir_analysis::astconv::AstConv; use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt; use rustc_hir_analysis::check::potentially_plural_count; use rustc_hir_analysis::structured_errors::StructuredDiagnostic; -use rustc_index::vec::IndexVec; +use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::TypeTrace; @@ -31,7 +31,7 @@ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, IsSuggestable, Ty}; use rustc_session::Session; use rustc_span::symbol::{kw, Ident}; -use rustc_span::{self, sym, Span}; +use rustc_span::{self, sym, BytePos, Span}; use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}; use std::iter; @@ -894,8 +894,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut errors = errors.into_iter().peekable(); + let mut only_extras_so_far = errors + .peek() + .map_or(false, |first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0)); let mut suggestions = vec![]; while let Some(error) = errors.next() { + only_extras_so_far &= matches!(error, Error::Extra(_)); + match error { Error::Invalid(provided_idx, expected_idx, compatibility) => { let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx]; @@ -941,10 +946,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if arg_idx.index() > 0 && let Some((_, prev)) = provided_arg_tys .get(ProvidedIdx::from_usize(arg_idx.index() - 1) - ) { - // Include previous comma - span = prev.shrink_to_hi().to(span); - } + ) { + // Include previous comma + span = prev.shrink_to_hi().to(span); + } + + // Is last argument for deletion in a row starting from the 0-th argument? + // Then delete the next comma, so we are not left with `f(, ...)` + // + // fn f() {} + // - f(0, 1,) + // + f() + if only_extras_so_far + && errors + .peek() + .map_or(true, |next_error| !matches!(next_error, Error::Extra(_))) + { + let next = provided_arg_tys + .get(arg_idx.plus(1)) + .map(|&(_, sp)| sp) + .unwrap_or_else(|| { + // Subtract one to move before `)` + call_expr + .span + .shrink_to_hi() + .with_lo(call_expr.span.hi() - BytePos(1)) + }); + + // Include next comma + span = span.until(next); + } + suggestions.push((span, String::new())); suggestion_text = match suggestion_text { diff --git a/tests/ui/argument-suggestions/issue-109425.fixed b/tests/ui/argument-suggestions/issue-109425.fixed new file mode 100644 index 000000000000..143ddf99586f --- /dev/null +++ b/tests/ui/argument-suggestions/issue-109425.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +fn f() {} +fn i(_: u32) {} +fn is(_: u32, _: &str) {} +fn s(_: &str) {} + +fn main() { + // code expected suggestion + f(); // f() + //~^ error: this function takes 0 arguments but 2 arguments were supplied + i(0,); // i(0,) + //~^ error: this function takes 1 argument but 3 arguments were supplied + i(0); // i(0) + //~^ error: this function takes 1 argument but 3 arguments were supplied + is(0, ""); // is(0, "") + //~^ error: this function takes 2 arguments but 4 arguments were supplied + s(""); // s("") + //~^ error: this function takes 1 argument but 3 arguments were supplied +} diff --git a/tests/ui/argument-suggestions/issue-109425.rs b/tests/ui/argument-suggestions/issue-109425.rs index 2b92b6dccd7b..a845c419555c 100644 --- a/tests/ui/argument-suggestions/issue-109425.rs +++ b/tests/ui/argument-suggestions/issue-109425.rs @@ -1,3 +1,5 @@ +// run-rustfix + fn f() {} fn i(_: u32) {} fn is(_: u32, _: &str) {} diff --git a/tests/ui/argument-suggestions/issue-109425.stderr b/tests/ui/argument-suggestions/issue-109425.stderr index 59febb682220..1514f1cb487e 100644 --- a/tests/ui/argument-suggestions/issue-109425.stderr +++ b/tests/ui/argument-suggestions/issue-109425.stderr @@ -1,5 +1,5 @@ error[E0061]: this function takes 0 arguments but 2 arguments were supplied - --> $DIR/issue-109425.rs:8:5 + --> $DIR/issue-109425.rs:10:5 | LL | f(0, 1,); // f() | ^ - - unexpected argument of type `{integer}` @@ -7,18 +7,18 @@ LL | f(0, 1,); // f() | unexpected argument of type `{integer}` | note: function defined here - --> $DIR/issue-109425.rs:1:4 + --> $DIR/issue-109425.rs:3:4 | LL | fn f() {} | ^ help: remove the extra arguments | LL - f(0, 1,); // f() -LL + f(,); // f() +LL + f(); // f() | error[E0061]: this function takes 1 argument but 3 arguments were supplied - --> $DIR/issue-109425.rs:10:5 + --> $DIR/issue-109425.rs:12:5 | LL | i(0, 1, 2,); // i(0,) | ^ - - unexpected argument of type `{integer}` @@ -26,7 +26,7 @@ LL | i(0, 1, 2,); // i(0,) | unexpected argument of type `{integer}` | note: function defined here - --> $DIR/issue-109425.rs:2:4 + --> $DIR/issue-109425.rs:4:4 | LL | fn i(_: u32) {} | ^ ------ @@ -37,7 +37,7 @@ LL + i(0,); // i(0,) | error[E0061]: this function takes 1 argument but 3 arguments were supplied - --> $DIR/issue-109425.rs:12:5 + --> $DIR/issue-109425.rs:14:5 | LL | i(0, 1, 2); // i(0) | ^ - - unexpected argument of type `{integer}` @@ -45,7 +45,7 @@ LL | i(0, 1, 2); // i(0) | unexpected argument of type `{integer}` | note: function defined here - --> $DIR/issue-109425.rs:2:4 + --> $DIR/issue-109425.rs:4:4 | LL | fn i(_: u32) {} | ^ ------ @@ -56,7 +56,7 @@ LL + i(0); // i(0) | error[E0061]: this function takes 2 arguments but 4 arguments were supplied - --> $DIR/issue-109425.rs:14:5 + --> $DIR/issue-109425.rs:16:5 | LL | is(0, 1, 2, ""); // is(0, "") | ^^ - - unexpected argument of type `{integer}` @@ -64,7 +64,7 @@ LL | is(0, 1, 2, ""); // is(0, "") | unexpected argument of type `{integer}` | note: function defined here - --> $DIR/issue-109425.rs:3:4 + --> $DIR/issue-109425.rs:5:4 | LL | fn is(_: u32, _: &str) {} | ^^ ------ ------- @@ -75,7 +75,7 @@ LL + is(0, ""); // is(0, "") | error[E0061]: this function takes 1 argument but 3 arguments were supplied - --> $DIR/issue-109425.rs:16:5 + --> $DIR/issue-109425.rs:18:5 | LL | s(0, 1, ""); // s("") | ^ - - unexpected argument of type `{integer}` @@ -83,14 +83,14 @@ LL | s(0, 1, ""); // s("") | unexpected argument of type `{integer}` | note: function defined here - --> $DIR/issue-109425.rs:4:4 + --> $DIR/issue-109425.rs:6:4 | LL | fn s(_: &str) {} | ^ ------- help: remove the extra arguments | LL - s(0, 1, ""); // s("") -LL + s(, ""); // s("") +LL + s(""); // s("") | error: aborting due to 5 previous errors diff --git a/tests/ui/suggestions/issue-109396.stderr b/tests/ui/suggestions/issue-109396.stderr index eca160e2fab2..d4956872a399 100644 --- a/tests/ui/suggestions/issue-109396.stderr +++ b/tests/ui/suggestions/issue-109396.stderr @@ -25,7 +25,7 @@ note: function defined here help: remove the extra arguments | LL - file.as_raw_fd(), -LL + , +LL + ); | error: aborting due to 2 previous errors From 6c941362c9814bc5d2c9c436830543ce37e694b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 31 Mar 2023 09:37:39 +0200 Subject: [PATCH 016/267] Workaround #109797 on windows-gnu --- library/std/src/sys/common/thread_local/os_local.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs index ce74ad3486e1..1442a397e767 100644 --- a/library/std/src/sys/common/thread_local/os_local.rs +++ b/library/std/src/sys/common/thread_local/os_local.rs @@ -49,7 +49,9 @@ macro_rules! __thread_local_inner { #[inline] fn __init() -> $t { $init } - #[cfg_attr(not(bootstrap), inline)] + // `#[inline] does not work on windows-gnu due to linking errors around dllimports. + // See https://github.com/rust-lang/rust/issues/109797. + #[cfg_attr(not(windows), inline)] unsafe fn __getit( init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { From 0504a333837e10f19454901fd060c0f99bf8f5b7 Mon Sep 17 00:00:00 2001 From: Julia Tatz Date: Tue, 6 Apr 2021 16:00:35 -0400 Subject: [PATCH 017/267] Preserve, clarify, and extend debug information `-Cdebuginfo=1` was never line tables only and can't be due to backwards compatibility issues. This was clarified and an option for line tables only was added. Additionally an option for line info directives only was added, which is well needed for some targets. The debug info options should now behave the same as clang's debug info options. --- .../src/debuginfo/metadata.rs | 19 +----------- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 6 ++-- compiler/rustc_codegen_ssa/src/back/linker.rs | 5 +++- compiler/rustc_interface/src/tests.rs | 3 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 3 ++ compiler/rustc_session/src/config.rs | 29 ++++--------------- compiler/rustc_session/src/options.rs | 19 ++++++++++-- src/doc/rustc/src/codegen-options/index.md | 8 +++-- tests/codegen/debug-limited.rs | 28 ++++++++++++++++++ tests/codegen/debug-line-directives-only.rs | 28 ++++++++++++++++++ tests/codegen/debug-line-tables-only.rs | 28 ++++++++++++++++++ tests/rustdoc-ui/c-help.stdout | 2 +- 13 files changed, 126 insertions(+), 54 deletions(-) create mode 100644 tests/codegen/debug-limited.rs create mode 100644 tests/codegen/debug-line-directives-only.rs create mode 100644 tests/codegen/debug-line-tables-only.rs diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index e2a592d851a8..4bf6762d1f60 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -830,24 +830,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( } .unwrap_or_default(); let split_name = split_name.to_str().unwrap(); - - // FIXME(#60020): - // - // This should actually be - // - // let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo); - // - // That is, we should set LLVM's emission kind to `LineTablesOnly` if - // we are compiling with "limited" debuginfo. However, some of the - // existing tools relied on slightly more debuginfo being generated than - // would be the case with `LineTablesOnly`, and we did not want to break - // these tools in a "drive-by fix", without a good idea or plan about - // what limited debuginfo should exactly look like. So for now we keep - // the emission kind as `FullDebug`. - // - // See https://github.com/rust-lang/rust/issues/60020 for details. - let kind = DebugEmissionKind::FullDebug; - assert!(tcx.sess.opts.debuginfo != DebugInfo::None); + let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo); unsafe { let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile( diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 5392534cfcb7..41a75c9d775f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -402,7 +402,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { cx: &CodegenCx<'ll, 'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> &'ll DIArray { - if cx.sess().opts.debuginfo == DebugInfo::Limited { + if cx.sess().opts.debuginfo != DebugInfo::Full { return create_DIArray(DIB(cx), &[]); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 0d63e634ad88..aff352abab46 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -946,6 +946,7 @@ pub mod debuginfo { NoDebug, FullDebug, LineTablesOnly, + DebugDirectivesOnly, } impl DebugEmissionKind { @@ -953,8 +954,9 @@ pub mod debuginfo { use rustc_session::config::DebugInfo; match kind { DebugInfo::None => DebugEmissionKind::NoDebug, - DebugInfo::Limited => DebugEmissionKind::LineTablesOnly, - DebugInfo::Full => DebugEmissionKind::FullDebug, + DebugInfo::LineDirectivesOnly => DebugEmissionKind::DebugDirectivesOnly, + DebugInfo::LineTablesOnly => DebugEmissionKind::LineTablesOnly, + DebugInfo::Limited | DebugInfo::Full => DebugEmissionKind::FullDebug, } } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 69bb00f804d3..65dfc325a118 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1121,9 +1121,12 @@ impl<'a> Linker for EmLinker<'a> { fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) { // Preserve names or generate source maps depending on debug info + // For more information see https://emscripten.org/docs/tools_reference/emcc.html#emcc-g self.cmd.arg(match self.sess.opts.debuginfo { DebugInfo::None => "-g0", - DebugInfo::Limited => "--profiling-funcs", + DebugInfo::Limited | DebugInfo::LineTablesOnly | DebugInfo::LineDirectivesOnly => { + "--profiling-funcs" + } DebugInfo::Full => "-g", }); } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index eb5990507fb6..10dfd32d418a 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::rustc_optgroups; +use rustc_session::config::DebugInfo; use rustc_session::config::Input; use rustc_session::config::InstrumentXRay; use rustc_session::config::TraitSolver; @@ -574,7 +575,7 @@ fn test_codegen_options_tracking_hash() { tracked!(code_model, Some(CodeModel::Large)); tracked!(control_flow_guard, CFGuard::Checks); tracked!(debug_assertions, Some(true)); - tracked!(debuginfo, 0xdeadbeef); + tracked!(debuginfo, DebugInfo::Limited); tracked!(embed_bitcode, false); tracked!(force_frame_pointers, Some(false)); tracked!(force_unwind_tables, Some(true)); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index e3493caaaf74..6a2fd5aa6e6a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -682,6 +682,7 @@ enum class LLVMRustDebugEmissionKind { NoDebug, FullDebug, LineTablesOnly, + DebugDirectivesOnly, }; static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) { @@ -692,6 +693,8 @@ static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) return DICompileUnit::DebugEmissionKind::FullDebug; case LLVMRustDebugEmissionKind::LineTablesOnly: return DICompileUnit::DebugEmissionKind::LineTablesOnly; + case LLVMRustDebugEmissionKind::DebugDirectivesOnly: + return DICompileUnit::DebugEmissionKind::DebugDirectivesOnly; default: report_fatal_error("bad DebugEmissionKind."); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 485c3f554625..1d8fedb8bd79 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -260,6 +260,8 @@ pub enum SymbolManglingVersion { #[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum DebugInfo { None, + LineDirectivesOnly, + LineTablesOnly, Limited, Full, } @@ -1979,11 +1981,7 @@ fn parse_opt_level( } } -fn select_debuginfo( - matches: &getopts::Matches, - cg: &CodegenOptions, - error_format: ErrorOutputType, -) -> DebugInfo { +fn select_debuginfo(matches: &getopts::Matches, cg: &CodegenOptions) -> DebugInfo { let max_g = matches.opt_positions("g").into_iter().max(); let max_c = matches .opt_strs_pos("C") @@ -1993,24 +1991,7 @@ fn select_debuginfo( if let Some("debuginfo") = s.split('=').next() { Some(i) } else { None } }) .max(); - if max_g > max_c { - DebugInfo::Full - } else { - match cg.debuginfo { - 0 => DebugInfo::None, - 1 => DebugInfo::Limited, - 2 => DebugInfo::Full, - arg => { - early_error( - error_format, - &format!( - "debug info level needs to be between \ - 0-2 (instead was `{arg}`)" - ), - ); - } - } - } + if max_g > max_c { DebugInfo::Full } else { cg.debuginfo } } pub(crate) fn parse_assert_incr_state( @@ -2498,7 +2479,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) // for more details. let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); - let debuginfo = select_debuginfo(matches, &cg, error_format); + let debuginfo = select_debuginfo(matches, &cg); let mut search_paths = vec![]; for s in &matches.opt_strs("L") { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c75af48e80af..953d6561669f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -377,6 +377,7 @@ mod desc { pub const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; + pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -767,6 +768,18 @@ mod parse { true } + pub(crate) fn parse_debuginfo(slot: &mut DebugInfo, v: Option<&str>) -> bool { + match v { + Some("0") | Some("none") => *slot = DebugInfo::None, + Some("line-directives-only") => *slot = DebugInfo::LineDirectivesOnly, + Some("line-tables-only") => *slot = DebugInfo::LineTablesOnly, + Some("1") | Some("limited") => *slot = DebugInfo::Limited, + Some("2") | Some("full") => *slot = DebugInfo::Full, + _ => return false, + } + true + } + pub(crate) fn parse_linker_flavor(slot: &mut Option, v: Option<&str>) -> bool { match v.and_then(LinkerFlavorCli::from_str) { Some(lf) => *slot = Some(lf), @@ -1217,9 +1230,9 @@ options! { "use Windows Control Flow Guard (default: no)"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the `cfg(debug_assertions)` directive"), - debuginfo: usize = (0, parse_number, [TRACKED], - "debug info emission level (0 = no debug info, 1 = line tables only, \ - 2 = full debug info with variable and type information; default: 0)"), + debuginfo: DebugInfo = (DebugInfo::None, parse_debuginfo, [TRACKED], + "debug info emission level (0-2, none, line-directives-only, \ + line-tables-only, limited, or full; default: 0)"), default_linker_libraries: bool = (false, parse_bool, [UNTRACKED], "allow the linker to link its default libraries (default: no)"), embed_bitcode: bool = (true, parse_bool, [TRACKED], diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index c7f120dafeaf..8b4f1cd2d416 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -71,9 +71,11 @@ If not specified, debug assertions are automatically enabled only if the This flag controls the generation of debug information. It takes one of the following values: -* `0`: no debug info at all (the default). -* `1`: line tables only. -* `2`: full debug info. +* `0` or `none`: no debug info at all (the default). +* `line-directives-only`: line info directives only. +* `line-tables-only`: line tables only. +* `1` or `limited`: debug info without type information. +* `2` or `full`: full debug info. Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`. diff --git a/tests/codegen/debug-limited.rs b/tests/codegen/debug-limited.rs new file mode 100644 index 000000000000..fafee0ef583a --- /dev/null +++ b/tests/codegen/debug-limited.rs @@ -0,0 +1,28 @@ +// Verify that the limited debuginfo option emits llvm's FullDebugInfo, but no type info. +// +// ignore-windows +// compile-flags: -C debuginfo=limited + +#[repr(C)] +struct StructType { + a: i64, + b: i32 +} + +extern "C" { + fn creator() -> *mut StructType; + fn save(p: *const StructType); +} + +fn main() { + unsafe { + let value: &mut StructType = &mut* creator(); + value.a = 7; + save(value as *const StructType) + } +} + +// CHECK: !DICompileUnit +// CHECK: emissionKind: FullDebug +// CHECK: !DILocation +// CHECK-NOT: !DIBasicType diff --git a/tests/codegen/debug-line-directives-only.rs b/tests/codegen/debug-line-directives-only.rs new file mode 100644 index 000000000000..0dd22931b30a --- /dev/null +++ b/tests/codegen/debug-line-directives-only.rs @@ -0,0 +1,28 @@ +// Verify that the only debuginfo generated are the line directives. +// +// ignore-windows +// compile-flags: -C debuginfo=line-directives-only + +#[repr(C)] +struct StructType { + a: i64, + b: i32 +} + +extern "C" { + fn creator() -> *mut StructType; + fn save(p: *const StructType); +} + +fn main() { + unsafe { + let value: &mut StructType = &mut* creator(); + value.a = 7; + save(value as *const StructType) + } +} + +// CHECK: !DICompileUnit +// CHECK: emissionKind: DebugDirectivesOnly +// CHECK: !DILocation +// CHECK-NOT: !DIBasicType diff --git a/tests/codegen/debug-line-tables-only.rs b/tests/codegen/debug-line-tables-only.rs new file mode 100644 index 000000000000..3d109d4ae519 --- /dev/null +++ b/tests/codegen/debug-line-tables-only.rs @@ -0,0 +1,28 @@ +// Verify that the only debuginfo generated are the line tables. +// +// ignore-windows +// compile-flags: -C debuginfo=line-tables-only + +#[repr(C)] +struct StructType { + a: i64, + b: i32 +} + +extern "C" { + fn creator() -> *mut StructType; + fn save(p: *const StructType); +} + +fn main() { + unsafe { + let value: &mut StructType = &mut* creator(); + value.a = 7; + save(value as *const StructType) + } +} + +// CHECK: !DICompileUnit +// CHECK: emissionKind: LineTablesOnly +// CHECK: !DILocation +// CHECK-NOT: !DIBasicType diff --git a/tests/rustdoc-ui/c-help.stdout b/tests/rustdoc-ui/c-help.stdout index 75b2e2a2a43f..0bd2d73efee5 100644 --- a/tests/rustdoc-ui/c-help.stdout +++ b/tests/rustdoc-ui/c-help.stdout @@ -3,7 +3,7 @@ -C codegen-units=val -- divide crate into N units to optimize in parallel -C control-flow-guard=val -- use Windows Control Flow Guard (default: no) -C debug-assertions=val -- explicitly enable the `cfg(debug_assertions)` directive - -C debuginfo=val -- debug info emission level (0 = no debug info, 1 = line tables only, 2 = full debug info with variable and type information; default: 0) + -C debuginfo=val -- debug info emission level (0-2, none, line-directives-only, line-tables-only, limited, or full; default: 0) -C default-linker-libraries=val -- allow the linker to link its default libraries (default: no) -C embed-bitcode=val -- emit bitcode in rlibs (default: yes) -C extra-filename=val -- extra data to put in each output filename From 7b453b9f5a3b921291fd723067d48fee28e7475b Mon Sep 17 00:00:00 2001 From: Julia Tatz Date: Fri, 3 Sep 2021 13:00:39 -0400 Subject: [PATCH 018/267] More in-depth documentation for the new debuginfo options --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 10 ++++++++++ src/doc/rustc/src/codegen-options/index.md | 4 ++-- tests/codegen/debug-limited.rs | 5 ++--- tests/codegen/debug-line-directives-only.rs | 5 ++--- tests/codegen/debug-line-tables-only.rs | 5 ++--- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index aff352abab46..556c6602ff43 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -951,6 +951,16 @@ pub mod debuginfo { impl DebugEmissionKind { pub fn from_generic(kind: rustc_session::config::DebugInfo) -> Self { + // We should be setting LLVM's emission kind to `LineTablesOnly` if + // we are compiling with "limited" debuginfo. However, some of the + // existing tools relied on slightly more debuginfo being generated than + // would be the case with `LineTablesOnly`, and we did not want to break + // these tools in a "drive-by fix", without a good idea or plan about + // what limited debuginfo should exactly look like. So for now we are + // instead adding a new debuginfo option "line-tables-only" so as to + // not break anything and to allow users to have 'limited' debug info. + // + // See https://github.com/rust-lang/rust/issues/60020 for details. use rustc_session::config::DebugInfo; match kind { DebugInfo::None => DebugEmissionKind::NoDebug, diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 8b4f1cd2d416..4d418f9c9b74 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -72,8 +72,8 @@ This flag controls the generation of debug information. It takes one of the following values: * `0` or `none`: no debug info at all (the default). -* `line-directives-only`: line info directives only. -* `line-tables-only`: line tables only. +* `line-directives-only`: line info directives only, (For the nvptx* targets this enables [profiling](https://reviews.llvm.org/D46061), but on other targets the behavior is unspecified). +* `line-tables-only`: line tables only, (Generates the minimal amount of debug info for backtraces with filename/line number info, but not anything else, i.e. variable or function parameter info). * `1` or `limited`: debug info without type information. * `2` or `full`: full debug info. diff --git a/tests/codegen/debug-limited.rs b/tests/codegen/debug-limited.rs index fafee0ef583a..48d676887fdd 100644 --- a/tests/codegen/debug-limited.rs +++ b/tests/codegen/debug-limited.rs @@ -1,12 +1,11 @@ // Verify that the limited debuginfo option emits llvm's FullDebugInfo, but no type info. // -// ignore-windows // compile-flags: -C debuginfo=limited #[repr(C)] struct StructType { a: i64, - b: i32 + b: i32, } extern "C" { @@ -16,7 +15,7 @@ extern "C" { fn main() { unsafe { - let value: &mut StructType = &mut* creator(); + let value: &mut StructType = &mut *creator(); value.a = 7; save(value as *const StructType) } diff --git a/tests/codegen/debug-line-directives-only.rs b/tests/codegen/debug-line-directives-only.rs index 0dd22931b30a..750bdd49de07 100644 --- a/tests/codegen/debug-line-directives-only.rs +++ b/tests/codegen/debug-line-directives-only.rs @@ -1,12 +1,11 @@ // Verify that the only debuginfo generated are the line directives. // -// ignore-windows // compile-flags: -C debuginfo=line-directives-only #[repr(C)] struct StructType { a: i64, - b: i32 + b: i32, } extern "C" { @@ -16,7 +15,7 @@ extern "C" { fn main() { unsafe { - let value: &mut StructType = &mut* creator(); + let value: &mut StructType = &mut *creator(); value.a = 7; save(value as *const StructType) } diff --git a/tests/codegen/debug-line-tables-only.rs b/tests/codegen/debug-line-tables-only.rs index 3d109d4ae519..3ed165a6f696 100644 --- a/tests/codegen/debug-line-tables-only.rs +++ b/tests/codegen/debug-line-tables-only.rs @@ -1,12 +1,11 @@ // Verify that the only debuginfo generated are the line tables. // -// ignore-windows // compile-flags: -C debuginfo=line-tables-only #[repr(C)] struct StructType { a: i64, - b: i32 + b: i32, } extern "C" { @@ -16,7 +15,7 @@ extern "C" { fn main() { unsafe { - let value: &mut StructType = &mut* creator(); + let value: &mut StructType = &mut *creator(); value.a = 7; save(value as *const StructType) } From 60c6dc07dedc1c85ebfff54a0d81f3328923a2a8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 Mar 2023 16:58:49 +0400 Subject: [PATCH 019/267] resolve: Restore some effective visibility optimizations Something similar was previously removed as a part of #104602, but after this PR all table changes should also be "locally correct" after every update. --- .../src/effective_visibilities.rs | 36 ++++++++++++++----- tests/ui/privacy/effective_visibilities.rs | 6 ++-- .../ui/privacy/effective_visibilities.stderr | 6 ++-- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 3673f603d167..bed579f6b925 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -155,10 +155,6 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } - fn cheap_private_vis(&self, parent_id: ParentId<'_>) -> Option { - matches!(parent_id, ParentId::Def(_)).then_some(self.current_private_vis) - } - fn effective_vis_or_private(&mut self, parent_id: ParentId<'a>) -> EffectiveVisibility { // Private nodes are only added to the table for caching, they could be added or removed at // any moment without consequences, so we don't set `changed` to true when adding them. @@ -172,15 +168,39 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } + /// All effective visibilities for a node are larger or equal than private visibility + /// for that node (see `check_invariants` in middle/privacy.rs). + /// So if either parent or nominal visibility is the same as private visibility, then + /// `min(parent_vis, nominal_vis) <= private_vis`, and the update logic is guaranteed + /// to not update anything and we can skip it. + /// + /// We are checking this condition only if the correct value of private visibility is + /// cheaply available, otherwise it does't make sense performance-wise. + /// + /// `None` is returned if the update can be skipped, + /// and cheap private visibility is returned otherwise. + fn may_update( + &self, + nominal_vis: Visibility, + parent_id: ParentId<'_>, + ) -> Option> { + match parent_id { + ParentId::Def(def_id) => (nominal_vis != self.current_private_vis + && self.r.visibilities[&def_id] != self.current_private_vis) + .then_some(Some(self.current_private_vis)), + ParentId::Import(_) => Some(None), + } + } + fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) { let nominal_vis = binding.vis.expect_local(); - let private_vis = self.cheap_private_vis(parent_id); + let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); let tcx = self.r.tcx; self.changed |= self.import_effective_visibilities.update( binding, nominal_vis, - || private_vis.unwrap_or_else(|| self.r.private_vis_import(binding)), + || cheap_private_vis.unwrap_or_else(|| self.r.private_vis_import(binding)), inherited_eff_vis, parent_id.level(), tcx, @@ -188,13 +208,13 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) { - let private_vis = self.cheap_private_vis(parent_id); + let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); let tcx = self.r.tcx; self.changed |= self.def_effective_visibilities.update( def_id, nominal_vis, - || private_vis.unwrap_or_else(|| self.r.private_vis_def(def_id)), + || cheap_private_vis.unwrap_or_else(|| self.r.private_vis_def(def_id)), inherited_eff_vis, parent_id.level(), tcx, diff --git a/tests/ui/privacy/effective_visibilities.rs b/tests/ui/privacy/effective_visibilities.rs index 3e9eef462306..e9ac93160870 100644 --- a/tests/ui/privacy/effective_visibilities.rs +++ b/tests/ui/privacy/effective_visibilities.rs @@ -18,13 +18,13 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub } #[rustc_effective_visibility] - struct PrivStruct; //~ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) - //~| ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) + struct PrivStruct; //~ ERROR not in the table + //~| ERROR not in the table #[rustc_effective_visibility] pub union PubUnion { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub #[rustc_effective_visibility] - a: u8, //~ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) + a: u8, //~ ERROR not in the table #[rustc_effective_visibility] pub b: u8, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub } diff --git a/tests/ui/privacy/effective_visibilities.stderr b/tests/ui/privacy/effective_visibilities.stderr index 2618fc427e91..f74f812e1a0e 100644 --- a/tests/ui/privacy/effective_visibilities.stderr +++ b/tests/ui/privacy/effective_visibilities.stderr @@ -34,13 +34,13 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl LL | pub trait PubTrait { | ^^^^^^^^^^^^^^^^^^ -error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) +error: not in the table --> $DIR/effective_visibilities.rs:21:9 | LL | struct PrivStruct; | ^^^^^^^^^^^^^^^^^ -error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) +error: not in the table --> $DIR/effective_visibilities.rs:21:9 | LL | struct PrivStruct; @@ -52,7 +52,7 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl LL | pub union PubUnion { | ^^^^^^^^^^^^^^^^^^ -error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) +error: not in the table --> $DIR/effective_visibilities.rs:27:13 | LL | a: u8, From 000e94e67d2b439c9dc3644c124ae4c405624a14 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 25 Mar 2023 09:28:28 -0700 Subject: [PATCH 020/267] diagnostics: account for glob shadowing when linting redundant imports Co-Authored-By: Vadim Petrochenkov --- compiler/rustc_resolve/src/ident.rs | 35 +++++++++++-------- tests/ui/lint/use-redundant/issue-92904.rs | 17 +++++++++ .../use-redundant-glob-parent.rs | 16 +++++++++ .../use-redundant-glob-parent.stderr | 17 +++++++++ .../lint/use-redundant/use-redundant-glob.rs | 15 ++++++++ .../use-redundant/use-redundant-glob.stderr | 16 +++++++++ .../use-redundant-multiple-namespaces.rs | 21 +++++++++++ .../use-redundant/use-redundant-not-parent.rs | 19 ++++++++++ 8 files changed, 142 insertions(+), 14 deletions(-) create mode 100644 tests/ui/lint/use-redundant/issue-92904.rs create mode 100644 tests/ui/lint/use-redundant/use-redundant-glob-parent.rs create mode 100644 tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr create mode 100644 tests/ui/lint/use-redundant/use-redundant-glob.rs create mode 100644 tests/ui/lint/use-redundant/use-redundant-glob.stderr create mode 100644 tests/ui/lint/use-redundant/use-redundant-multiple-namespaces.rs create mode 100644 tests/ui/lint/use-redundant/use-redundant-not-parent.rs diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 52f0b65fad67..5e1d5d8a8fb0 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -869,17 +869,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let resolution = self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. - if let Some(Finalize { path_span, report_private, .. }) = finalize { - // If the primary binding is unusable, search further and return the shadowed glob - // binding if it exists. What we really want here is having two separate scopes in - // a module - one for non-globs and one for globs, but until that's done use this - // hack to avoid inconsistent resolution ICEs during import validation. - let binding = [resolution.binding, resolution.shadowed_glob].into_iter().find_map( - |binding| match (binding, ignore_binding) { + // If the primary binding is unusable, search further and return the shadowed glob + // binding if it exists. What we really want here is having two separate scopes in + // a module - one for non-globs and one for globs, but until that's done use this + // hack to avoid inconsistent resolution ICEs during import validation. + let binding = + [resolution.binding, resolution.shadowed_glob].into_iter().find_map(|binding| { + match (binding, ignore_binding) { (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None, _ => binding, - }, - ); + } + }); + + if let Some(Finalize { path_span, report_private, .. }) = finalize { let Some(binding) = binding else { return Err((Determined, Weak::No)); }; @@ -927,15 +929,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { - if let Some(ignored) = ignore_binding && ptr::eq(binding, ignored) { - return Err((Determined, Weak::No)); - } let usable = this.is_accessible_from(binding.vis, parent_scope.module); if usable { Ok(binding) } else { Err((Determined, Weak::No)) } }; // Items and single imports are not shadowable, if we have one, then it's determined. - if let Some(binding) = resolution.binding { + if let Some(binding) = binding { if !binding.is_glob_import() { return check_usable(self, binding); } @@ -952,6 +951,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !self.is_accessible_from(import_vis, parent_scope.module) { continue; } + if let Some(ignored) = ignore_binding && + let NameBindingKind::Import { import, .. } = ignored.kind && + ptr::eq(import, &**single_import) { + // Ignore not just the binding itself, but if it has a shadowed_glob, + // ignore that, too, because this loop is supposed to only process + // named imports. + continue; + } let Some(module) = single_import.imported_module.get() else { return Err((Undetermined, Weak::No)); }; @@ -989,7 +996,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted // shadowing is enabled, see `macro_expanded_macro_export_errors`). let unexpanded_macros = !module.unexpanded_invocations.borrow().is_empty(); - if let Some(binding) = resolution.binding { + if let Some(binding) = binding { if !unexpanded_macros || ns == MacroNS || restricted_shadowing { return check_usable(self, binding); } else { diff --git a/tests/ui/lint/use-redundant/issue-92904.rs b/tests/ui/lint/use-redundant/issue-92904.rs new file mode 100644 index 000000000000..511d9d263cf8 --- /dev/null +++ b/tests/ui/lint/use-redundant/issue-92904.rs @@ -0,0 +1,17 @@ +// check-pass + +pub struct Foo(bar::Bar); + +pub mod bar { + pub struct Foo(pub Bar); + pub struct Bar(pub char); +} + +pub fn warning() -> Foo { + use bar::*; + #[deny(unused_imports)] + use self::Foo; // no error + Foo(Bar('a')) +} + +fn main() {} diff --git a/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs b/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs new file mode 100644 index 000000000000..6b1e018d2dc3 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs @@ -0,0 +1,16 @@ +// check-pass +#![warn(unused_imports)] + +pub mod bar { + pub struct Foo(pub Bar); + pub struct Bar(pub char); +} + +use bar::*; + +pub fn warning() -> Foo { + use bar::Foo; //~ WARNING imported redundantly + Foo(Bar('a')) +} + +fn main() {} diff --git a/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr b/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr new file mode 100644 index 000000000000..2c3b33452702 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr @@ -0,0 +1,17 @@ +warning: the item `Foo` is imported redundantly + --> $DIR/use-redundant-glob-parent.rs:12:9 + | +LL | use bar::*; + | ------ the item `Foo` is already imported here +... +LL | use bar::Foo; + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/use-redundant-glob-parent.rs:2:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant-glob.rs b/tests/ui/lint/use-redundant/use-redundant-glob.rs new file mode 100644 index 000000000000..bd9e51b6f594 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-glob.rs @@ -0,0 +1,15 @@ +// check-pass +#![warn(unused_imports)] + +pub mod bar { + pub struct Foo(pub Bar); + pub struct Bar(pub char); +} + +pub fn warning() -> bar::Foo { + use bar::*; + use bar::Foo; //~ WARNING imported redundantly + Foo(Bar('a')) +} + +fn main() {} diff --git a/tests/ui/lint/use-redundant/use-redundant-glob.stderr b/tests/ui/lint/use-redundant/use-redundant-glob.stderr new file mode 100644 index 000000000000..d3b406d82b6d --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-glob.stderr @@ -0,0 +1,16 @@ +warning: the item `Foo` is imported redundantly + --> $DIR/use-redundant-glob.rs:11:9 + | +LL | use bar::*; + | ------ the item `Foo` is already imported here +LL | use bar::Foo; + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/use-redundant-glob.rs:2:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant-multiple-namespaces.rs b/tests/ui/lint/use-redundant/use-redundant-multiple-namespaces.rs new file mode 100644 index 000000000000..0fb60840f8ad --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-multiple-namespaces.rs @@ -0,0 +1,21 @@ +// check-pass +#![allow(nonstandard_style)] + +pub mod bar { + pub struct Foo { pub bar: Bar } + pub struct Bar(pub char); +} + +pub mod x { + use crate::bar; + pub const Foo: bar::Bar = bar::Bar('a'); +} + +pub fn warning() -> bar::Foo { + #![deny(unused_imports)] // no error + use bar::*; + use x::Foo; + Foo { bar: Foo } +} + +fn main() {} diff --git a/tests/ui/lint/use-redundant/use-redundant-not-parent.rs b/tests/ui/lint/use-redundant/use-redundant-not-parent.rs new file mode 100644 index 000000000000..c97a3d34163c --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-not-parent.rs @@ -0,0 +1,19 @@ +// check-pass + +pub mod bar { + pub struct Foo(pub Bar); + pub struct Bar(pub char); +} + +pub mod x { + pub struct Foo(pub crate::bar::Bar); +} + +pub fn warning() -> x::Foo { + use bar::*; + #[deny(unused_imports)] + use x::Foo; // no error + Foo(Bar('a')) +} + +fn main() {} From 47ae42ee101c36fe18a5fe15e6cb501c8992fe7a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 1 Apr 2023 23:14:18 +0100 Subject: [PATCH 021/267] Only create graphviz nodes for reachable MIR bb's --- .../rustc_mir_dataflow/src/framework/graphviz.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 96c42894b697..c188105eae89 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -6,6 +6,7 @@ use std::{io, ops, str}; use regex::Regex; use rustc_graphviz as dot; +use rustc_index::bit_set::BitSet; use rustc_middle::mir::graphviz_safe_def_name; use rustc_middle::mir::{self, BasicBlock, Body, Location}; @@ -34,6 +35,7 @@ where body: &'a Body<'tcx>, results: &'a Results<'tcx, A>, style: OutputStyle, + reachable: BitSet, } impl<'a, 'tcx, A> Formatter<'a, 'tcx, A> @@ -41,7 +43,8 @@ where A: Analysis<'tcx>, { pub fn new(body: &'a Body<'tcx>, results: &'a Results<'tcx, A>, style: OutputStyle) -> Self { - Formatter { body, results, style } + let reachable = mir::traversal::reachable_as_bitset(body); + Formatter { body, results, style, reachable } } } @@ -108,7 +111,12 @@ where type Edge = CfgEdge; fn nodes(&self) -> dot::Nodes<'_, Self::Node> { - self.body.basic_blocks.indices().collect::>().into() + self.body + .basic_blocks + .indices() + .filter(|&idx| self.reachable.contains(idx)) + .collect::>() + .into() } fn edges(&self) -> dot::Edges<'_, Self::Edge> { From 696f182191eae8ac8da951edb1206c97ad5da384 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 1 Apr 2023 17:54:20 +0100 Subject: [PATCH 022/267] Fix `non_exhaustive_omitted_patterns` lint span --- .../src/thir/pattern/deconstruct_pat.rs | 35 ++++++++++--------- .../src/thir/pattern/usefulness.rs | 8 ++--- .../omitted-patterns.rs | 8 +++++ .../omitted-patterns.stderr | 16 ++++++++- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index e619e095496b..29f7cae3d3fe 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -1154,8 +1154,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { fn wildcards_from_tys( cx: &MatchCheckCtxt<'p, 'tcx>, tys: impl IntoIterator>, + span: Span, ) -> Self { - Fields::from_iter(cx, tys.into_iter().map(DeconstructedPat::wildcard)) + Fields::from_iter(cx, tys.into_iter().map(|ty| DeconstructedPat::wildcard(ty, span))) } // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide @@ -1191,18 +1192,18 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { pub(super) fn wildcards(pcx: &PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self { let ret = match constructor { Single | Variant(_) => match pcx.ty.kind() { - ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter()), - ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty)), + ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter(), pcx.span), + ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty), pcx.span), ty::Adt(adt, substs) => { if adt.is_box() { // The only legal patterns of type `Box` (outside `std`) are `_` and box // patterns. If we're here we can assume this is a box pattern. - Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0))) + Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0)), pcx.span) } else { let variant = &adt.variant(constructor.variant_index_for_adt(*adt)); let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant) .map(|(_, ty)| ty); - Fields::wildcards_from_tys(pcx.cx, tys) + Fields::wildcards_from_tys(pcx.cx, tys, pcx.span) } } _ => bug!("Unexpected type for `Single` constructor: {:?}", pcx), @@ -1210,7 +1211,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { Slice(slice) => match *pcx.ty.kind() { ty::Slice(ty) | ty::Array(ty, _) => { let arity = slice.arity(); - Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty)) + Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty), pcx.span) } _ => bug!("bad slice pattern {:?} {:?}", constructor, pcx), }, @@ -1251,8 +1252,8 @@ pub(crate) struct DeconstructedPat<'p, 'tcx> { } impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { - pub(super) fn wildcard(ty: Ty<'tcx>) -> Self { - Self::new(Wildcard, Fields::empty(), ty, DUMMY_SP) + pub(super) fn wildcard(ty: Ty<'tcx>, span: Span) -> Self { + Self::new(Wildcard, Fields::empty(), ty, span) } pub(super) fn new( @@ -1269,7 +1270,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { /// `Some(_)`. pub(super) fn wild_from_ctor(pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self { let fields = Fields::wildcards(pcx, &ctor); - DeconstructedPat::new(ctor, fields, pcx.ty, DUMMY_SP) + DeconstructedPat::new(ctor, fields, pcx.ty, pcx.span) } /// Clone this value. This method emphasizes that cloning loses reachability information and @@ -1298,7 +1299,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { ty::Tuple(fs) => { ctor = Single; let mut wilds: SmallVec<[_; 2]> = - fs.iter().map(DeconstructedPat::wildcard).collect(); + fs.iter().map(|ty| DeconstructedPat::wildcard(ty, pat.span)).collect(); for pat in subpatterns { wilds[pat.field.index()] = mkpat(&pat.pattern); } @@ -1317,11 +1318,11 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { // normally or through box-patterns. We'll have to figure out a proper // solution when we introduce generalized deref patterns. Also need to // prevent mixing of those two options. - let pat = subpatterns.into_iter().find(|pat| pat.field.index() == 0); - let pat = if let Some(pat) = pat { + let pattern = subpatterns.into_iter().find(|pat| pat.field.index() == 0); + let pat = if let Some(pat) = pattern { mkpat(&pat.pattern) } else { - DeconstructedPat::wildcard(substs.type_at(0)) + DeconstructedPat::wildcard(substs.type_at(0), pat.span) }; ctor = Single; fields = Fields::singleton(cx, pat); @@ -1343,7 +1344,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { ty }); let mut wilds: SmallVec<[_; 2]> = - tys.map(DeconstructedPat::wildcard).collect(); + tys.map(|ty| DeconstructedPat::wildcard(ty, pat.span)).collect(); for pat in subpatterns { if let Some(i) = field_id_to_id[pat.field.index()] { wilds[i] = mkpat(&pat.pattern); @@ -1566,8 +1567,10 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { }; let prefix = &self.fields.fields[..prefix]; let suffix = &self.fields.fields[self_slice.arity() - suffix..]; - let wildcard: &_ = - pcx.cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty)); + let wildcard: &_ = pcx + .cx + .pattern_arena + .alloc(DeconstructedPat::wildcard(inner_ty, pcx.span)); let extra_wildcards = other_slice.arity() - self_slice.arity(); let extra_wildcards = (0..extra_wildcards).map(|_| wildcard); prefix.iter().chain(extra_wildcards).chain(suffix).collect() diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 9edd7967e7a4..a324c3a62280 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -604,7 +604,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> { let new_patterns = if pcx.is_non_exhaustive { // Here we don't want the user to try to list all variants, we want them to add // a wildcard, so we only suggest that. - vec![DeconstructedPat::wildcard(pcx.ty)] + vec![DeconstructedPat::wildcard(pcx.ty, pcx.span)] } else { let mut split_wildcard = SplitWildcard::new(pcx); split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor)); @@ -631,7 +631,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> { .collect(); if hide_variant_show_wild { - new.push(DeconstructedPat::wildcard(pcx.ty)); + new.push(DeconstructedPat::wildcard(pcx.ty, pcx.span)); } new @@ -734,7 +734,7 @@ impl<'p, 'tcx> Witness<'p, 'tcx> { let arity = ctor.arity(pcx); let pats = self.0.drain((len - arity)..).rev(); let fields = Fields::from_iter(pcx.cx, pats); - DeconstructedPat::new(ctor.clone(), fields, pcx.ty, DUMMY_SP) + DeconstructedPat::new(ctor.clone(), fields, pcx.ty, pcx.span) }; self.0.push(pat); @@ -977,7 +977,7 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>( }) .collect(); - let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty)); + let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty, DUMMY_SP)); let v = PatStack::from_pattern(wild_pattern); let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, scrut_hir_id, false, true); let non_exhaustiveness_witnesses = match usefulness { diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs index 7ef1d635d9ce..3482af74752f 100644 --- a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs +++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs @@ -194,6 +194,14 @@ fn main() { let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit; //~^ refutable pattern in local binding + // Check that matching on a reference results in a correctly spanned diagnostic + #[deny(non_exhaustive_omitted_patterns)] + match &non_enum { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } + //~^^ some variants are not matched explicitly } #[deny(non_exhaustive_omitted_patterns)] diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr index 617c629a4fe0..520a90322c1c 100644 --- a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr +++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr @@ -198,6 +198,20 @@ help: you might want to use `let else` to handle the variant that isn't matched LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit else { todo!() }; | ++++++++++++++++ -error: aborting due to 9 previous errors; 6 warnings emitted +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:202:9 + | +LL | _ => {} + | ^ pattern `NonExhaustiveEnum::Struct { .. }` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:198:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors; 6 warnings emitted For more information about this error, try `rustc --explain E0005`. From 7b9aa5fa2cb4daf8414b9b8091dc651a8e17f9e7 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 2 Apr 2023 20:45:20 -0700 Subject: [PATCH 023/267] Fix macos pkg installer when rust-docs is not available. --- src/bootstrap/dist.rs | 2 +- src/etc/installer/pkg/Distribution.xml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 2ce54d9a3b43..9eed2bf50237 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1488,7 +1488,7 @@ impl Step for Extended { let xform = |p: &Path| { let mut contents = t!(fs::read_to_string(p)); - for tool in &["rust-demangler", "miri"] { + for tool in &["rust-demangler", "miri", "rust-docs"] { if !built_tools.contains(tool) { contents = filter(&contents, tool); } diff --git a/src/etc/installer/pkg/Distribution.xml b/src/etc/installer/pkg/Distribution.xml index 64f6bab9bb5f..1643fc8364b6 100644 --- a/src/etc/installer/pkg/Distribution.xml +++ b/src/etc/installer/pkg/Distribution.xml @@ -15,7 +15,9 @@ + + @@ -55,15 +57,19 @@ > + + rustc.pkg cargo.pkg + rust-docs.pkg + rust-std.pkg uninstall.pkg Date: Mon, 6 Mar 2023 10:31:16 +0100 Subject: [PATCH 024/267] include eventual comment in the compiletest ignore reason --- src/tools/compiletest/src/header.rs | 72 ++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 5bc9d9afcb9d..15020a373f06 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -16,8 +16,20 @@ use crate::{extract_cdb_version, extract_gdb_version}; mod tests; /// The result of parse_cfg_name_directive. +#[derive(Clone, PartialEq, Debug)] +struct ParsedNameDirective { + comment: Option, + outcome: MatchOutcome, +} + +impl ParsedNameDirective { + fn invalid() -> Self { + Self { comment: None, outcome: MatchOutcome::NoMatch } + } +} + #[derive(Clone, Copy, PartialEq, Debug)] -enum ParsedNameDirective { +enum MatchOutcome { /// No match. NoMatch, /// Match. @@ -647,7 +659,7 @@ impl Config { } fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> { - if self.parse_cfg_name_directive(line, prefix) == ParsedNameDirective::Match { + if self.parse_cfg_name_directive(line, prefix).outcome == MatchOutcome::Match { let from = parse_normalization_string(&mut line)?; let to = parse_normalization_string(&mut line)?; Some((from, to)) @@ -668,13 +680,15 @@ impl Config { /// or `normalize-stderr-32bit`. fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective { if !line.as_bytes().starts_with(prefix.as_bytes()) { - return ParsedNameDirective::NoMatch; + return ParsedNameDirective::invalid(); } if line.as_bytes().get(prefix.len()) != Some(&b'-') { - return ParsedNameDirective::NoMatch; + return ParsedNameDirective::invalid(); } + let line = &line[prefix.len() + 1..]; - let name = line[prefix.len() + 1..].split(&[':', ' '][..]).next().unwrap(); + let (name, comment) = + line.split_once(&[':', ' ']).map(|(l, c)| (l, Some(c))).unwrap_or((line, None)); let matches_pointer_width = || { name.strip_suffix("bit") @@ -723,7 +737,10 @@ impl Config { None => false, }; - if is_match { ParsedNameDirective::Match } else { ParsedNameDirective::NoMatch } + ParsedNameDirective { + comment: comment.map(|c| c.trim().trim_start_matches('-').trim().to_string()), + outcome: if is_match { MatchOutcome::Match } else { MatchOutcome::NoMatch }, + } } fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool { @@ -992,19 +1009,40 @@ pub fn make_test_description( } }; } - ignore = match config.parse_cfg_name_directive(ln, "ignore") { - ParsedNameDirective::Match => { - ignore_message = Some("cfg -> ignore => Match"); - true - } - ParsedNameDirective::NoMatch => ignore, - }; + + { + let parsed = config.parse_cfg_name_directive(ln, "ignore"); + ignore = match parsed.outcome { + MatchOutcome::Match => { + ignore_message = Some(match parsed.comment { + // The ignore reason must be a &'static str, so we have to leak memory to + // create it. This is fine, as the header is parsed only at the start of + // compiletest so it won't grow indefinitely. + Some(comment) => Box::leak(Box::::from(format!( + "cfg -> ignore => Match ({comment})" + ))), + None => "cfg -> ignore => Match", + }); + true + } + MatchOutcome::NoMatch => ignore, + }; + } if config.has_cfg_prefix(ln, "only") { - ignore = match config.parse_cfg_name_directive(ln, "only") { - ParsedNameDirective::Match => ignore, - ParsedNameDirective::NoMatch => { - ignore_message = Some("cfg -> only => NoMatch"); + let parsed = config.parse_cfg_name_directive(ln, "only"); + ignore = match parsed.outcome { + MatchOutcome::Match => ignore, + MatchOutcome::NoMatch => { + ignore_message = Some(match parsed.comment { + // The ignore reason must be a &'static str, so we have to leak memory to + // create it. This is fine, as the header is parsed only at the start of + // compiletest so it won't grow indefinitely. + Some(comment) => Box::leak(Box::::from(format!( + "cfg -> only => NoMatch ({comment})" + ))), + None => "cfg -> only => NoMatch", + }); true } }; From 4e2a98268a3193e3161adafd4534c036f139da8f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 6 Mar 2023 12:10:55 +0100 Subject: [PATCH 025/267] include pretty reason why ignore-FOO matched --- src/tools/compiletest/src/common.rs | 16 +-- src/tools/compiletest/src/header.rs | 198 +++++++++++++++++++--------- 2 files changed, 141 insertions(+), 73 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 28c045f83824..496b83a956b9 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -159,7 +159,7 @@ pub enum Debugger { } impl Debugger { - fn to_str(&self) -> &'static str { + pub(crate) fn to_str(&self) -> &'static str { match self { Debugger::Cdb => "cdb", Debugger::Gdb => "gdb", @@ -396,7 +396,7 @@ impl Config { }) } - fn target_cfg(&self) -> &TargetCfg { + pub fn target_cfg(&self) -> &TargetCfg { self.target_cfg.borrow_with(|| TargetCfg::new(self)) } @@ -451,12 +451,12 @@ impl Config { #[derive(Clone, Debug)] pub struct TargetCfg { - arch: String, - os: String, - env: String, - abi: String, - families: Vec, - pointer_width: u32, + pub(crate) arch: String, + pub(crate) os: String, + pub(crate) env: String, + pub(crate) abi: String, + pub(crate) families: Vec, + pub(crate) pointer_width: u32, endian: Endian, panic: PanicStrategy, } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 15020a373f06..ea900ff068fc 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -8,7 +8,7 @@ use std::process::Command; use tracing::*; -use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PassMode}; +use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; use crate::util; use crate::{extract_cdb_version, extract_gdb_version}; @@ -17,14 +17,16 @@ mod tests; /// The result of parse_cfg_name_directive. #[derive(Clone, PartialEq, Debug)] -struct ParsedNameDirective { - comment: Option, +struct ParsedNameDirective<'a> { + name: Option<&'a str>, + pretty_reason: Option, + comment: Option<&'a str>, outcome: MatchOutcome, } -impl ParsedNameDirective { +impl ParsedNameDirective<'_> { fn invalid() -> Self { - Self { comment: None, outcome: MatchOutcome::NoMatch } + Self { name: None, pretty_reason: None, comment: None, outcome: MatchOutcome::NoMatch } } } @@ -678,7 +680,7 @@ impl Config { /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86` /// or `normalize-stderr-32bit`. - fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective { + fn parse_cfg_name_directive<'a>(&self, line: &'a str, prefix: &str) -> ParsedNameDirective<'a> { if !line.as_bytes().starts_with(prefix.as_bytes()) { return ParsedNameDirective::invalid(); } @@ -690,56 +692,124 @@ impl Config { let (name, comment) = line.split_once(&[':', ' ']).map(|(l, c)| (l, Some(c))).unwrap_or((line, None)); - let matches_pointer_width = || { - name.strip_suffix("bit") - .and_then(|width| width.parse::().ok()) - .map(|width| self.get_pointer_width() == width) - .unwrap_or(false) - }; + let mut is_match = None; + + macro_rules! maybe_condition { + (name: $name:expr, $(condition: $condition:expr,)? message: $($message:tt)*) => { + if let Some(expected) = $name { + if name == expected $(&& $condition)? { + is_match = Some(format!($($message)*)); + } + } + }; + } + macro_rules! condition { + (name: $name:expr, $(condition: $condition:expr,)? message: $($message:tt)*) => { + maybe_condition! { + name: Some($name), + $(condition: $condition,)* + message: $($message)* + } + }; + } + + condition! { + name: "test", + message: "always" + } + condition! { + name: &self.target, + message: "when the target is {name}" + } + + let target_cfg = self.target_cfg(); + condition! { + name: &target_cfg.os, + message: "when the operative system is {name}" + } + condition! { + name: &target_cfg.env, + message: "when the target environment is {name}" + } + condition! { + name: &target_cfg.abi, + message: "when the ABI is {name}" + } + condition! { + name: &target_cfg.arch, + message: "when the architecture is {name}" + } + condition! { + name: format!("{}bit", target_cfg.pointer_width), + message: "when the pointer width is {name}" + } + for family in &target_cfg.families { + condition! { + name: family, + message: "when the target family is {name}" + } + } // If something is ignored for emscripten, it likely also needs to be // ignored for wasm32-unknown-unknown. // `wasm32-bare` is an alias to refer to just wasm32-unknown-unknown // (in contrast to `wasm32` which also matches non-bare targets like // asmjs-unknown-emscripten). - let matches_wasm32_alias = || { - self.target == "wasm32-unknown-unknown" && matches!(name, "emscripten" | "wasm32-bare") - }; + condition! { + name: "emscripten", + condition: self.target == "wasm32-unknown-unknown", + message: "when the target is WASM", + } + condition! { + name: "wasm32-bare", + condition: self.target == "wasm32-unknown-unknown", + message: "when the target is WASM" + } - let is_match = name == "test" || - self.target == name || // triple - self.matches_os(name) || - self.matches_env(name) || - self.matches_abi(name) || - self.matches_family(name) || - self.target.ends_with(name) || // target and env - self.matches_arch(name) || - matches_wasm32_alias() || - matches_pointer_width() || - name == self.stage_id.split('-').next().unwrap() || // stage - name == self.channel || // channel - (self.target != self.host && name == "cross-compile") || - (name == "endian-big" && self.is_big_endian()) || - (self.remote_test_client.is_some() && name == "remote") || - match self.compare_mode { - Some(CompareMode::Polonius) => name == "compare-mode-polonius", - Some(CompareMode::Chalk) => name == "compare-mode-chalk", - Some(CompareMode::NextSolver) => name == "compare-mode-next-solver", - Some(CompareMode::SplitDwarf) => name == "compare-mode-split-dwarf", - Some(CompareMode::SplitDwarfSingle) => name == "compare-mode-split-dwarf-single", - None => false, - } || - (cfg!(debug_assertions) && name == "debug") || - match self.debugger { - Some(Debugger::Cdb) => name == "cdb", - Some(Debugger::Gdb) => name == "gdb", - Some(Debugger::Lldb) => name == "lldb", - None => false, - }; + condition! { + name: &self.channel, + message: "when the release channel is {name}", + } + condition! { + name: "cross-compile", + condition: self.target != self.host, + message: "when cross-compiling" + } + condition! { + name: "endian-big", + condition: self.is_big_endian(), + message: "on big-endian targets", + } + condition! { + name: self.stage_id.split('-').next().unwrap(), + message: "when the bootstrapping stage is {name}", + } + condition! { + name: "remote", + condition: self.remote_test_client.is_some(), + message: "when running tests remotely", + } + condition! { + name: "debug", + condition: cfg!(debug_assertions), + message: "when building with debug assertions", + } + maybe_condition! { + name: self.debugger.as_ref().map(|d| d.to_str()), + message: "when the debugger is {name}", + } + maybe_condition! { + name: self.compare_mode + .as_ref() + .map(|d| format!("compare-mode-{}", d.to_str())), + message: "when comparing with {name}", + } ParsedNameDirective { - comment: comment.map(|c| c.trim().trim_start_matches('-').trim().to_string()), - outcome: if is_match { MatchOutcome::Match } else { MatchOutcome::NoMatch }, + name: Some(name), + comment: comment.map(|c| c.trim().trim_start_matches('-').trim()), + outcome: if is_match.is_some() { MatchOutcome::Match } else { MatchOutcome::NoMatch }, + pretty_reason: is_match, } } @@ -1014,15 +1084,14 @@ pub fn make_test_description( let parsed = config.parse_cfg_name_directive(ln, "ignore"); ignore = match parsed.outcome { MatchOutcome::Match => { - ignore_message = Some(match parsed.comment { - // The ignore reason must be a &'static str, so we have to leak memory to - // create it. This is fine, as the header is parsed only at the start of - // compiletest so it won't grow indefinitely. - Some(comment) => Box::leak(Box::::from(format!( - "cfg -> ignore => Match ({comment})" - ))), - None => "cfg -> ignore => Match", - }); + let reason = parsed.pretty_reason.unwrap(); + // The ignore reason must be a &'static str, so we have to leak memory to + // create it. This is fine, as the header is parsed only at the start of + // compiletest so it won't grow indefinitely. + ignore_message = Some(Box::leak(Box::::from(match parsed.comment { + Some(comment) => format!("ignored {reason} ({comment})"), + None => format!("ignored {reason}"), + })) as &str); true } MatchOutcome::NoMatch => ignore, @@ -1034,15 +1103,14 @@ pub fn make_test_description( ignore = match parsed.outcome { MatchOutcome::Match => ignore, MatchOutcome::NoMatch => { - ignore_message = Some(match parsed.comment { - // The ignore reason must be a &'static str, so we have to leak memory to - // create it. This is fine, as the header is parsed only at the start of - // compiletest so it won't grow indefinitely. - Some(comment) => Box::leak(Box::::from(format!( - "cfg -> only => NoMatch ({comment})" - ))), - None => "cfg -> only => NoMatch", - }); + let name = parsed.name.unwrap(); + // The ignore reason must be a &'static str, so we have to leak memory to + // create it. This is fine, as the header is parsed only at the start of + // compiletest so it won't grow indefinitely. + ignore_message = Some(Box::leak(Box::::from(match parsed.comment { + Some(comment) => format!("did not match only-{name} ({comment})"), + None => format!("did not match only-{name}"), + })) as &str); true } }; From 9bc8bb91de5f5428da0d9f13c79bff68cf6f9b3c Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 8 Mar 2023 10:27:38 +0100 Subject: [PATCH 026/267] validate ignore-FOO/only-FOO directives and output only-FOO reasoning --- src/tools/compiletest/src/common.rs | 118 ++++++++++++++++++++++------ src/tools/compiletest/src/header.rs | 96 ++++++++++++++++++---- src/tools/compiletest/src/main.rs | 2 +- 3 files changed, 178 insertions(+), 38 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 496b83a956b9..9df5c298757d 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -9,6 +9,7 @@ use std::str::FromStr; use crate::util::{add_dylib_path, PathBufExt}; use lazycell::LazyCell; +use std::collections::HashSet; use test::{ColorConfig, OutputFormat}; #[derive(Clone, Copy, PartialEq, Debug)] @@ -129,6 +130,14 @@ pub enum CompareMode { } impl CompareMode { + pub(crate) const VARIANTS: &'static [CompareMode] = &[ + CompareMode::Polonius, + CompareMode::Chalk, + CompareMode::NextSolver, + CompareMode::SplitDwarf, + CompareMode::SplitDwarfSingle, + ]; + pub(crate) fn to_str(&self) -> &'static str { match *self { CompareMode::Polonius => "polonius", @@ -159,6 +168,9 @@ pub enum Debugger { } impl Debugger { + pub(crate) const VARIANTS: &'static [Debugger] = + &[Debugger::Cdb, Debugger::Gdb, Debugger::Lldb]; + pub(crate) fn to_str(&self) -> &'static str { match self { Debugger::Cdb => "cdb", @@ -396,8 +408,12 @@ impl Config { }) } + pub fn target_cfgs(&self) -> &TargetCfgs { + self.target_cfgs.borrow_with(|| TargetCfgs::new(self)) + } + pub fn target_cfg(&self) -> &TargetCfg { - self.target_cfg.borrow_with(|| TargetCfg::new(self)) + &self.target_cfgs().current } pub fn matches_arch(&self, arch: &str) -> bool { @@ -449,6 +465,63 @@ impl Config { } } +#[derive(Debug, Clone)] +pub struct TargetCfgs { + pub current: TargetCfg, + pub all_targets: HashSet, + pub all_archs: HashSet, + pub all_oses: HashSet, + pub all_envs: HashSet, + pub all_abis: HashSet, + pub all_families: HashSet, + pub all_pointer_widths: HashSet, +} + +impl TargetCfgs { + fn new(config: &Config) -> TargetCfgs { + // Gather list of all targets + let targets = rustc_output(config, &["--print=target-list"]); + + let mut current = None; + let mut all_targets = HashSet::new(); + let mut all_archs = HashSet::new(); + let mut all_oses = HashSet::new(); + let mut all_envs = HashSet::new(); + let mut all_abis = HashSet::new(); + let mut all_families = HashSet::new(); + let mut all_pointer_widths = HashSet::new(); + + for target in targets.trim().lines() { + let cfg = TargetCfg::new(config, target); + + all_archs.insert(cfg.arch.clone()); + all_oses.insert(cfg.os.clone()); + all_envs.insert(cfg.env.clone()); + all_abis.insert(cfg.abi.clone()); + for family in &cfg.families { + all_families.insert(family.clone()); + } + all_pointer_widths.insert(format!("{}bit", cfg.pointer_width)); + + if target == config.target { + current = Some(cfg); + } + all_targets.insert(target.into()); + } + + Self { + current: current.expect("current target not found"), + all_targets, + all_archs, + all_oses, + all_envs, + all_abis, + all_families, + all_pointer_widths, + } + } +} + #[derive(Clone, Debug)] pub struct TargetCfg { pub(crate) arch: String, @@ -468,28 +541,8 @@ pub enum Endian { } impl TargetCfg { - fn new(config: &Config) -> TargetCfg { - let mut command = Command::new(&config.rustc_path); - add_dylib_path(&mut command, iter::once(&config.compile_lib_path)); - let output = match command - .arg("--print=cfg") - .arg("--target") - .arg(&config.target) - .args(&config.target_rustcflags) - .output() - { - Ok(output) => output, - Err(e) => panic!("error: failed to get cfg info from {:?}: {e}", config.rustc_path), - }; - if !output.status.success() { - panic!( - "error: failed to get cfg info from {:?}\n--- stdout\n{}\n--- stderr\n{}", - config.rustc_path, - String::from_utf8(output.stdout).unwrap(), - String::from_utf8(output.stderr).unwrap(), - ); - } - let print_cfg = String::from_utf8(output.stdout).unwrap(); + fn new(config: &Config, target: &str) -> TargetCfg { + let print_cfg = rustc_output(config, &["--print=cfg", "--target", target]); let mut arch = None; let mut os = None; let mut env = None; @@ -539,6 +592,25 @@ impl TargetCfg { } } +fn rustc_output(config: &Config, args: &[&str]) -> String { + let mut command = Command::new(&config.rustc_path); + add_dylib_path(&mut command, iter::once(&config.compile_lib_path)); + command.args(&config.target_rustcflags).args(args); + + let output = match command.output() { + Ok(output) => output, + Err(e) => panic!("error: failed to run {command:?}: {e}"), + }; + if !output.status.success() { + panic!( + "error: failed to run {command:?}\n--- stdout\n{}\n--- stderr\n{}", + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap(), + ); + } + String::from_utf8(output.stdout).unwrap() +} + #[derive(Debug, Clone)] pub struct TestPaths { pub file: PathBuf, // e.g., compile-test/foo/bar/baz.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index ea900ff068fc..71e1072ceb37 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -8,6 +8,7 @@ use std::process::Command; use tracing::*; +use crate::common::CompareMode; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; use crate::util; use crate::{extract_cdb_version, extract_gdb_version}; @@ -36,6 +37,10 @@ enum MatchOutcome { NoMatch, /// Match. Match, + /// The directive was invalid. + Invalid, + /// The directive is handled by other parts of our tooling. + External, } /// Properties which must be known very early, before actually running @@ -692,26 +697,60 @@ impl Config { let (name, comment) = line.split_once(&[':', ' ']).map(|(l, c)| (l, Some(c))).unwrap_or((line, None)); - let mut is_match = None; + let mut outcome = MatchOutcome::Invalid; + let mut message = None; macro_rules! maybe_condition { - (name: $name:expr, $(condition: $condition:expr,)? message: $($message:tt)*) => { - if let Some(expected) = $name { - if name == expected $(&& $condition)? { - is_match = Some(format!($($message)*)); + ( + name: $name:expr, + $(allowed_names: $allowed_names:expr,)? + $(condition: $condition:expr,)? + message: $($message:tt)* + ) => {{ + // This is not inlined to avoid problems with macro repetitions. + let format_message = || format!($($message)*); + + if outcome != MatchOutcome::Invalid { + // Ignore all other matches if we already found one + } else if $name.as_ref().map(|n| n == &name).unwrap_or(false) { + message = Some(format_message()); + if true $(&& $condition)? { + outcome = MatchOutcome::Match; + } else { + outcome = MatchOutcome::NoMatch; } } - }; + $(else if $allowed_names.contains(name) { + message = Some(format_message()); + outcome = MatchOutcome::NoMatch; + })? + }}; } macro_rules! condition { - (name: $name:expr, $(condition: $condition:expr,)? message: $($message:tt)*) => { + ( + name: $name:expr, + $(allowed_names: $allowed_names:expr,)? + $(condition: $condition:expr,)? + message: $($message:tt)* + ) => { maybe_condition! { name: Some($name), + $(allowed_names: $allowed_names,)* $(condition: $condition,)* message: $($message)* } }; } + macro_rules! hashset { + ($($value:expr),* $(,)?) => {{ + let mut set = HashSet::new(); + $(set.insert($value);)* + set + }} + } + + let target_cfgs = self.target_cfgs(); + let target_cfg = self.target_cfg(); condition! { name: "test", @@ -719,33 +758,38 @@ impl Config { } condition! { name: &self.target, + allowed_names: &target_cfgs.all_targets, message: "when the target is {name}" } - - let target_cfg = self.target_cfg(); condition! { name: &target_cfg.os, + allowed_names: &target_cfgs.all_oses, message: "when the operative system is {name}" } condition! { name: &target_cfg.env, + allowed_names: &target_cfgs.all_envs, message: "when the target environment is {name}" } condition! { name: &target_cfg.abi, + allowed_names: &target_cfgs.all_abis, message: "when the ABI is {name}" } condition! { name: &target_cfg.arch, + allowed_names: &target_cfgs.all_archs, message: "when the architecture is {name}" } condition! { name: format!("{}bit", target_cfg.pointer_width), + allowed_names: &target_cfgs.all_pointer_widths, message: "when the pointer width is {name}" } for family in &target_cfg.families { condition! { name: family, + allowed_names: &target_cfgs.all_families, message: "when the target family is {name}" } } @@ -768,6 +812,7 @@ impl Config { condition! { name: &self.channel, + allowed_names: hashset!["stable", "beta", "nightly"], message: "when the release channel is {name}", } condition! { @@ -782,6 +827,7 @@ impl Config { } condition! { name: self.stage_id.split('-').next().unwrap(), + allowed_names: hashset!["stable", "beta", "nightly"], message: "when the bootstrapping stage is {name}", } condition! { @@ -796,20 +842,38 @@ impl Config { } maybe_condition! { name: self.debugger.as_ref().map(|d| d.to_str()), + allowed_names: Debugger::VARIANTS + .iter() + .map(|v| v.to_str()) + .collect::>(), message: "when the debugger is {name}", } maybe_condition! { name: self.compare_mode .as_ref() .map(|d| format!("compare-mode-{}", d.to_str())), + allowed_names: CompareMode::VARIANTS + .iter() + .map(|cm| format!("compare-mode-{}", cm.to_str())) + .collect::>(), message: "when comparing with {name}", } + // Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest. + if prefix == "ignore" && name.starts_with("tidy-") && outcome == MatchOutcome::Invalid { + outcome = MatchOutcome::External; + } + + // Don't error out for ignore-pass, as that is handled elsewhere. + if prefix == "ignore" && name == "pass" && outcome == MatchOutcome::Invalid { + outcome = MatchOutcome::External; + } + ParsedNameDirective { name: Some(name), comment: comment.map(|c| c.trim().trim_start_matches('-').trim()), - outcome: if is_match.is_some() { MatchOutcome::Match } else { MatchOutcome::NoMatch }, - pretty_reason: is_match, + outcome, + pretty_reason: message, } } @@ -1095,6 +1159,8 @@ pub fn make_test_description( true } MatchOutcome::NoMatch => ignore, + MatchOutcome::External => ignore, + MatchOutcome::Invalid => panic!("invalid line in {}: {ln}", path.display()), }; } @@ -1103,16 +1169,18 @@ pub fn make_test_description( ignore = match parsed.outcome { MatchOutcome::Match => ignore, MatchOutcome::NoMatch => { - let name = parsed.name.unwrap(); + let reason = parsed.pretty_reason.unwrap(); // The ignore reason must be a &'static str, so we have to leak memory to // create it. This is fine, as the header is parsed only at the start of // compiletest so it won't grow indefinitely. ignore_message = Some(Box::leak(Box::::from(match parsed.comment { - Some(comment) => format!("did not match only-{name} ({comment})"), - None => format!("did not match only-{name}"), + Some(comment) => format!("only executed {reason} ({comment})"), + None => format!("only executed {reason}"), })) as &str); true } + MatchOutcome::External => ignore, + MatchOutcome::Invalid => panic!("invalid line in {}: {ln}", path.display()), }; } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 7048b0e08bbf..b10c2d36d602 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -311,7 +311,7 @@ pub fn parse_config(args: Vec) -> Config { force_rerun: matches.opt_present("force-rerun"), - target_cfg: LazyCell::new(), + target_cfgs: LazyCell::new(), nocapture: matches.opt_present("nocapture"), } From 0aaf9d58a24a6efba88842318b4c66d0b7418867 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 8 Mar 2023 14:28:57 +0100 Subject: [PATCH 027/267] reduce boilerplate with common enums --- src/tools/compiletest/src/common.rs | 218 ++++++++++------------------ src/tools/compiletest/src/main.rs | 6 +- 2 files changed, 77 insertions(+), 147 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 9df5c298757d..86810179ff8b 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -12,21 +12,59 @@ use lazycell::LazyCell; use std::collections::HashSet; use test::{ColorConfig, OutputFormat}; -#[derive(Clone, Copy, PartialEq, Debug)] -pub enum Mode { - RunPassValgrind, - Pretty, - DebugInfo, - Codegen, - Rustdoc, - RustdocJson, - CodegenUnits, - Incremental, - RunMake, - Ui, - JsDocTest, - MirOpt, - Assembly, +macro_rules! string_enum { + ($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => { + $(#[$meta])* + $vis enum $name { + $($variant,)* + } + + impl $name { + $vis const VARIANTS: &'static [Self] = &[$(Self::$variant,)*]; + + $vis fn to_str(&self) -> &'static str { + match self { + $(Self::$variant => $repr,)* + } + } + } + + impl fmt::Display for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.to_str(), f) + } + } + + impl FromStr for $name { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + $($repr => Ok(Self::$variant),)* + _ => Err(()), + } + } + } + } +} + +string_enum! { + #[derive(Clone, Copy, PartialEq, Debug)] + pub enum Mode { + RunPassValgrind => "run-pass-valgrind", + Pretty => "pretty", + DebugInfo => "debuginfo", + Codegen => "codegen", + Rustdoc => "rustdoc", + RustdocJson => "rustdoc-json", + CodegenUnits => "codegen-units", + Incremental => "incremental", + RunMake => "run-make", + Ui => "ui", + JsDocTest => "js-doc-test", + MirOpt => "mir-opt", + Assembly => "assembly", + } } impl Mode { @@ -40,76 +78,12 @@ impl Mode { } } -impl FromStr for Mode { - type Err = (); - fn from_str(s: &str) -> Result { - match s { - "run-pass-valgrind" => Ok(RunPassValgrind), - "pretty" => Ok(Pretty), - "debuginfo" => Ok(DebugInfo), - "codegen" => Ok(Codegen), - "rustdoc" => Ok(Rustdoc), - "rustdoc-json" => Ok(RustdocJson), - "codegen-units" => Ok(CodegenUnits), - "incremental" => Ok(Incremental), - "run-make" => Ok(RunMake), - "ui" => Ok(Ui), - "js-doc-test" => Ok(JsDocTest), - "mir-opt" => Ok(MirOpt), - "assembly" => Ok(Assembly), - _ => Err(()), - } - } -} - -impl fmt::Display for Mode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s = match *self { - RunPassValgrind => "run-pass-valgrind", - Pretty => "pretty", - DebugInfo => "debuginfo", - Codegen => "codegen", - Rustdoc => "rustdoc", - RustdocJson => "rustdoc-json", - CodegenUnits => "codegen-units", - Incremental => "incremental", - RunMake => "run-make", - Ui => "ui", - JsDocTest => "js-doc-test", - MirOpt => "mir-opt", - Assembly => "assembly", - }; - fmt::Display::fmt(s, f) - } -} - -#[derive(Clone, Copy, PartialEq, Debug, Hash)] -pub enum PassMode { - Check, - Build, - Run, -} - -impl FromStr for PassMode { - type Err = (); - fn from_str(s: &str) -> Result { - match s { - "check" => Ok(PassMode::Check), - "build" => Ok(PassMode::Build), - "run" => Ok(PassMode::Run), - _ => Err(()), - } - } -} - -impl fmt::Display for PassMode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s = match *self { - PassMode::Check => "check", - PassMode::Build => "build", - PassMode::Run => "run", - }; - fmt::Display::fmt(s, f) +string_enum! { + #[derive(Clone, Copy, PartialEq, Debug, Hash)] + pub enum PassMode { + Check => "check", + Build => "build", + Run => "run", } } @@ -120,69 +94,23 @@ pub enum FailMode { Run, } -#[derive(Clone, Debug, PartialEq)] -pub enum CompareMode { - Polonius, - Chalk, - NextSolver, - SplitDwarf, - SplitDwarfSingle, -} - -impl CompareMode { - pub(crate) const VARIANTS: &'static [CompareMode] = &[ - CompareMode::Polonius, - CompareMode::Chalk, - CompareMode::NextSolver, - CompareMode::SplitDwarf, - CompareMode::SplitDwarfSingle, - ]; - - pub(crate) fn to_str(&self) -> &'static str { - match *self { - CompareMode::Polonius => "polonius", - CompareMode::Chalk => "chalk", - CompareMode::NextSolver => "next-solver", - CompareMode::SplitDwarf => "split-dwarf", - CompareMode::SplitDwarfSingle => "split-dwarf-single", - } - } - - pub fn parse(s: String) -> CompareMode { - match s.as_str() { - "polonius" => CompareMode::Polonius, - "chalk" => CompareMode::Chalk, - "next-solver" => CompareMode::NextSolver, - "split-dwarf" => CompareMode::SplitDwarf, - "split-dwarf-single" => CompareMode::SplitDwarfSingle, - x => panic!("unknown --compare-mode option: {}", x), - } +string_enum! { + #[derive(Clone, Debug, PartialEq)] + pub enum CompareMode { + Polonius => "polonius", + Chalk => "chalk", + NextSolver => "next-solver", + SplitDwarf => "split-dwarf", + SplitDwarfSingle => "split-dwarf-single", } } -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum Debugger { - Cdb, - Gdb, - Lldb, -} - -impl Debugger { - pub(crate) const VARIANTS: &'static [Debugger] = - &[Debugger::Cdb, Debugger::Gdb, Debugger::Lldb]; - - pub(crate) fn to_str(&self) -> &'static str { - match self { - Debugger::Cdb => "cdb", - Debugger::Gdb => "gdb", - Debugger::Lldb => "lldb", - } - } -} - -impl fmt::Display for Debugger { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self.to_str(), f) +string_enum! { + #[derive(Clone, Copy, Debug, PartialEq)] + pub enum Debugger { + Cdb => "cdb", + Gdb => "gdb", + Lldb => "lldb", } } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index b10c2d36d602..7700db0c74d8 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -6,7 +6,7 @@ extern crate test; use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS}; -use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, TestPaths}; +use crate::common::{Config, Debugger, Mode, PassMode, TestPaths}; use crate::util::logv; use build_helper::git::{get_git_modified_files, get_git_untracked_files}; use core::panic; @@ -293,7 +293,9 @@ pub fn parse_config(args: Vec) -> Config { only_modified: matches.opt_present("only-modified"), color, remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from), - compare_mode: matches.opt_str("compare-mode").map(CompareMode::parse), + compare_mode: matches + .opt_str("compare-mode") + .map(|s| s.parse().expect("invalid --compare-mode provided")), rustfix_coverage: matches.opt_present("rustfix-coverage"), has_tidy, channel: matches.opt_str("channel").unwrap(), From 703ba0ce260b76b0ea4aefb0bfe2a66df2f822a2 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 8 Mar 2023 10:12:27 +0100 Subject: [PATCH 028/267] fix ignore-thumbv8m.base --- tests/ui/attributes/issue-105594-invalid-attr-validation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs index 6c68e6b046f0..096ce97ab048 100644 --- a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs +++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs @@ -1,7 +1,7 @@ // This checks that the attribute validation ICE in issue #105594 doesn't // recur. // -// ignore-thumbv8m.base +// ignore-thumbv8m.base-none-eabi #![feature(cmse_nonsecure_entry)] fn main() {} From 8dd6c193797a528ecd203c7268497c6add7ad5a5 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 8 Mar 2023 10:25:46 +0100 Subject: [PATCH 029/267] split invalid only-x86-windows into only-x86 and only-windows --- tests/ui/symbol-names/x86-stdcall.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ui/symbol-names/x86-stdcall.rs b/tests/ui/symbol-names/x86-stdcall.rs index 9948488c0e95..dd0e5477e2e1 100644 --- a/tests/ui/symbol-names/x86-stdcall.rs +++ b/tests/ui/symbol-names/x86-stdcall.rs @@ -1,5 +1,6 @@ // build-pass -// only-x86-windows +// only-x86 +// only-windows #![crate_type = "cdylib"] #![feature(abi_vectorcall)] From 64af5093774f355875b6f0df339a392f153cc962 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 8 Mar 2023 10:13:02 +0100 Subject: [PATCH 030/267] remove invalid ignore-pretty --- tests/ui/abi/stack-probes-lto.rs | 1 - tests/ui/binding/optional_comma_in_match_arm.rs | 1 - tests/ui/borrowck/borrowck-pat-enum.rs | 1 - tests/ui/command/command-exec.rs | 1 - tests/ui/hygiene/arguments.rs | 2 -- tests/ui/hygiene/arguments.stderr | 2 +- tests/ui/hygiene/assoc_item_ctxt.rs | 2 -- tests/ui/hygiene/assoc_item_ctxt.stderr | 4 ++-- tests/ui/hygiene/assoc_ty_bindings.rs | 1 - tests/ui/hygiene/auxiliary/legacy_interaction.rs | 2 -- tests/ui/hygiene/fields.rs | 2 -- tests/ui/hygiene/fields.stderr | 8 ++++---- tests/ui/hygiene/generic_params.rs | 1 - tests/ui/hygiene/impl_items.rs | 2 -- tests/ui/hygiene/impl_items.stderr | 2 +- tests/ui/hygiene/intercrate.rs | 2 -- tests/ui/hygiene/intercrate.stderr | 2 +- tests/ui/hygiene/issue-47311.rs | 1 - tests/ui/hygiene/issue-47312.rs | 1 - tests/ui/hygiene/items.rs | 1 - tests/ui/hygiene/legacy_interaction.rs | 1 - tests/ui/hygiene/lexical.rs | 1 - tests/ui/hygiene/specialization.rs | 1 - tests/ui/hygiene/trait_items-2.rs | 1 - tests/ui/hygiene/wrap_unhygienic_example.rs | 1 - tests/ui/hygiene/xcrate.rs | 1 - .../issue-26873-multifile/issue-26873-multifile.rs | 1 - tests/ui/issues/issue-11709.rs | 1 - tests/ui/issues/issue-28839.rs | 1 - tests/ui/issues/issue-38190.rs | 1 - tests/ui/issues/issue-9129.rs | 1 - .../lexer-crlf-line-endings-string-literal-doc-comment.rs | 1 - tests/ui/macros/issue-40469.rs | 1 - tests/ui/macros/macro-comma-support-rpass.rs | 1 - tests/ui/macros/macro-include-items.rs | 1 - tests/ui/macros/syntax-extension-source-utils.rs | 7 +++---- tests/ui/modules/mod_dir_implicit.rs | 1 - tests/ui/modules/mod_dir_path.rs | 1 - tests/ui/modules/mod_dir_path2.rs | 1 - tests/ui/modules/mod_dir_path3.rs | 1 - tests/ui/modules/mod_dir_path_multi.rs | 1 - tests/ui/modules/mod_dir_recursive.rs | 1 - tests/ui/modules/mod_dir_simple.rs | 1 - tests/ui/modules/mod_file.rs | 1 - tests/ui/modules/mod_file_with_path_attr.rs | 1 - tests/ui/non_modrs_mods/non_modrs_mods.rs | 1 - tests/ui/parser/issues/issue-48508.rs | 1 - tests/ui/proc-macro/span-api-tests.rs | 1 - tests/ui/runtime/backtrace-debuginfo.rs | 1 - tests/ui/traits/dyn-trait.rs | 1 - 50 files changed, 12 insertions(+), 63 deletions(-) diff --git a/tests/ui/abi/stack-probes-lto.rs b/tests/ui/abi/stack-probes-lto.rs index a455eef42eac..039507d51040 100644 --- a/tests/ui/abi/stack-probes-lto.rs +++ b/tests/ui/abi/stack-probes-lto.rs @@ -9,7 +9,6 @@ // ignore-emscripten no processes // ignore-sgx no processes // ignore-musl FIXME #31506 -// ignore-pretty // ignore-fuchsia no exception handler registered for segfault // compile-flags: -C lto // no-prefer-dynamic diff --git a/tests/ui/binding/optional_comma_in_match_arm.rs b/tests/ui/binding/optional_comma_in_match_arm.rs index fc268bf2a45a..71e2f07bb6b0 100644 --- a/tests/ui/binding/optional_comma_in_match_arm.rs +++ b/tests/ui/binding/optional_comma_in_match_arm.rs @@ -1,6 +1,5 @@ // run-pass #![allow(unused_unsafe)] -// ignore-pretty issue #37199 #![allow(while_true)] fn main() { diff --git a/tests/ui/borrowck/borrowck-pat-enum.rs b/tests/ui/borrowck/borrowck-pat-enum.rs index 7f9c5544d0bd..6e51a2b2e027 100644 --- a/tests/ui/borrowck/borrowck-pat-enum.rs +++ b/tests/ui/borrowck/borrowck-pat-enum.rs @@ -1,6 +1,5 @@ // run-pass #![allow(dead_code)] -// ignore-pretty issue #37199 fn match_ref(v: Option) -> isize { match v { diff --git a/tests/ui/command/command-exec.rs b/tests/ui/command/command-exec.rs index 032dad1840d4..edc33446d79b 100644 --- a/tests/ui/command/command-exec.rs +++ b/tests/ui/command/command-exec.rs @@ -2,7 +2,6 @@ #![allow(stable_features)] // ignore-windows - this is a unix-specific test -// ignore-pretty issue #37199 // ignore-emscripten no processes // ignore-sgx no processes // ignore-fuchsia no execvp syscall provided diff --git a/tests/ui/hygiene/arguments.rs b/tests/ui/hygiene/arguments.rs index f0f732f4c6ff..ab58301d468b 100644 --- a/tests/ui/hygiene/arguments.rs +++ b/tests/ui/hygiene/arguments.rs @@ -1,5 +1,3 @@ -// ignore-pretty pretty-printing is unhygienic - #![feature(decl_macro)] macro m($t:ty, $e:expr) { diff --git a/tests/ui/hygiene/arguments.stderr b/tests/ui/hygiene/arguments.stderr index d072086e086d..714178375f2d 100644 --- a/tests/ui/hygiene/arguments.stderr +++ b/tests/ui/hygiene/arguments.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `S` in this scope - --> $DIR/arguments.rs:16:8 + --> $DIR/arguments.rs:14:8 | LL | m!(S, S); | ^ not found in this scope diff --git a/tests/ui/hygiene/assoc_item_ctxt.rs b/tests/ui/hygiene/assoc_item_ctxt.rs index 65593d1d5607..f09f81a5d52d 100644 --- a/tests/ui/hygiene/assoc_item_ctxt.rs +++ b/tests/ui/hygiene/assoc_item_ctxt.rs @@ -1,5 +1,3 @@ -// ignore-pretty pretty-printing is unhygienic - #![feature(decl_macro)] #![allow(unused)] diff --git a/tests/ui/hygiene/assoc_item_ctxt.stderr b/tests/ui/hygiene/assoc_item_ctxt.stderr index d65716ec2ce6..effa9e8d6559 100644 --- a/tests/ui/hygiene/assoc_item_ctxt.stderr +++ b/tests/ui/hygiene/assoc_item_ctxt.stderr @@ -1,5 +1,5 @@ error[E0407]: method `method` is not a member of trait `Tr` - --> $DIR/assoc_item_ctxt.rs:35:13 + --> $DIR/assoc_item_ctxt.rs:33:13 | LL | fn method() {} | ^^^------^^^^^ @@ -13,7 +13,7 @@ LL | mac_trait_impl!(); = note: this error originates in the macro `mac_trait_impl` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0046]: not all trait items implemented, missing: `method` - --> $DIR/assoc_item_ctxt.rs:34:9 + --> $DIR/assoc_item_ctxt.rs:32:9 | LL | fn method(); | ------------ `method` from trait diff --git a/tests/ui/hygiene/assoc_ty_bindings.rs b/tests/ui/hygiene/assoc_ty_bindings.rs index 0567beab9b9c..a78612749329 100644 --- a/tests/ui/hygiene/assoc_ty_bindings.rs +++ b/tests/ui/hygiene/assoc_ty_bindings.rs @@ -1,5 +1,4 @@ // check-pass -// ignore-pretty pretty-printing is unhygienic #![feature(decl_macro, associated_type_defaults)] diff --git a/tests/ui/hygiene/auxiliary/legacy_interaction.rs b/tests/ui/hygiene/auxiliary/legacy_interaction.rs index 90d5243b74b7..3293e346dade 100644 --- a/tests/ui/hygiene/auxiliary/legacy_interaction.rs +++ b/tests/ui/hygiene/auxiliary/legacy_interaction.rs @@ -1,5 +1,3 @@ -// ignore-pretty pretty-printing is unhygienic - #[macro_export] macro_rules! m { () => { diff --git a/tests/ui/hygiene/fields.rs b/tests/ui/hygiene/fields.rs index 7a417b46fcc9..86b3d8151d04 100644 --- a/tests/ui/hygiene/fields.rs +++ b/tests/ui/hygiene/fields.rs @@ -1,5 +1,3 @@ -// ignore-pretty pretty-printing is unhygienic - #![feature(decl_macro)] mod foo { diff --git a/tests/ui/hygiene/fields.stderr b/tests/ui/hygiene/fields.stderr index 978120b1f101..99252c4b752c 100644 --- a/tests/ui/hygiene/fields.stderr +++ b/tests/ui/hygiene/fields.stderr @@ -1,5 +1,5 @@ error: type `foo::S` is private - --> $DIR/fields.rs:15:17 + --> $DIR/fields.rs:13:17 | LL | let s = S { x: 0 }; | ^^^^^^^^^^ private type @@ -10,7 +10,7 @@ LL | let s = foo::m!(S, x); = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `foo::S` is private - --> $DIR/fields.rs:16:17 + --> $DIR/fields.rs:14:17 | LL | let _ = s.x; | ^ private type @@ -21,7 +21,7 @@ LL | let s = foo::m!(S, x); = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `T` is private - --> $DIR/fields.rs:18:17 + --> $DIR/fields.rs:16:17 | LL | let t = T(0); | ^^^^ private type @@ -32,7 +32,7 @@ LL | let s = foo::m!(S, x); = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `T` is private - --> $DIR/fields.rs:19:17 + --> $DIR/fields.rs:17:17 | LL | let _ = t.0; | ^ private type diff --git a/tests/ui/hygiene/generic_params.rs b/tests/ui/hygiene/generic_params.rs index 3b6216c3e637..b42152955f77 100644 --- a/tests/ui/hygiene/generic_params.rs +++ b/tests/ui/hygiene/generic_params.rs @@ -1,7 +1,6 @@ // Ensure that generic parameters always have modern hygiene. // check-pass -// ignore-pretty pretty-printing is unhygienic #![feature(decl_macro, rustc_attrs)] diff --git a/tests/ui/hygiene/impl_items.rs b/tests/ui/hygiene/impl_items.rs index ddb25c06b1b1..51088e3693d7 100644 --- a/tests/ui/hygiene/impl_items.rs +++ b/tests/ui/hygiene/impl_items.rs @@ -1,5 +1,3 @@ -// ignore-pretty pretty-printing is unhygienic - #![feature(decl_macro)] mod foo { diff --git a/tests/ui/hygiene/impl_items.stderr b/tests/ui/hygiene/impl_items.stderr index 46a2500386e0..32ba3741a59e 100644 --- a/tests/ui/hygiene/impl_items.stderr +++ b/tests/ui/hygiene/impl_items.stderr @@ -1,5 +1,5 @@ error: type `for<'a> fn(&'a foo::S) {foo::S::f}` is private - --> $DIR/impl_items.rs:12:23 + --> $DIR/impl_items.rs:10:23 | LL | let _: () = S.f(); | ^ private type diff --git a/tests/ui/hygiene/intercrate.rs b/tests/ui/hygiene/intercrate.rs index d9b5b789e4ab..2de62f6aff77 100644 --- a/tests/ui/hygiene/intercrate.rs +++ b/tests/ui/hygiene/intercrate.rs @@ -1,5 +1,3 @@ -// ignore-pretty pretty-printing is unhygienic - // aux-build:intercrate.rs #![feature(decl_macro)] diff --git a/tests/ui/hygiene/intercrate.stderr b/tests/ui/hygiene/intercrate.stderr index 91358b279e2b..f108617fba61 100644 --- a/tests/ui/hygiene/intercrate.stderr +++ b/tests/ui/hygiene/intercrate.stderr @@ -1,5 +1,5 @@ error: type `fn() -> u32 {foo::bar::f}` is private - --> $DIR/intercrate.rs:10:16 + --> $DIR/intercrate.rs:8:16 | LL | assert_eq!(intercrate::foo::m!(), 1); | ^^^^^^^^^^^^^^^^^^^^^ private type diff --git a/tests/ui/hygiene/issue-47311.rs b/tests/ui/hygiene/issue-47311.rs index 5c2379a8abab..3f1b7397301c 100644 --- a/tests/ui/hygiene/issue-47311.rs +++ b/tests/ui/hygiene/issue-47311.rs @@ -1,5 +1,4 @@ // check-pass -// ignore-pretty pretty-printing is unhygienic #![feature(decl_macro)] #![allow(unused)] diff --git a/tests/ui/hygiene/issue-47312.rs b/tests/ui/hygiene/issue-47312.rs index bbcb3a7f3931..c8b5c36767cf 100644 --- a/tests/ui/hygiene/issue-47312.rs +++ b/tests/ui/hygiene/issue-47312.rs @@ -1,5 +1,4 @@ // check-pass -// ignore-pretty pretty-printing is unhygienic #![feature(decl_macro)] #![allow(unused)] diff --git a/tests/ui/hygiene/items.rs b/tests/ui/hygiene/items.rs index 1c625a9728c4..a7ed749f526e 100644 --- a/tests/ui/hygiene/items.rs +++ b/tests/ui/hygiene/items.rs @@ -1,5 +1,4 @@ // check-pass -// ignore-pretty pretty-printing is unhygienic #![feature(decl_macro)] diff --git a/tests/ui/hygiene/legacy_interaction.rs b/tests/ui/hygiene/legacy_interaction.rs index 52008eed5151..4d150baf5d49 100644 --- a/tests/ui/hygiene/legacy_interaction.rs +++ b/tests/ui/hygiene/legacy_interaction.rs @@ -1,6 +1,5 @@ // check-pass #![allow(dead_code)] -// ignore-pretty pretty-printing is unhygienic // aux-build:legacy_interaction.rs diff --git a/tests/ui/hygiene/lexical.rs b/tests/ui/hygiene/lexical.rs index 3d25c720989b..81de974c2035 100644 --- a/tests/ui/hygiene/lexical.rs +++ b/tests/ui/hygiene/lexical.rs @@ -1,5 +1,4 @@ // check-pass -// ignore-pretty pretty-printing is unhygienic #![feature(decl_macro)] diff --git a/tests/ui/hygiene/specialization.rs b/tests/ui/hygiene/specialization.rs index 656aa880ad1f..b8c4c1b0d587 100644 --- a/tests/ui/hygiene/specialization.rs +++ b/tests/ui/hygiene/specialization.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty pretty-printing is unhygienic #![feature(decl_macro)] diff --git a/tests/ui/hygiene/trait_items-2.rs b/tests/ui/hygiene/trait_items-2.rs index 39edfc37d697..cd9122656cd2 100644 --- a/tests/ui/hygiene/trait_items-2.rs +++ b/tests/ui/hygiene/trait_items-2.rs @@ -1,5 +1,4 @@ // check-pass -// ignore-pretty pretty-printing is unhygienic #![feature(decl_macro)] diff --git a/tests/ui/hygiene/wrap_unhygienic_example.rs b/tests/ui/hygiene/wrap_unhygienic_example.rs index 50c6b35ab18d..f6b48156888c 100644 --- a/tests/ui/hygiene/wrap_unhygienic_example.rs +++ b/tests/ui/hygiene/wrap_unhygienic_example.rs @@ -1,5 +1,4 @@ // check-pass -// ignore-pretty pretty-printing is unhygienic // aux-build:my_crate.rs // aux-build:unhygienic_example.rs diff --git a/tests/ui/hygiene/xcrate.rs b/tests/ui/hygiene/xcrate.rs index 6981ce3f687d..6366bebb52f3 100644 --- a/tests/ui/hygiene/xcrate.rs +++ b/tests/ui/hygiene/xcrate.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty pretty-printing is unhygienic // aux-build:xcrate.rs diff --git a/tests/ui/imports/issue-26873-multifile/issue-26873-multifile.rs b/tests/ui/imports/issue-26873-multifile/issue-26873-multifile.rs index da2acf6c9f70..d369f1e71d06 100644 --- a/tests/ui/imports/issue-26873-multifile/issue-26873-multifile.rs +++ b/tests/ui/imports/issue-26873-multifile/issue-26873-multifile.rs @@ -3,7 +3,6 @@ #![allow(unused_imports)] #![allow(non_snake_case)] -// ignore-pretty issue #37195 #[path = "issue-26873-multifile/mod.rs"] mod multifile; diff --git a/tests/ui/issues/issue-11709.rs b/tests/ui/issues/issue-11709.rs index cb5e3dff3b31..58424f9e4c58 100644 --- a/tests/ui/issues/issue-11709.rs +++ b/tests/ui/issues/issue-11709.rs @@ -1,6 +1,5 @@ // run-pass #![allow(dead_code)] -// ignore-pretty issue #37199 // Don't panic on blocks without results // There are several tests in this run-pass that raised diff --git a/tests/ui/issues/issue-28839.rs b/tests/ui/issues/issue-28839.rs index 73be87a0c1e6..c086f412a288 100644 --- a/tests/ui/issues/issue-28839.rs +++ b/tests/ui/issues/issue-28839.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37199 pub struct Foo; diff --git a/tests/ui/issues/issue-38190.rs b/tests/ui/issues/issue-38190.rs index cfa0420c80d1..3bb4c7b980ca 100644 --- a/tests/ui/issues/issue-38190.rs +++ b/tests/ui/issues/issue-38190.rs @@ -1,6 +1,5 @@ // run-pass // aux-build:issue-38190.rs -// ignore-pretty issue #37195 #[macro_use] extern crate issue_38190; diff --git a/tests/ui/issues/issue-9129.rs b/tests/ui/issues/issue-9129.rs index 04110b3ae895..5d623ed540f7 100644 --- a/tests/ui/issues/issue-9129.rs +++ b/tests/ui/issues/issue-9129.rs @@ -2,7 +2,6 @@ #![allow(dead_code)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] -// ignore-pretty unreported pub trait bomb { fn boom(&self, _: Ident); } pub struct S; diff --git a/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs b/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs index 802be7f5afb5..9ba01540aaf2 100644 --- a/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs +++ b/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs @@ -6,7 +6,6 @@ // N.B., this file needs CRLF line endings. The .gitattributes file in // this directory should enforce it. -// ignore-pretty issue #37195 /// Doc comment that ends in CRLF pub fn foo() {} diff --git a/tests/ui/macros/issue-40469.rs b/tests/ui/macros/issue-40469.rs index 25e08ef85e96..9b22aaef289a 100644 --- a/tests/ui/macros/issue-40469.rs +++ b/tests/ui/macros/issue-40469.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37195 #![allow(dead_code)] diff --git a/tests/ui/macros/macro-comma-support-rpass.rs b/tests/ui/macros/macro-comma-support-rpass.rs index 25b8c3cc62e1..cb019792e656 100644 --- a/tests/ui/macros/macro-comma-support-rpass.rs +++ b/tests/ui/macros/macro-comma-support-rpass.rs @@ -8,7 +8,6 @@ // implementations for some macro_rules! macros as an implementation // detail. -// ignore-pretty issue #37195 // compile-flags: --test -C debug_assertions=yes // revisions: std core diff --git a/tests/ui/macros/macro-include-items.rs b/tests/ui/macros/macro-include-items.rs index 332bf59c944e..ad6f04009b6c 100644 --- a/tests/ui/macros/macro-include-items.rs +++ b/tests/ui/macros/macro-include-items.rs @@ -1,7 +1,6 @@ // run-pass #![allow(non_camel_case_types)] -// ignore-pretty issue #37195 fn bar() {} diff --git a/tests/ui/macros/syntax-extension-source-utils.rs b/tests/ui/macros/syntax-extension-source-utils.rs index 7e46260d5163..f41faddddf6c 100644 --- a/tests/ui/macros/syntax-extension-source-utils.rs +++ b/tests/ui/macros/syntax-extension-source-utils.rs @@ -1,7 +1,6 @@ // run-pass #![allow(stable_features)] -// ignore-pretty issue #37195 pub mod m1 { pub mod m2 { @@ -14,9 +13,9 @@ pub mod m1 { macro_rules! indirect_line { () => ( line!() ) } pub fn main() { - assert_eq!(line!(), 17); + assert_eq!(line!(), 16); assert_eq!(column!(), 16); - assert_eq!(indirect_line!(), 19); + assert_eq!(indirect_line!(), 18); assert!((file!().ends_with("syntax-extension-source-utils.rs"))); assert_eq!(stringify!((2*3) + 5).to_string(), "(2 * 3) + 5".to_string()); assert!(include!("syntax-extension-source-utils-files/includeme.\ @@ -33,5 +32,5 @@ pub fn main() { // The Windows tests are wrapped in an extra module for some reason assert!((m1::m2::where_am_i().ends_with("m1::m2"))); - assert_eq!((36, "(2 * 3) + 5"), (line!(), stringify!((2*3) + 5))); + assert_eq!((35, "(2 * 3) + 5"), (line!(), stringify!((2*3) + 5))); } diff --git a/tests/ui/modules/mod_dir_implicit.rs b/tests/ui/modules/mod_dir_implicit.rs index d6ea6a98bda4..7eac90f4d9b6 100644 --- a/tests/ui/modules/mod_dir_implicit.rs +++ b/tests/ui/modules/mod_dir_implicit.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37195 mod mod_dir_implicit_aux; diff --git a/tests/ui/modules/mod_dir_path.rs b/tests/ui/modules/mod_dir_path.rs index 70f592d0c0ed..72db8e44be31 100644 --- a/tests/ui/modules/mod_dir_path.rs +++ b/tests/ui/modules/mod_dir_path.rs @@ -1,6 +1,5 @@ // run-pass #![allow(unused_macros)] -// ignore-pretty issue #37195 mod mod_dir_simple { #[path = "test.rs"] diff --git a/tests/ui/modules/mod_dir_path2.rs b/tests/ui/modules/mod_dir_path2.rs index c3e3e1d639e9..b4f8f1c84547 100644 --- a/tests/ui/modules/mod_dir_path2.rs +++ b/tests/ui/modules/mod_dir_path2.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37195 #[path = "mod_dir_simple"] mod pancakes { diff --git a/tests/ui/modules/mod_dir_path3.rs b/tests/ui/modules/mod_dir_path3.rs index fed70c1bc984..56980c01049b 100644 --- a/tests/ui/modules/mod_dir_path3.rs +++ b/tests/ui/modules/mod_dir_path3.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37195 #[path = "mod_dir_simple"] mod pancakes { diff --git a/tests/ui/modules/mod_dir_path_multi.rs b/tests/ui/modules/mod_dir_path_multi.rs index 2b805141a63d..1c111294a337 100644 --- a/tests/ui/modules/mod_dir_path_multi.rs +++ b/tests/ui/modules/mod_dir_path_multi.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37195 #[path = "mod_dir_simple"] mod biscuits { diff --git a/tests/ui/modules/mod_dir_recursive.rs b/tests/ui/modules/mod_dir_recursive.rs index b109d13d1643..56f26139828f 100644 --- a/tests/ui/modules/mod_dir_recursive.rs +++ b/tests/ui/modules/mod_dir_recursive.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37195 // Testing that the parser for each file tracks its modules // and paths independently. The load_another_mod module should diff --git a/tests/ui/modules/mod_dir_simple.rs b/tests/ui/modules/mod_dir_simple.rs index 1d92c968a8fe..56f15b1d6105 100644 --- a/tests/ui/modules/mod_dir_simple.rs +++ b/tests/ui/modules/mod_dir_simple.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37195 mod mod_dir_simple { pub mod test; diff --git a/tests/ui/modules/mod_file.rs b/tests/ui/modules/mod_file.rs index 0ca52889e5c9..7b56b99eb3ac 100644 --- a/tests/ui/modules/mod_file.rs +++ b/tests/ui/modules/mod_file.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37195 // Testing that a plain .rs file can load modules from other source files diff --git a/tests/ui/modules/mod_file_with_path_attr.rs b/tests/ui/modules/mod_file_with_path_attr.rs index 48e253eadae5..e739366954eb 100644 --- a/tests/ui/modules/mod_file_with_path_attr.rs +++ b/tests/ui/modules/mod_file_with_path_attr.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37195 // Testing that a plain .rs file can load modules from other source files diff --git a/tests/ui/non_modrs_mods/non_modrs_mods.rs b/tests/ui/non_modrs_mods/non_modrs_mods.rs index f664b0166d80..b3fa390087f5 100644 --- a/tests/ui/non_modrs_mods/non_modrs_mods.rs +++ b/tests/ui/non_modrs_mods/non_modrs_mods.rs @@ -1,6 +1,5 @@ // run-pass // -// ignore-pretty issue #37195 pub mod modrs_mod; pub mod foors_mod; #[path = "some_crazy_attr_mod_dir/arbitrary_name.rs"] diff --git a/tests/ui/parser/issues/issue-48508.rs b/tests/ui/parser/issues/issue-48508.rs index 37d04c5d65f0..1e7db9df814b 100644 --- a/tests/ui/parser/issues/issue-48508.rs +++ b/tests/ui/parser/issues/issue-48508.rs @@ -7,7 +7,6 @@ // issue-48508-aux.rs // compile-flags:-g -// ignore-pretty issue #37195 // ignore-asmjs wasm2js does not support source maps yet #![allow(uncommon_codepoints)] diff --git a/tests/ui/proc-macro/span-api-tests.rs b/tests/ui/proc-macro/span-api-tests.rs index 3f04ba866b7d..7493f9cdb3de 100644 --- a/tests/ui/proc-macro/span-api-tests.rs +++ b/tests/ui/proc-macro/span-api-tests.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty // aux-build:span-api-tests.rs // aux-build:span-test-macros.rs // compile-flags: -Ztranslate-remapped-path-to-local-path=yes diff --git a/tests/ui/runtime/backtrace-debuginfo.rs b/tests/ui/runtime/backtrace-debuginfo.rs index 8b5466b6cfa0..5d233b38dbe2 100644 --- a/tests/ui/runtime/backtrace-debuginfo.rs +++ b/tests/ui/runtime/backtrace-debuginfo.rs @@ -9,7 +9,6 @@ // compile-flags:-g -Copt-level=0 -Cllvm-args=-enable-tail-merge=0 // compile-flags:-Cforce-frame-pointers=yes // compile-flags:-Cstrip=none -// ignore-pretty issue #37195 // ignore-emscripten spawning processes is not supported // ignore-sgx no processes // ignore-fuchsia Backtrace not symbolized, trace different line alignment diff --git a/tests/ui/traits/dyn-trait.rs b/tests/ui/traits/dyn-trait.rs index e1c1a8de55a0..10e69105ceda 100644 --- a/tests/ui/traits/dyn-trait.rs +++ b/tests/ui/traits/dyn-trait.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty `dyn ::foo` parses differently in the current edition use std::fmt::Display; From e592aaa70596741af5969a91f6054a0b16b60352 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 8 Mar 2023 10:14:42 +0100 Subject: [PATCH 031/267] remove invalid ignore-powerpc64le --- tests/codegen/global_asm.rs | 1 - tests/codegen/global_asm_include.rs | 1 - tests/codegen/global_asm_x2.rs | 1 - .../codegen/repr-transparent-aggregates-2.rs | 1 - tests/ui/target-feature/gate.rs | 1 - tests/ui/target-feature/gate.stderr | 2 +- tests/ui/target-feature/invalid-attribute.rs | 1 - .../target-feature/invalid-attribute.stderr | 44 +++++++++---------- 8 files changed, 23 insertions(+), 29 deletions(-) diff --git a/tests/codegen/global_asm.rs b/tests/codegen/global_asm.rs index fab84868fdfb..9d27fc447f6f 100644 --- a/tests/codegen/global_asm.rs +++ b/tests/codegen/global_asm.rs @@ -10,7 +10,6 @@ // ignore-mips64 // ignore-msp430 // ignore-powerpc64 -// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/tests/codegen/global_asm_include.rs b/tests/codegen/global_asm_include.rs index 02ee916458f4..438d37445c2b 100644 --- a/tests/codegen/global_asm_include.rs +++ b/tests/codegen/global_asm_include.rs @@ -10,7 +10,6 @@ // ignore-mips64 // ignore-msp430 // ignore-powerpc64 -// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/tests/codegen/global_asm_x2.rs b/tests/codegen/global_asm_x2.rs index bdcf0ea843c4..f9840e44157b 100644 --- a/tests/codegen/global_asm_x2.rs +++ b/tests/codegen/global_asm_x2.rs @@ -10,7 +10,6 @@ // ignore-mips64 // ignore-msp430 // ignore-powerpc64 -// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/tests/codegen/repr-transparent-aggregates-2.rs b/tests/codegen/repr-transparent-aggregates-2.rs index df7e88f08c73..e9fa5143b188 100644 --- a/tests/codegen/repr-transparent-aggregates-2.rs +++ b/tests/codegen/repr-transparent-aggregates-2.rs @@ -6,7 +6,6 @@ // ignore-mips64 // ignore-powerpc // ignore-powerpc64 -// ignore-powerpc64le // ignore-riscv64 see codegen/riscv-abi // ignore-s390x // ignore-sparc diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 2382c98f8f12..2eea087c7059 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -6,7 +6,6 @@ // ignore-mips64 // ignore-powerpc // ignore-powerpc64 -// ignore-powerpc64le // ignore-riscv64 // ignore-sparc // ignore-sparc64 diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index ee542b60a263..2d6abcc0a015 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:32:18 + --> $DIR/gate.rs:31:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/target-feature/invalid-attribute.rs b/tests/ui/target-feature/invalid-attribute.rs index 0c400d7bf972..b59ed076f936 100644 --- a/tests/ui/target-feature/invalid-attribute.rs +++ b/tests/ui/target-feature/invalid-attribute.rs @@ -6,7 +6,6 @@ // ignore-mips64 // ignore-powerpc // ignore-powerpc64 -// ignore-powerpc64le // ignore-riscv64 // ignore-s390x // ignore-sparc diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index 6d37d0917bc6..c36392d430f7 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -1,11 +1,11 @@ error: malformed `target_feature` attribute input - --> $DIR/invalid-attribute.rs:32:1 + --> $DIR/invalid-attribute.rs:31:1 | LL | #[target_feature = "+sse2"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]` error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:17:1 + --> $DIR/invalid-attribute.rs:16:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | extern crate alloc; | ------------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:22:1 + --> $DIR/invalid-attribute.rs:21:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | use alloc::alloc::alloc; | ------------------------ not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:27:1 + --> $DIR/invalid-attribute.rs:26:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | extern "Rust" {} | ---------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:49:1 + --> $DIR/invalid-attribute.rs:48:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | mod another {} | -------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:54:1 + --> $DIR/invalid-attribute.rs:53:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +50,7 @@ LL | const FOO: usize = 7; | --------------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:59:1 + --> $DIR/invalid-attribute.rs:58:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | struct Foo; | ----------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:64:1 + --> $DIR/invalid-attribute.rs:63:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | enum Bar {} | ----------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:69:1 + --> $DIR/invalid-attribute.rs:68:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | | } | |_- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:77:1 + --> $DIR/invalid-attribute.rs:76:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | type Uwu = (); | -------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:82:1 + --> $DIR/invalid-attribute.rs:81:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | trait Baz {} | ------------ not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:92:1 + --> $DIR/invalid-attribute.rs:91:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | static A: () = (); | ------------------ not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:97:1 + --> $DIR/invalid-attribute.rs:96:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -117,7 +117,7 @@ LL | impl Quux for u8 {} | ------------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:102:1 + --> $DIR/invalid-attribute.rs:101:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -126,7 +126,7 @@ LL | impl Foo {} | ----------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:120:5 + --> $DIR/invalid-attribute.rs:119:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,7 +138,7 @@ LL | | } | |_____- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:128:5 + --> $DIR/invalid-attribute.rs:127:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -147,25 +147,25 @@ LL | || {}; | ----- not a function definition error: the feature named `foo` is not valid for this target - --> $DIR/invalid-attribute.rs:34:18 + --> $DIR/invalid-attribute.rs:33:18 | LL | #[target_feature(enable = "foo")] | ^^^^^^^^^^^^^^ `foo` is not valid for this target error: malformed `target_feature` attribute input - --> $DIR/invalid-attribute.rs:37:18 + --> $DIR/invalid-attribute.rs:36:18 | LL | #[target_feature(bar)] | ^^^ help: must be of the form: `enable = ".."` error: malformed `target_feature` attribute input - --> $DIR/invalid-attribute.rs:39:18 + --> $DIR/invalid-attribute.rs:38:18 | LL | #[target_feature(disable = "baz")] | ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."` error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions - --> $DIR/invalid-attribute.rs:43:1 + --> $DIR/invalid-attribute.rs:42:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,13 +177,13 @@ LL | fn bar() {} = help: add `#![feature(target_feature_11)]` to the crate attributes to enable error: cannot use `#[inline(always)]` with `#[target_feature]` - --> $DIR/invalid-attribute.rs:87:1 + --> $DIR/invalid-attribute.rs:86:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions - --> $DIR/invalid-attribute.rs:112:5 + --> $DIR/invalid-attribute.rs:111:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From ef2bf6d5053f55057aecd0f0cb35c13ef332d72a Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 9 Mar 2023 14:52:45 +0100 Subject: [PATCH 032/267] implement --print=all-target-specs-json --- compiler/rustc_driver_impl/src/lib.rs | 11 +++++++++++ compiler/rustc_session/src/config.rs | 19 ++++++++++++++++--- .../valid-print-requests.stderr | 2 +- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b96b356f5517..730d41ab962f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -44,8 +44,10 @@ use rustc_session::{early_error, early_error_no_abort, early_warn}; use rustc_span::source_map::{FileLoader, FileName}; use rustc_span::symbol::sym; use rustc_target::json::ToJson; +use rustc_target::spec::{Target, TargetTriple}; use std::cmp::max; +use std::collections::BTreeMap; use std::env; use std::ffi::OsString; use std::fs; @@ -648,6 +650,15 @@ fn print_crate_info( TargetSpec => { println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); } + AllTargetSpecs => { + let mut targets = BTreeMap::new(); + for name in rustc_target::spec::TARGETS { + let triple = TargetTriple::from_triple(name); + let target = Target::expect_builtin(&triple); + targets.insert(name, target.to_json()); + } + println!("{}", serde_json::to_string_pretty(&targets).unwrap()); + } FileNames | CrateName => { let Some(attrs) = attrs.as_ref() else { // no crate attributes, print out an error and exit diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 485c3f554625..7ad3d59a1d3a 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -580,6 +580,7 @@ pub enum PrintRequest { CodeModels, TlsModels, TargetSpec, + AllTargetSpecs, NativeStaticLibs, StackProtectorStrategies, LinkArgs, @@ -1439,8 +1440,8 @@ pub fn rustc_short_optgroups() -> Vec { "Compiler information to print on stdout", "[crate-name|file-names|sysroot|target-libdir|cfg|calling-conventions|\ target-list|target-cpus|target-features|relocation-models|code-models|\ - tls-models|target-spec-json|native-static-libs|stack-protector-strategies|\ - link-args]", + tls-models|target-spec-json|all-target-specs-json|native-static-libs|\ + stack-protector-strategies|link-args]", ), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), @@ -1887,6 +1888,7 @@ fn collect_print_requests( ("native-static-libs", PrintRequest::NativeStaticLibs), ("stack-protector-strategies", PrintRequest::StackProtectorStrategies), ("target-spec-json", PrintRequest::TargetSpec), + ("all-target-specs-json", PrintRequest::AllTargetSpecs), ("link-args", PrintRequest::LinkArgs), ("split-debuginfo", PrintRequest::SplitDebuginfo), ]; @@ -1900,7 +1902,18 @@ fn collect_print_requests( early_error( error_format, "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option", + enable the target-spec-json print option", + ); + } + } + Some((_, PrintRequest::AllTargetSpecs)) => { + if unstable_opts.unstable_options { + PrintRequest::AllTargetSpecs + } else { + early_error( + error_format, + "the `-Z unstable-options` flag must also be passed to \ + enable the all-target-specs-json print option", ); } } diff --git a/tests/run-make/valid-print-requests/valid-print-requests.stderr b/tests/run-make/valid-print-requests/valid-print-requests.stderr index 5191e4676486..bea6ce067f6e 100644 --- a/tests/run-make/valid-print-requests/valid-print-requests.stderr +++ b/tests/run-make/valid-print-requests/valid-print-requests.stderr @@ -1,2 +1,2 @@ -error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `link-args`, `split-debuginfo` +error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `all-target-specs-json`, `link-args`, `split-debuginfo` From 0e6d2053b460a130ad798a5037708bb01352b3ea Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 9 Mar 2023 17:04:11 +0100 Subject: [PATCH 033/267] use target specs rather than --print=cfg to discover targets --- src/tools/compiletest/src/common.rs | 78 +++++++++++------------------ 1 file changed, 29 insertions(+), 49 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 86810179ff8b..03c0f2982fa7 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -11,6 +11,7 @@ use crate::util::{add_dylib_path, PathBufExt}; use lazycell::LazyCell; use std::collections::HashSet; use test::{ColorConfig, OutputFormat}; +use serde::de::{Deserialize, Deserializer, Error as _}; macro_rules! string_enum { ($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => { @@ -114,8 +115,10 @@ string_enum! { } } -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Default, serde::Deserialize)] +#[serde(rename_all = "kebab-case")] pub enum PanicStrategy { + #[default] Unwind, Abort, } @@ -450,72 +453,43 @@ impl TargetCfgs { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, serde::Deserialize)] +#[serde(rename_all = "kebab-case")] pub struct TargetCfg { pub(crate) arch: String, + #[serde(default)] pub(crate) os: String, + #[serde(default)] pub(crate) env: String, + #[serde(default)] pub(crate) abi: String, + #[serde(rename = "target-family", default)] pub(crate) families: Vec, + #[serde(rename = "target-pointer-width", deserialize_with = "serde_parse_u32")] pub(crate) pointer_width: u32, + #[serde(rename = "target-endian", default)] endian: Endian, + #[serde(rename = "panic-strategy", default)] panic: PanicStrategy, } -#[derive(Eq, PartialEq, Clone, Debug)] +#[derive(Eq, PartialEq, Clone, Debug, Default, serde::Deserialize)] +#[serde(rename_all = "kebab-case")] pub enum Endian { + #[default] Little, Big, } impl TargetCfg { fn new(config: &Config, target: &str) -> TargetCfg { - let print_cfg = rustc_output(config, &["--print=cfg", "--target", target]); - let mut arch = None; - let mut os = None; - let mut env = None; - let mut abi = None; - let mut families = Vec::new(); - let mut pointer_width = None; - let mut endian = None; - let mut panic = None; - for line in print_cfg.lines() { - if let Some((name, value)) = line.split_once('=') { - let value = value.trim_matches('"'); - match name { - "target_arch" => arch = Some(value), - "target_os" => os = Some(value), - "target_env" => env = Some(value), - "target_abi" => abi = Some(value), - "target_family" => families.push(value.to_string()), - "target_pointer_width" => pointer_width = Some(value.parse().unwrap()), - "target_endian" => { - endian = Some(match value { - "little" => Endian::Little, - "big" => Endian::Big, - s => panic!("unexpected {s}"), - }) - } - "panic" => { - panic = match value { - "abort" => Some(PanicStrategy::Abort), - "unwind" => Some(PanicStrategy::Unwind), - s => panic!("unexpected {s}"), - } - } - _ => {} - } - } - } - TargetCfg { - arch: arch.unwrap().to_string(), - os: os.unwrap().to_string(), - env: env.unwrap().to_string(), - abi: abi.unwrap().to_string(), - families, - pointer_width: pointer_width.unwrap(), - endian: endian.unwrap(), - panic: panic.unwrap(), + let json = rustc_output( + config, + &["--print=target-spec-json", "-Zunstable-options", "--target", target], + ); + match serde_json::from_str(&json) { + Ok(res) => res, + Err(err) => panic!("failed to parse target spec for {target}: {err}"), } } } @@ -524,6 +498,7 @@ fn rustc_output(config: &Config, args: &[&str]) -> String { let mut command = Command::new(&config.rustc_path); add_dylib_path(&mut command, iter::once(&config.compile_lib_path)); command.args(&config.target_rustcflags).args(args); + command.env("RUSTC_BOOTSTRAP", "1"); let output = match command.output() { Ok(output) => output, @@ -539,6 +514,11 @@ fn rustc_output(config: &Config, args: &[&str]) -> String { String::from_utf8(output.stdout).unwrap() } +fn serde_parse_u32<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + let string = String::deserialize(deserializer)?; + string.parse().map_err(D::Error::custom) +} + #[derive(Debug, Clone)] pub struct TestPaths { pub file: PathBuf, // e.g., compile-test/foo/bar/baz.rs From c075691b825dce55e4261aba570cd2d9665950c0 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 9 Mar 2023 17:14:25 +0100 Subject: [PATCH 034/267] use --print=all-target-specs-json for stage1+ --- src/tools/compiletest/src/common.rs | 53 ++++++++++++++++++----------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 03c0f2982fa7..833579aa926e 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -9,9 +9,9 @@ use std::str::FromStr; use crate::util::{add_dylib_path, PathBufExt}; use lazycell::LazyCell; -use std::collections::HashSet; -use test::{ColorConfig, OutputFormat}; use serde::de::{Deserialize, Deserializer, Error as _}; +use std::collections::{HashMap, HashSet}; +use test::{ColorConfig, OutputFormat}; macro_rules! string_enum { ($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => { @@ -410,8 +410,17 @@ pub struct TargetCfgs { impl TargetCfgs { fn new(config: &Config) -> TargetCfgs { - // Gather list of all targets - let targets = rustc_output(config, &["--print=target-list"]); + let targets: HashMap = if config.stage_id.starts_with("stage0-") { + // #[cfg(bootstrap)] + // Needed only for one cycle, remove during the bootstrap bump. + Self::collect_all_slow(config) + } else { + serde_json::from_str(&rustc_output( + config, + &["--print=all-target-specs-json", "-Zunstable-options"], + )) + .unwrap() + }; let mut current = None; let mut all_targets = HashSet::new(); @@ -422,9 +431,7 @@ impl TargetCfgs { let mut all_families = HashSet::new(); let mut all_pointer_widths = HashSet::new(); - for target in targets.trim().lines() { - let cfg = TargetCfg::new(config, target); - + for (target, cfg) in targets.into_iter() { all_archs.insert(cfg.arch.clone()); all_oses.insert(cfg.os.clone()); all_envs.insert(cfg.env.clone()); @@ -451,6 +458,25 @@ impl TargetCfgs { all_pointer_widths, } } + + // #[cfg(bootstrap)] + // Needed only for one cycle, remove during the bootstrap bump. + fn collect_all_slow(config: &Config) -> HashMap { + let mut result = HashMap::new(); + for target in rustc_output(config, &["--print=target-list"]).trim().lines() { + let json = rustc_output( + config, + &["--print=target-spec-json", "-Zunstable-options", "--target", target], + ); + match serde_json::from_str(&json) { + Ok(res) => { + result.insert(target.into(), res); + } + Err(err) => panic!("failed to parse target spec for {target}: {err}"), + } + } + result + } } #[derive(Clone, Debug, serde::Deserialize)] @@ -481,19 +507,6 @@ pub enum Endian { Big, } -impl TargetCfg { - fn new(config: &Config, target: &str) -> TargetCfg { - let json = rustc_output( - config, - &["--print=target-spec-json", "-Zunstable-options", "--target", target], - ); - match serde_json::from_str(&json) { - Ok(res) => res, - Err(err) => panic!("failed to parse target spec for {target}: {err}"), - } - } -} - fn rustc_output(config: &Config, args: &[&str]) -> String { let mut command = Command::new(&config.rustc_path); add_dylib_path(&mut command, iter::once(&config.compile_lib_path)); From 55121a9c460115a6a5758dd5b7057c20407f5b71 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 Mar 2023 12:17:36 +0100 Subject: [PATCH 035/267] avoid cloning the whole compiletest configuration for every test --- src/tools/compiletest/src/common.rs | 12 +++-- src/tools/compiletest/src/main.rs | 66 ++++++++++++++++------------ src/tools/compiletest/src/runtest.rs | 3 +- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 833579aa926e..3d3f8278f652 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -8,7 +8,7 @@ use std::process::Command; use std::str::FromStr; use crate::util::{add_dylib_path, PathBufExt}; -use lazycell::LazyCell; +use lazycell::AtomicLazyCell; use serde::de::{Deserialize, Deserializer, Error as _}; use std::collections::{HashMap, HashSet}; use test::{ColorConfig, OutputFormat}; @@ -326,7 +326,7 @@ pub struct Config { /// Only rerun the tests that result has been modified accoring to Git status pub only_modified: bool, - pub target_cfg: LazyCell, + pub target_cfgs: AtomicLazyCell, pub nocapture: bool, } @@ -340,7 +340,13 @@ impl Config { } pub fn target_cfgs(&self) -> &TargetCfgs { - self.target_cfgs.borrow_with(|| TargetCfgs::new(self)) + match self.target_cfgs.borrow() { + Some(cfgs) => cfgs, + None => { + let _ = self.target_cfgs.fill(TargetCfgs::new(self)); + self.target_cfgs.borrow().unwrap() + } + } } pub fn target_cfg(&self) -> &TargetCfg { diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 7700db0c74d8..cfb1ee34f679 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -11,7 +11,7 @@ use crate::util::logv; use build_helper::git::{get_git_modified_files, get_git_untracked_files}; use core::panic; use getopts::Options; -use lazycell::LazyCell; +use lazycell::AtomicLazyCell; use std::collections::BTreeSet; use std::ffi::OsString; use std::fs; @@ -25,6 +25,7 @@ use tracing::*; use walkdir::WalkDir; use self::header::{make_test_description, EarlyProps}; +use std::sync::Arc; #[cfg(test)] mod tests; @@ -42,7 +43,7 @@ pub mod util; fn main() { tracing_subscriber::fmt::init(); - let config = parse_config(env::args().collect()); + let config = Arc::new(parse_config(env::args().collect())); if config.valgrind_path.is_none() && config.force_valgrind { panic!("Can't find Valgrind to run Valgrind tests"); @@ -313,7 +314,7 @@ pub fn parse_config(args: Vec) -> Config { force_rerun: matches.opt_present("force-rerun"), - target_cfgs: LazyCell::new(), + target_cfgs: AtomicLazyCell::new(), nocapture: matches.opt_present("nocapture"), } @@ -369,7 +370,7 @@ pub fn opt_str2(maybestr: Option) -> String { } } -pub fn run_tests(config: Config) { +pub fn run_tests(config: Arc) { // If we want to collect rustfix coverage information, // we first make sure that the coverage file does not exist. // It will be created later on. @@ -411,7 +412,7 @@ pub fn run_tests(config: Config) { }; let mut tests = Vec::new(); - for c in &configs { + for c in configs { let mut found_paths = BTreeSet::new(); make_tests(c, &mut tests, &mut found_paths); check_overlapping_tests(&found_paths); @@ -433,7 +434,11 @@ pub fn run_tests(config: Config) { println!( "Some tests failed in compiletest suite={}{} mode={} host={} target={}", config.suite, - config.compare_mode.map(|c| format!(" compare_mode={:?}", c)).unwrap_or_default(), + config + .compare_mode + .as_ref() + .map(|c| format!(" compare_mode={:?}", c)) + .unwrap_or_default(), config.mode, config.host, config.target @@ -453,13 +458,13 @@ pub fn run_tests(config: Config) { } } -fn configure_cdb(config: &Config) -> Option { +fn configure_cdb(config: &Config) -> Option> { config.cdb.as_ref()?; - Some(Config { debugger: Some(Debugger::Cdb), ..config.clone() }) + Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() })) } -fn configure_gdb(config: &Config) -> Option { +fn configure_gdb(config: &Config) -> Option> { config.gdb_version?; if config.matches_env("msvc") { @@ -490,10 +495,10 @@ fn configure_gdb(config: &Config) -> Option { env::set_var("RUST_TEST_THREADS", "1"); } - Some(Config { debugger: Some(Debugger::Gdb), ..config.clone() }) + Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() })) } -fn configure_lldb(config: &Config) -> Option { +fn configure_lldb(config: &Config) -> Option> { config.lldb_python_dir.as_ref()?; if let Some(350) = config.lldb_version { @@ -506,7 +511,7 @@ fn configure_lldb(config: &Config) -> Option { return None; } - Some(Config { debugger: Some(Debugger::Lldb), ..config.clone() }) + Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() })) } pub fn test_opts(config: &Config) -> test::TestOpts { @@ -541,17 +546,17 @@ pub fn test_opts(config: &Config) -> test::TestOpts { } pub fn make_tests( - config: &Config, + config: Arc, tests: &mut Vec, found_paths: &mut BTreeSet, ) { debug!("making tests from {:?}", config.src_base.display()); - let inputs = common_inputs_stamp(config); - let modified_tests = modified_tests(config, &config.src_base).unwrap_or_else(|err| { + let inputs = common_inputs_stamp(&config); + let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| { panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err) }); collect_tests_from_dir( - config, + config.clone(), &config.src_base, &PathBuf::new(), &inputs, @@ -622,7 +627,7 @@ fn modified_tests(config: &Config, dir: &Path) -> Result, String> { } fn collect_tests_from_dir( - config: &Config, + config: Arc, dir: &Path, relative_dir_path: &Path, inputs: &Stamp, @@ -650,7 +655,7 @@ fn collect_tests_from_dir( // sequential loop because otherwise, if we do it in the // tests themselves, they race for the privilege of // creating the directories and sometimes fail randomly. - let build_dir = output_relative_path(config, relative_dir_path); + let build_dir = output_relative_path(&config, relative_dir_path); fs::create_dir_all(&build_dir).unwrap(); // Add each `.rs` file as a test, and recurse further on any @@ -666,13 +671,13 @@ fn collect_tests_from_dir( let paths = TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() }; - tests.extend(make_test(config, &paths, inputs)) + tests.extend(make_test(config.clone(), &paths, inputs)) } else if file_path.is_dir() { let relative_file_path = relative_dir_path.join(file.file_name()); if &file_name != "auxiliary" { debug!("found directory: {:?}", file_path.display()); collect_tests_from_dir( - config, + config.clone(), &file_path, &relative_file_path, inputs, @@ -701,14 +706,18 @@ pub fn is_test(file_name: &OsString) -> bool { !invalid_prefixes.iter().any(|p| file_name.starts_with(p)) } -fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec { +fn make_test( + config: Arc, + testpaths: &TestPaths, + inputs: &Stamp, +) -> Vec { let test_path = if config.mode == Mode::RunMake { // Parse directives in the Makefile testpaths.file.join("Makefile") } else { PathBuf::from(&testpaths.file) }; - let early_props = EarlyProps::from_file(config, &test_path); + let early_props = EarlyProps::from_file(&config, &test_path); // Incremental tests are special, they inherently cannot be run in parallel. // `runtest::run` will be responsible for iterating over revisions. @@ -723,19 +732,22 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec, testpaths: &TestPaths, revision: Option<&String>, ) -> test::TestFn { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a40030723105..794c845458b2 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -30,6 +30,7 @@ use std::iter; use std::path::{Path, PathBuf}; use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::str; +use std::sync::Arc; use glob::glob; use once_cell::sync::Lazy; @@ -96,7 +97,7 @@ pub fn get_lib_name(lib: &str, dylib: bool) -> String { } } -pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) { +pub fn run(config: Arc, testpaths: &TestPaths, revision: Option<&str>) { match &*config.target { "arm-linux-androideabi" | "armv7-linux-androideabi" From 8eb3def446b7026b2ff2a981791e5fc6fe031944 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 Mar 2023 12:22:07 +0100 Subject: [PATCH 036/267] handle "ignore-" and "only-" --- src/tools/compiletest/src/header.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 71e1072ceb37..b0b66e232014 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -697,6 +697,12 @@ impl Config { let (name, comment) = line.split_once(&[':', ' ']).map(|(l, c)| (l, Some(c))).unwrap_or((line, None)); + // Some of the matchers might be "" depending on what the target information is. To avoid + // problems we outright reject empty directives. + if name == "" { + return ParsedNameDirective::invalid(); + } + let mut outcome = MatchOutcome::Invalid; let mut message = None; From 9cb4373a8458e38c1ed8b1d8e768e11f305e551f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 Mar 2023 12:32:02 +0100 Subject: [PATCH 037/267] move cfg handling into its own module --- src/tools/compiletest/src/header.rs | 237 +----------------------- src/tools/compiletest/src/header/cfg.rs | 233 +++++++++++++++++++++++ 2 files changed, 239 insertions(+), 231 deletions(-) create mode 100644 src/tools/compiletest/src/header/cfg.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index b0b66e232014..50b99b805729 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -8,41 +8,16 @@ use std::process::Command; use tracing::*; -use crate::common::CompareMode; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; +use crate::header::cfg::parse_cfg_name_directive; +use crate::header::cfg::MatchOutcome; use crate::util; use crate::{extract_cdb_version, extract_gdb_version}; +mod cfg; #[cfg(test)] mod tests; -/// The result of parse_cfg_name_directive. -#[derive(Clone, PartialEq, Debug)] -struct ParsedNameDirective<'a> { - name: Option<&'a str>, - pretty_reason: Option, - comment: Option<&'a str>, - outcome: MatchOutcome, -} - -impl ParsedNameDirective<'_> { - fn invalid() -> Self { - Self { name: None, pretty_reason: None, comment: None, outcome: MatchOutcome::NoMatch } - } -} - -#[derive(Clone, Copy, PartialEq, Debug)] -enum MatchOutcome { - /// No match. - NoMatch, - /// Match. - Match, - /// The directive was invalid. - Invalid, - /// The directive is handled by other parts of our tooling. - External, -} - /// Properties which must be known very early, before actually running /// the test. #[derive(Default)] @@ -666,7 +641,7 @@ impl Config { } fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> { - if self.parse_cfg_name_directive(line, prefix).outcome == MatchOutcome::Match { + if parse_cfg_name_directive(self, line, prefix).outcome == MatchOutcome::Match { let from = parse_normalization_string(&mut line)?; let to = parse_normalization_string(&mut line)?; Some((from, to)) @@ -683,206 +658,6 @@ impl Config { self.parse_name_directive(line, "needs-profiler-support") } - /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86` - /// or `normalize-stderr-32bit`. - fn parse_cfg_name_directive<'a>(&self, line: &'a str, prefix: &str) -> ParsedNameDirective<'a> { - if !line.as_bytes().starts_with(prefix.as_bytes()) { - return ParsedNameDirective::invalid(); - } - if line.as_bytes().get(prefix.len()) != Some(&b'-') { - return ParsedNameDirective::invalid(); - } - let line = &line[prefix.len() + 1..]; - - let (name, comment) = - line.split_once(&[':', ' ']).map(|(l, c)| (l, Some(c))).unwrap_or((line, None)); - - // Some of the matchers might be "" depending on what the target information is. To avoid - // problems we outright reject empty directives. - if name == "" { - return ParsedNameDirective::invalid(); - } - - let mut outcome = MatchOutcome::Invalid; - let mut message = None; - - macro_rules! maybe_condition { - ( - name: $name:expr, - $(allowed_names: $allowed_names:expr,)? - $(condition: $condition:expr,)? - message: $($message:tt)* - ) => {{ - // This is not inlined to avoid problems with macro repetitions. - let format_message = || format!($($message)*); - - if outcome != MatchOutcome::Invalid { - // Ignore all other matches if we already found one - } else if $name.as_ref().map(|n| n == &name).unwrap_or(false) { - message = Some(format_message()); - if true $(&& $condition)? { - outcome = MatchOutcome::Match; - } else { - outcome = MatchOutcome::NoMatch; - } - } - $(else if $allowed_names.contains(name) { - message = Some(format_message()); - outcome = MatchOutcome::NoMatch; - })? - }}; - } - macro_rules! condition { - ( - name: $name:expr, - $(allowed_names: $allowed_names:expr,)? - $(condition: $condition:expr,)? - message: $($message:tt)* - ) => { - maybe_condition! { - name: Some($name), - $(allowed_names: $allowed_names,)* - $(condition: $condition,)* - message: $($message)* - } - }; - } - macro_rules! hashset { - ($($value:expr),* $(,)?) => {{ - let mut set = HashSet::new(); - $(set.insert($value);)* - set - }} - } - - let target_cfgs = self.target_cfgs(); - let target_cfg = self.target_cfg(); - - condition! { - name: "test", - message: "always" - } - condition! { - name: &self.target, - allowed_names: &target_cfgs.all_targets, - message: "when the target is {name}" - } - condition! { - name: &target_cfg.os, - allowed_names: &target_cfgs.all_oses, - message: "when the operative system is {name}" - } - condition! { - name: &target_cfg.env, - allowed_names: &target_cfgs.all_envs, - message: "when the target environment is {name}" - } - condition! { - name: &target_cfg.abi, - allowed_names: &target_cfgs.all_abis, - message: "when the ABI is {name}" - } - condition! { - name: &target_cfg.arch, - allowed_names: &target_cfgs.all_archs, - message: "when the architecture is {name}" - } - condition! { - name: format!("{}bit", target_cfg.pointer_width), - allowed_names: &target_cfgs.all_pointer_widths, - message: "when the pointer width is {name}" - } - for family in &target_cfg.families { - condition! { - name: family, - allowed_names: &target_cfgs.all_families, - message: "when the target family is {name}" - } - } - - // If something is ignored for emscripten, it likely also needs to be - // ignored for wasm32-unknown-unknown. - // `wasm32-bare` is an alias to refer to just wasm32-unknown-unknown - // (in contrast to `wasm32` which also matches non-bare targets like - // asmjs-unknown-emscripten). - condition! { - name: "emscripten", - condition: self.target == "wasm32-unknown-unknown", - message: "when the target is WASM", - } - condition! { - name: "wasm32-bare", - condition: self.target == "wasm32-unknown-unknown", - message: "when the target is WASM" - } - - condition! { - name: &self.channel, - allowed_names: hashset!["stable", "beta", "nightly"], - message: "when the release channel is {name}", - } - condition! { - name: "cross-compile", - condition: self.target != self.host, - message: "when cross-compiling" - } - condition! { - name: "endian-big", - condition: self.is_big_endian(), - message: "on big-endian targets", - } - condition! { - name: self.stage_id.split('-').next().unwrap(), - allowed_names: hashset!["stable", "beta", "nightly"], - message: "when the bootstrapping stage is {name}", - } - condition! { - name: "remote", - condition: self.remote_test_client.is_some(), - message: "when running tests remotely", - } - condition! { - name: "debug", - condition: cfg!(debug_assertions), - message: "when building with debug assertions", - } - maybe_condition! { - name: self.debugger.as_ref().map(|d| d.to_str()), - allowed_names: Debugger::VARIANTS - .iter() - .map(|v| v.to_str()) - .collect::>(), - message: "when the debugger is {name}", - } - maybe_condition! { - name: self.compare_mode - .as_ref() - .map(|d| format!("compare-mode-{}", d.to_str())), - allowed_names: CompareMode::VARIANTS - .iter() - .map(|cm| format!("compare-mode-{}", cm.to_str())) - .collect::>(), - message: "when comparing with {name}", - } - - // Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest. - if prefix == "ignore" && name.starts_with("tidy-") && outcome == MatchOutcome::Invalid { - outcome = MatchOutcome::External; - } - - // Don't error out for ignore-pass, as that is handled elsewhere. - if prefix == "ignore" && name == "pass" && outcome == MatchOutcome::Invalid { - outcome = MatchOutcome::External; - } - - ParsedNameDirective { - name: Some(name), - comment: comment.map(|c| c.trim().trim_start_matches('-').trim()), - outcome, - pretty_reason: message, - } - } - fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool { // returns whether this line contains this prefix or not. For prefix // "ignore", returns true if line says "ignore-x86_64", "ignore-arch", @@ -1151,7 +926,7 @@ pub fn make_test_description( } { - let parsed = config.parse_cfg_name_directive(ln, "ignore"); + let parsed = parse_cfg_name_directive(config, ln, "ignore"); ignore = match parsed.outcome { MatchOutcome::Match => { let reason = parsed.pretty_reason.unwrap(); @@ -1171,7 +946,7 @@ pub fn make_test_description( } if config.has_cfg_prefix(ln, "only") { - let parsed = config.parse_cfg_name_directive(ln, "only"); + let parsed = parse_cfg_name_directive(config, ln, "only"); ignore = match parsed.outcome { MatchOutcome::Match => ignore, MatchOutcome::NoMatch => { diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs new file mode 100644 index 000000000000..a6812792c277 --- /dev/null +++ b/src/tools/compiletest/src/header/cfg.rs @@ -0,0 +1,233 @@ +use crate::common::{Config, CompareMode, Debugger}; +use std::collections::HashSet; + +/// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86` +/// or `normalize-stderr-32bit`. +pub(super) fn parse_cfg_name_directive<'a>( + config: &Config, + line: &'a str, + prefix: &str, +) -> ParsedNameDirective<'a> { + if !line.as_bytes().starts_with(prefix.as_bytes()) { + return ParsedNameDirective::invalid(); + } + if line.as_bytes().get(prefix.len()) != Some(&b'-') { + return ParsedNameDirective::invalid(); + } + let line = &line[prefix.len() + 1..]; + + let (name, comment) = + line.split_once(&[':', ' ']).map(|(l, c)| (l, Some(c))).unwrap_or((line, None)); + + // Some of the matchers might be "" depending on what the target information is. To avoid + // problems we outright reject empty directives. + if name == "" { + return ParsedNameDirective::invalid(); + } + + let mut outcome = MatchOutcome::Invalid; + let mut message = None; + + macro_rules! maybe_condition { + ( + name: $name:expr, + $(allowed_names: $allowed_names:expr,)? + $(condition: $condition:expr,)? + message: $($message:tt)* + ) => {{ + // This is not inlined to avoid problems with macro repetitions. + let format_message = || format!($($message)*); + + if outcome != MatchOutcome::Invalid { + // Ignore all other matches if we already found one + } else if $name.as_ref().map(|n| n == &name).unwrap_or(false) { + message = Some(format_message()); + if true $(&& $condition)? { + outcome = MatchOutcome::Match; + } else { + outcome = MatchOutcome::NoMatch; + } + } + $(else if $allowed_names.contains(name) { + message = Some(format_message()); + outcome = MatchOutcome::NoMatch; + })? + }}; + } + macro_rules! condition { + ( + name: $name:expr, + $(allowed_names: $allowed_names:expr,)? + $(condition: $condition:expr,)? + message: $($message:tt)* + ) => { + maybe_condition! { + name: Some($name), + $(allowed_names: $allowed_names,)* + $(condition: $condition,)* + message: $($message)* + } + }; + } + macro_rules! hashset { + ($($value:expr),* $(,)?) => {{ + let mut set = HashSet::new(); + $(set.insert($value);)* + set + }} + } + + let target_cfgs = config.target_cfgs(); + let target_cfg = config.target_cfg(); + + condition! { + name: "test", + message: "always" + } + condition! { + name: &config.target, + allowed_names: &target_cfgs.all_targets, + message: "when the target is {name}" + } + condition! { + name: &target_cfg.os, + allowed_names: &target_cfgs.all_oses, + message: "when the operative system is {name}" + } + condition! { + name: &target_cfg.env, + allowed_names: &target_cfgs.all_envs, + message: "when the target environment is {name}" + } + condition! { + name: &target_cfg.abi, + allowed_names: &target_cfgs.all_abis, + message: "when the ABI is {name}" + } + condition! { + name: &target_cfg.arch, + allowed_names: &target_cfgs.all_archs, + message: "when the architecture is {name}" + } + condition! { + name: format!("{}bit", target_cfg.pointer_width), + allowed_names: &target_cfgs.all_pointer_widths, + message: "when the pointer width is {name}" + } + for family in &target_cfg.families { + condition! { + name: family, + allowed_names: &target_cfgs.all_families, + message: "when the target family is {name}" + } + } + + // If something is ignored for emscripten, it likely also needs to be + // ignored for wasm32-unknown-unknown. + // `wasm32-bare` is an alias to refer to just wasm32-unknown-unknown + // (in contrast to `wasm32` which also matches non-bare targets like + // asmjs-unknown-emscripten). + condition! { + name: "emscripten", + condition: config.target == "wasm32-unknown-unknown", + message: "when the target is WASM", + } + condition! { + name: "wasm32-bare", + condition: config.target == "wasm32-unknown-unknown", + message: "when the target is WASM" + } + + condition! { + name: &config.channel, + allowed_names: hashset!["stable", "beta", "nightly"], + message: "when the release channel is {name}", + } + condition! { + name: "cross-compile", + condition: config.target != config.host, + message: "when cross-compiling" + } + condition! { + name: "endian-big", + condition: config.is_big_endian(), + message: "on big-endian targets", + } + condition! { + name: config.stage_id.split('-').next().unwrap(), + allowed_names: hashset!["stable", "beta", "nightly"], + message: "when the bootstrapping stage is {name}", + } + condition! { + name: "remote", + condition: config.remote_test_client.is_some(), + message: "when running tests remotely", + } + condition! { + name: "debug", + condition: cfg!(debug_assertions), + message: "when building with debug assertions", + } + maybe_condition! { + name: config.debugger.as_ref().map(|d| d.to_str()), + allowed_names: Debugger::VARIANTS + .iter() + .map(|v| v.to_str()) + .collect::>(), + message: "when the debugger is {name}", + } + maybe_condition! { + name: config.compare_mode + .as_ref() + .map(|d| format!("compare-mode-{}", d.to_str())), + allowed_names: CompareMode::VARIANTS + .iter() + .map(|cm| format!("compare-mode-{}", cm.to_str())) + .collect::>(), + message: "when comparing with {name}", + } + + // Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest. + if prefix == "ignore" && name.starts_with("tidy-") && outcome == MatchOutcome::Invalid { + outcome = MatchOutcome::External; + } + + // Don't error out for ignore-pass, as that is handled elsewhere. + if prefix == "ignore" && name == "pass" && outcome == MatchOutcome::Invalid { + outcome = MatchOutcome::External; + } + + ParsedNameDirective { + name: Some(name), + comment: comment.map(|c| c.trim().trim_start_matches('-').trim()), + outcome, + pretty_reason: message, + } +} + +/// The result of parse_cfg_name_directive. +#[derive(Clone, PartialEq, Debug)] +pub(super) struct ParsedNameDirective<'a> { + pub(super) name: Option<&'a str>, + pub(super) pretty_reason: Option, + pub(super) comment: Option<&'a str>, + pub(super) outcome: MatchOutcome, +} + +impl ParsedNameDirective<'_> { + fn invalid() -> Self { + Self { name: None, pretty_reason: None, comment: None, outcome: MatchOutcome::NoMatch } + } +} + +#[derive(Clone, Copy, PartialEq, Debug)] +pub(super) enum MatchOutcome { + /// No match. + NoMatch, + /// Match. + Match, + /// The directive was invalid. + Invalid, + /// The directive is handled by other parts of our tooling. + External, +} From bc991de2336df5e6c29d50fb448778c725f9d9cf Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 Mar 2023 14:05:43 +0100 Subject: [PATCH 038/267] reduce allocations when validating cfgs --- src/tools/compiletest/src/common.rs | 3 +- src/tools/compiletest/src/header/cfg.rs | 64 +++++++++++++++++-------- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 3d3f8278f652..f03f732684cd 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -22,8 +22,9 @@ macro_rules! string_enum { impl $name { $vis const VARIANTS: &'static [Self] = &[$(Self::$variant,)*]; + $vis const STR_VARIANTS: &'static [&'static str] = &[$(Self::$variant.to_str(),)*]; - $vis fn to_str(&self) -> &'static str { + $vis const fn to_str(&self) -> &'static str { match self { $(Self::$variant => $repr,)* } diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index a6812792c277..a14943c9466c 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -1,4 +1,4 @@ -use crate::common::{Config, CompareMode, Debugger}; +use crate::common::{CompareMode, Config, Debugger}; use std::collections::HashSet; /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86` @@ -48,7 +48,7 @@ pub(super) fn parse_cfg_name_directive<'a>( outcome = MatchOutcome::NoMatch; } } - $(else if $allowed_names.contains(name) { + $(else if $allowed_names.custom_contains(name) { message = Some(format_message()); outcome = MatchOutcome::NoMatch; })? @@ -69,13 +69,6 @@ pub(super) fn parse_cfg_name_directive<'a>( } }; } - macro_rules! hashset { - ($($value:expr),* $(,)?) => {{ - let mut set = HashSet::new(); - $(set.insert($value);)* - set - }} - } let target_cfgs = config.target_cfgs(); let target_cfg = config.target_cfg(); @@ -140,7 +133,7 @@ pub(super) fn parse_cfg_name_directive<'a>( condition! { name: &config.channel, - allowed_names: hashset!["stable", "beta", "nightly"], + allowed_names: &["stable", "beta", "nightly"], message: "when the release channel is {name}", } condition! { @@ -155,7 +148,7 @@ pub(super) fn parse_cfg_name_directive<'a>( } condition! { name: config.stage_id.split('-').next().unwrap(), - allowed_names: hashset!["stable", "beta", "nightly"], + allowed_names: &["stable", "beta", "nightly"], message: "when the bootstrapping stage is {name}", } condition! { @@ -170,20 +163,17 @@ pub(super) fn parse_cfg_name_directive<'a>( } maybe_condition! { name: config.debugger.as_ref().map(|d| d.to_str()), - allowed_names: Debugger::VARIANTS - .iter() - .map(|v| v.to_str()) - .collect::>(), + allowed_names: &Debugger::STR_VARIANTS, message: "when the debugger is {name}", } maybe_condition! { name: config.compare_mode .as_ref() .map(|d| format!("compare-mode-{}", d.to_str())), - allowed_names: CompareMode::VARIANTS - .iter() - .map(|cm| format!("compare-mode-{}", cm.to_str())) - .collect::>(), + allowed_names: ContainsPrefixed { + prefix: "compare-mode-", + inner: CompareMode::STR_VARIANTS, + }, message: "when comparing with {name}", } @@ -231,3 +221,39 @@ pub(super) enum MatchOutcome { /// The directive is handled by other parts of our tooling. External, } + +trait CustomContains { + fn custom_contains(&self, item: &str) -> bool; +} + +impl CustomContains for HashSet { + fn custom_contains(&self, item: &str) -> bool { + self.contains(item) + } +} + +impl CustomContains for &[&str] { + fn custom_contains(&self, item: &str) -> bool { + self.contains(&item) + } +} + +impl CustomContains for [&str; N] { + fn custom_contains(&self, item: &str) -> bool { + self.contains(&item) + } +} + +struct ContainsPrefixed { + prefix: &'static str, + inner: T, +} + +impl CustomContains for ContainsPrefixed { + fn custom_contains(&self, item: &str) -> bool { + match item.strip_prefix(self.prefix) { + Some(stripped) => self.inner.custom_contains(stripped), + None => false, + } + } +} From e085192729c3f276e52eeb7a7e7cfaa39cc5c09c Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 Mar 2023 14:09:17 +0100 Subject: [PATCH 039/267] allow some out of tree archs --- src/tools/compiletest/src/header/cfg.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index a14943c9466c..dbc78dd521b7 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -1,6 +1,8 @@ use crate::common::{CompareMode, Config, Debugger}; use std::collections::HashSet; +const EXTRA_ARCHS: &[&str] = &["asmjs", "spirv"]; + /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86` /// or `normalize-stderr-32bit`. pub(super) fn parse_cfg_name_directive<'a>( @@ -99,7 +101,7 @@ pub(super) fn parse_cfg_name_directive<'a>( } condition! { name: &target_cfg.arch, - allowed_names: &target_cfgs.all_archs, + allowed_names: ContainsEither { a: &target_cfgs.all_archs, b: &EXTRA_ARCHS }, message: "when the architecture is {name}" } condition! { @@ -257,3 +259,14 @@ impl CustomContains for ContainsPrefixed { } } } + +struct ContainsEither<'a, A: CustomContains, B: CustomContains> { + a: &'a A, + b: &'a B, +} + +impl CustomContains for ContainsEither<'_, A, B> { + fn custom_contains(&self, item: &str) -> bool { + self.a.custom_contains(item) || self.b.custom_contains(item) + } +} From 4cdb783cb9813ab3f627303e6d763a49ee730e33 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 Mar 2023 15:29:09 +0100 Subject: [PATCH 040/267] migrate existing behavior of matches_arch --- src/tools/compiletest/src/header/cfg.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index dbc78dd521b7..747cf10bd342 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -1,7 +1,7 @@ use crate::common::{CompareMode, Config, Debugger}; use std::collections::HashSet; -const EXTRA_ARCHS: &[&str] = &["asmjs", "spirv"]; +const EXTRA_ARCHS: &[&str] = &["spirv"]; /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86` /// or `normalize-stderr-32bit`. @@ -133,6 +133,17 @@ pub(super) fn parse_cfg_name_directive<'a>( message: "when the target is WASM" } + condition! { + name: "asmjs", + condition: config.target.starts_with("asmjs"), + message: "when the architecture is asm.js", + } + condition! { + name: "thumb", + condition: config.target.starts_with("thumb"), + message: "when the architecture is part of the Thumb family" + } + condition! { name: &config.channel, allowed_names: &["stable", "beta", "nightly"], From 91be8cadcbcc94eaf78393fc8254b03c6177bca8 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 Mar 2023 15:44:58 +0100 Subject: [PATCH 041/267] properly match multiple families --- src/tools/compiletest/src/header/cfg.rs | 64 +++++++++++++++---------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 747cf10bd342..0c3250b7f760 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -30,7 +30,7 @@ pub(super) fn parse_cfg_name_directive<'a>( let mut outcome = MatchOutcome::Invalid; let mut message = None; - macro_rules! maybe_condition { + macro_rules! condition { ( name: $name:expr, $(allowed_names: $allowed_names:expr,)? @@ -42,7 +42,7 @@ pub(super) fn parse_cfg_name_directive<'a>( if outcome != MatchOutcome::Invalid { // Ignore all other matches if we already found one - } else if $name.as_ref().map(|n| n == &name).unwrap_or(false) { + } else if $name.custom_matches(name) { message = Some(format_message()); if true $(&& $condition)? { outcome = MatchOutcome::Match; @@ -56,21 +56,6 @@ pub(super) fn parse_cfg_name_directive<'a>( })? }}; } - macro_rules! condition { - ( - name: $name:expr, - $(allowed_names: $allowed_names:expr,)? - $(condition: $condition:expr,)? - message: $($message:tt)* - ) => { - maybe_condition! { - name: Some($name), - $(allowed_names: $allowed_names,)* - $(condition: $condition,)* - message: $($message)* - } - }; - } let target_cfgs = config.target_cfgs(); let target_cfg = config.target_cfg(); @@ -109,12 +94,10 @@ pub(super) fn parse_cfg_name_directive<'a>( allowed_names: &target_cfgs.all_pointer_widths, message: "when the pointer width is {name}" } - for family in &target_cfg.families { - condition! { - name: family, - allowed_names: &target_cfgs.all_families, - message: "when the target family is {name}" - } + condition! { + name: &*target_cfg.families, + allowed_names: &target_cfgs.all_families, + message: "when the target family is {name}" } // If something is ignored for emscripten, it likely also needs to be @@ -174,12 +157,12 @@ pub(super) fn parse_cfg_name_directive<'a>( condition: cfg!(debug_assertions), message: "when building with debug assertions", } - maybe_condition! { + condition! { name: config.debugger.as_ref().map(|d| d.to_str()), allowed_names: &Debugger::STR_VARIANTS, message: "when the debugger is {name}", } - maybe_condition! { + condition! { name: config.compare_mode .as_ref() .map(|d| format!("compare-mode-{}", d.to_str())), @@ -281,3 +264,34 @@ impl CustomContains for ContainsEither<'_, self.a.custom_contains(item) || self.b.custom_contains(item) } } + +trait CustomMatches { + fn custom_matches(&self, name: &str) -> bool; +} + +impl CustomMatches for &str { + fn custom_matches(&self, name: &str) -> bool { + name == *self + } +} + +impl CustomMatches for String { + fn custom_matches(&self, name: &str) -> bool { + name == self + } +} + +impl CustomMatches for &[T] { + fn custom_matches(&self, name: &str) -> bool { + self.iter().any(|m| m.custom_matches(name)) + } +} + +impl CustomMatches for Option { + fn custom_matches(&self, name: &str) -> bool { + match self { + Some(inner) => inner.custom_matches(name), + None => false, + } + } +} From 54c4762a86e4c278f8aa97d7136997cd77d4ede7 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 Mar 2023 16:11:00 +0100 Subject: [PATCH 042/267] fix remaining tests --- src/bootstrap/test.rs | 2 +- src/tools/compiletest/src/common.rs | 6 +++++- src/tools/compiletest/src/header/cfg.rs | 22 +++++++++++++--------- src/tools/compiletest/src/header/tests.rs | 6 +++--- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 92a7603a9df6..84afddbf9794 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -694,7 +694,7 @@ impl Step for CompiletestTest { /// Runs `cargo test` for compiletest. fn run(self, builder: &Builder<'_>) { let host = self.host; - let compiler = builder.compiler(0, host); + let compiler = builder.compiler(1, host); // We need `ToolStd` for the locally-built sysroot because // compiletest uses unstable features of the `test` crate. diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index f03f732684cd..2e3c1ec48eef 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -490,7 +490,7 @@ impl TargetCfgs { #[serde(rename_all = "kebab-case")] pub struct TargetCfg { pub(crate) arch: String, - #[serde(default)] + #[serde(default = "default_os")] pub(crate) os: String, #[serde(default)] pub(crate) env: String, @@ -506,6 +506,10 @@ pub struct TargetCfg { panic: PanicStrategy, } +fn default_os() -> String { + "none".into() +} + #[derive(Eq, PartialEq, Clone, Debug, Default, serde::Deserialize)] #[serde(rename_all = "kebab-case")] pub enum Endian { diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 0c3250b7f760..e1931474a5f9 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -70,7 +70,12 @@ pub(super) fn parse_cfg_name_directive<'a>( message: "when the target is {name}" } condition! { - name: &target_cfg.os, + name: &[ + Some(&*target_cfg.os), + // If something is ignored for emscripten, it likely also needs to be + // ignored for wasm32-unknown-unknown. + (config.target == "wasm32-unknown-unknown").then_some("emscripten"), + ], allowed_names: &target_cfgs.all_oses, message: "when the operative system is {name}" } @@ -100,16 +105,9 @@ pub(super) fn parse_cfg_name_directive<'a>( message: "when the target family is {name}" } - // If something is ignored for emscripten, it likely also needs to be - // ignored for wasm32-unknown-unknown. // `wasm32-bare` is an alias to refer to just wasm32-unknown-unknown // (in contrast to `wasm32` which also matches non-bare targets like // asmjs-unknown-emscripten). - condition! { - name: "emscripten", - condition: config.target == "wasm32-unknown-unknown", - message: "when the target is WASM", - } condition! { name: "wasm32-bare", condition: config.target == "wasm32-unknown-unknown", @@ -144,7 +142,7 @@ pub(super) fn parse_cfg_name_directive<'a>( } condition! { name: config.stage_id.split('-').next().unwrap(), - allowed_names: &["stable", "beta", "nightly"], + allowed_names: &["stage0", "stage1", "stage2"], message: "when the bootstrapping stage is {name}", } condition! { @@ -287,6 +285,12 @@ impl CustomMatches for &[T] { } } +impl CustomMatches for [T; N] { + fn custom_matches(&self, name: &str) -> bool { + self.iter().any(|m| m.custom_matches(name)) + } +} + impl CustomMatches for Option { fn custom_matches(&self, name: &str) -> bool { match self { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index e42b8c524084..acd588d7fee0 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -47,7 +47,7 @@ fn config() -> Config { "--src-base=", "--build-base=", "--sysroot-base=", - "--stage-id=stage2", + "--stage-id=stage2-x86_64-unknown-linux-gnu", "--cc=c", "--cxx=c++", "--cflags=", @@ -174,7 +174,7 @@ fn ignore_target() { assert!(check_ignore(&config, "// ignore-gnu")); assert!(check_ignore(&config, "// ignore-64bit")); - assert!(!check_ignore(&config, "// ignore-i686")); + assert!(!check_ignore(&config, "// ignore-x86")); assert!(!check_ignore(&config, "// ignore-windows")); assert!(!check_ignore(&config, "// ignore-msvc")); assert!(!check_ignore(&config, "// ignore-32bit")); @@ -200,7 +200,7 @@ fn only_target() { #[test] fn stage() { let mut config = config(); - config.stage_id = "stage1".to_owned(); + config.stage_id = "stage1-x86_64-unknown-linux-gnu".to_owned(); assert!(check_ignore(&config, "// ignore-stage1")); assert!(!check_ignore(&config, "// ignore-stage2")); From 60f2761503143937102f37e7ec07ecf2b5b2923e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 16 Mar 2023 10:19:14 +0100 Subject: [PATCH 043/267] add support for ignore-llvm-version --- src/tools/compiletest/src/header/cfg.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index e1931474a5f9..ffb81dfdcdb6 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -171,14 +171,22 @@ pub(super) fn parse_cfg_name_directive<'a>( message: "when comparing with {name}", } - // Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest. - if prefix == "ignore" && name.starts_with("tidy-") && outcome == MatchOutcome::Invalid { - outcome = MatchOutcome::External; - } + if prefix == "ignore" && outcome == MatchOutcome::Invalid { + // Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest. + if name.starts_with("tidy-") { + outcome = MatchOutcome::External; + } - // Don't error out for ignore-pass, as that is handled elsewhere. - if prefix == "ignore" && name == "pass" && outcome == MatchOutcome::Invalid { - outcome = MatchOutcome::External; + // Don't error out for ignore-pass, as that is handled elsewhere. + if name == "pass" { + outcome = MatchOutcome::External; + } + + // Don't error out for ignore-llvm-version, that has a custom syntax and is handled + // elsewhere. + if name == "llvm-version" { + outcome = MatchOutcome::External; + } } ParsedNameDirective { From e045598c68dfc9ce4ac5b2eccfa3585c121e1931 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 16 Mar 2023 10:19:27 +0100 Subject: [PATCH 044/267] remove a bunch of unknown archs from the global_asm tests --- tests/codegen/global_asm.rs | 26 ++++---------------------- tests/codegen/global_asm_include.rs | 26 ++++---------------------- tests/codegen/global_asm_x2.rs | 26 ++++---------------------- 3 files changed, 12 insertions(+), 66 deletions(-) diff --git a/tests/codegen/global_asm.rs b/tests/codegen/global_asm.rs index 9d27fc447f6f..9912b1e75bf5 100644 --- a/tests/codegen/global_asm.rs +++ b/tests/codegen/global_asm.rs @@ -1,38 +1,20 @@ // ignore-aarch64 -// ignore-aarch64_be // ignore-arm -// ignore-armeb // ignore-avr -// ignore-bpfel -// ignore-bpfeb +// ignore-bpf +// ignore-bpf // ignore-hexagon // ignore-mips // ignore-mips64 // ignore-msp430 // ignore-powerpc64 // ignore-powerpc -// ignore-r600 -// ignore-amdgcn // ignore-sparc -// ignore-sparcv9 -// ignore-sparcel +// ignore-sparc64 // ignore-s390x -// ignore-tce // ignore-thumb -// ignore-thumbeb -// ignore-xcore -// ignore-nvptx // ignore-nvptx64 -// ignore-le32 -// ignore-le64 -// ignore-amdil -// ignore-amdil64 -// ignore-hsail -// ignore-hsail64 -// ignore-spir -// ignore-spir64 -// ignore-kalimba -// ignore-shave +// ignore-spirv // ignore-wasm32 // ignore-wasm64 // ignore-emscripten diff --git a/tests/codegen/global_asm_include.rs b/tests/codegen/global_asm_include.rs index 438d37445c2b..b68c5ad3b9dd 100644 --- a/tests/codegen/global_asm_include.rs +++ b/tests/codegen/global_asm_include.rs @@ -1,38 +1,20 @@ // ignore-aarch64 -// ignore-aarch64_be // ignore-arm -// ignore-armeb // ignore-avr -// ignore-bpfel -// ignore-bpfeb +// ignore-bpf +// ignore-bpf // ignore-hexagon // ignore-mips // ignore-mips64 // ignore-msp430 // ignore-powerpc64 // ignore-powerpc -// ignore-r600 -// ignore-amdgcn // ignore-sparc -// ignore-sparcv9 -// ignore-sparcel +// ignore-sparc64 // ignore-s390x -// ignore-tce // ignore-thumb -// ignore-thumbeb -// ignore-xcore -// ignore-nvptx // ignore-nvptx64 -// ignore-le32 -// ignore-le64 -// ignore-amdil -// ignore-amdil64 -// ignore-hsail -// ignore-hsail64 -// ignore-spir -// ignore-spir64 -// ignore-kalimba -// ignore-shave +// ignore-spirv // ignore-wasm32 // ignore-wasm64 // ignore-emscripten diff --git a/tests/codegen/global_asm_x2.rs b/tests/codegen/global_asm_x2.rs index f9840e44157b..d87e02befb9b 100644 --- a/tests/codegen/global_asm_x2.rs +++ b/tests/codegen/global_asm_x2.rs @@ -1,38 +1,20 @@ // ignore-aarch64 -// ignore-aarch64_be // ignore-arm -// ignore-armeb // ignore-avr -// ignore-bpfel -// ignore-bpfeb +// ignore-bpf +// ignore-bpf // ignore-hexagon // ignore-mips // ignore-mips64 // ignore-msp430 // ignore-powerpc64 // ignore-powerpc -// ignore-r600 -// ignore-amdgcn // ignore-sparc -// ignore-sparcv9 -// ignore-sparcel +// ignore-sparc64 // ignore-s390x -// ignore-tce // ignore-thumb -// ignore-thumbeb -// ignore-xcore -// ignore-nvptx // ignore-nvptx64 -// ignore-le32 -// ignore-le64 -// ignore-amdil -// ignore-amdil64 -// ignore-hsail -// ignore-hsail64 -// ignore-spir -// ignore-spir64 -// ignore-kalimba -// ignore-shave +// ignore-spirv // ignore-wasm32 // ignore-wasm64 // ignore-emscripten From 3602200d50d895f911c8efe35fcd2463b4e8d891 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 16 Mar 2023 10:20:57 +0100 Subject: [PATCH 045/267] make 32bit ignore more accurate --- tests/codegen/issues/issue-37945.rs | 6 +----- tests/run-make/static-pie/Makefile | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/codegen/issues/issue-37945.rs b/tests/codegen/issues/issue-37945.rs index 19e7e8b1f6e1..4f386d335c7d 100644 --- a/tests/codegen/issues/issue-37945.rs +++ b/tests/codegen/issues/issue-37945.rs @@ -1,9 +1,5 @@ // compile-flags: -O -Zmerge-functions=disabled -// ignore-x86 -// ignore-arm -// ignore-emscripten -// ignore-gnux32 -// ignore 32-bit platforms (LLVM has a bug with them) +// ignore-32bit LLVM has a bug with them // ignore-debug // Check that LLVM understands that `Iter` pointer is not null. Issue #37945. diff --git a/tests/run-make/static-pie/Makefile b/tests/run-make/static-pie/Makefile index 19c041d94284..8379730cc3df 100644 --- a/tests/run-make/static-pie/Makefile +++ b/tests/run-make/static-pie/Makefile @@ -2,7 +2,7 @@ include ../tools.mk # only-x86_64 # only-linux -# ignore-gnux32 +# ignore-32bit # How to manually run this # $ ./x.py test --target x86_64-unknown-linux-[musl,gnu] tests/run-make/static-pie From 8f8873e386e6bab091b50f24d746b3ed0487524f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 16 Mar 2023 10:21:12 +0100 Subject: [PATCH 046/267] remove unknown xcore arch --- tests/codegen/abi-main-signature-16bit-c-int.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/codegen/abi-main-signature-16bit-c-int.rs b/tests/codegen/abi-main-signature-16bit-c-int.rs index 4ed491dfb2b4..3548cc06a5b6 100644 --- a/tests/codegen/abi-main-signature-16bit-c-int.rs +++ b/tests/codegen/abi-main-signature-16bit-c-int.rs @@ -17,7 +17,6 @@ // ignore-wasm32 // ignore-x86 // ignore-x86_64 -// ignore-xcore fn main() { } From 5b0a0d8254fa9c4d799d501b2a5b280170d4fd95 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 16 Mar 2023 11:19:30 +0100 Subject: [PATCH 047/267] add support for ignore-gdb-version --- src/tools/compiletest/src/header/cfg.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index ffb81dfdcdb6..da4af98ce91e 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -187,6 +187,12 @@ pub(super) fn parse_cfg_name_directive<'a>( if name == "llvm-version" { outcome = MatchOutcome::External; } + + // Don't error out for ignore-llvm-version, that has a custom syntax and is handled + // elsewhere. + if name == "gdb-version" { + outcome = MatchOutcome::External; + } } ParsedNameDirective { From 9a2d1b85edc99866f0f0763a000a09c0b61b2f58 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 16 Mar 2023 11:34:18 +0100 Subject: [PATCH 048/267] restore check for both target os and env This is better than the old impl of target.ends_with("windows-gnu"), because it also catches things like windows-gnullvm --- src/tools/compiletest/src/common.rs | 10 ++++++++++ src/tools/compiletest/src/header/cfg.rs | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 2e3c1ec48eef..98b27a5c6b60 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -409,6 +409,7 @@ pub struct TargetCfgs { pub all_targets: HashSet, pub all_archs: HashSet, pub all_oses: HashSet, + pub all_oses_and_envs: HashSet, pub all_envs: HashSet, pub all_abis: HashSet, pub all_families: HashSet, @@ -433,6 +434,7 @@ impl TargetCfgs { let mut all_targets = HashSet::new(); let mut all_archs = HashSet::new(); let mut all_oses = HashSet::new(); + let mut all_oses_and_envs = HashSet::new(); let mut all_envs = HashSet::new(); let mut all_abis = HashSet::new(); let mut all_families = HashSet::new(); @@ -441,6 +443,7 @@ impl TargetCfgs { for (target, cfg) in targets.into_iter() { all_archs.insert(cfg.arch.clone()); all_oses.insert(cfg.os.clone()); + all_oses_and_envs.insert(cfg.os_and_env()); all_envs.insert(cfg.env.clone()); all_abis.insert(cfg.abi.clone()); for family in &cfg.families { @@ -459,6 +462,7 @@ impl TargetCfgs { all_targets, all_archs, all_oses, + all_oses_and_envs, all_envs, all_abis, all_families, @@ -506,6 +510,12 @@ pub struct TargetCfg { panic: PanicStrategy, } +impl TargetCfg { + pub(crate) fn os_and_env(&self) -> String { + format!("{}-{}", self.os, self.env) + } +} + fn default_os() -> String { "none".into() } diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index da4af98ce91e..3b9333dfe7a0 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -84,6 +84,11 @@ pub(super) fn parse_cfg_name_directive<'a>( allowed_names: &target_cfgs.all_envs, message: "when the target environment is {name}" } + condition! { + name: &target_cfg.os_and_env(), + allowed_names: &target_cfgs.all_oses_and_envs, + message: "when the operative system and target environment are {name}" + } condition! { name: &target_cfg.abi, allowed_names: &target_cfgs.all_abis, From bf66ddbf24f3be48e31429540e3dfa4f832e61c7 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 16 Mar 2023 11:35:11 +0100 Subject: [PATCH 049/267] fix wrong ignore condition --- tests/ui-fulldeps/stable-mir/crate-info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 99b653f20b63..03dab2350402 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -1,7 +1,7 @@ // run-pass // Test that users are able to use stable mir APIs to retrieve information of the current crate -// ignore-stage-1 +// ignore-stage1 // ignore-cross-compile // ignore-remote // edition: 2021 From 48bea636fae05109ea90f08c290bae2b6bd9c69b Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 16 Mar 2023 14:18:07 +0100 Subject: [PATCH 050/267] fix solaris ignore --- tests/run-make/use-extern-for-plugins/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-make/use-extern-for-plugins/Makefile b/tests/run-make/use-extern-for-plugins/Makefile index 6ae53afad207..b8ec7e8dcda9 100644 --- a/tests/run-make/use-extern-for-plugins/Makefile +++ b/tests/run-make/use-extern-for-plugins/Makefile @@ -2,7 +2,7 @@ include ../tools.mk # ignore-freebsd # ignore-openbsd -# ignore-sunos +# ignore-solaris HOST := $(shell $(RUSTC) -vV | grep 'host:' | sed 's/host: //') ifeq ($(findstring i686,$(HOST)),i686) From bbcbb6fccee0bc9edd7f4da96426d33a1742687d Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 30 Mar 2023 12:38:41 +0200 Subject: [PATCH 051/267] ignore x86-stdcall on mingw --- tests/ui/symbol-names/x86-stdcall.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/symbol-names/x86-stdcall.rs b/tests/ui/symbol-names/x86-stdcall.rs index dd0e5477e2e1..43c086dc6bc1 100644 --- a/tests/ui/symbol-names/x86-stdcall.rs +++ b/tests/ui/symbol-names/x86-stdcall.rs @@ -1,6 +1,7 @@ // build-pass // only-x86 // only-windows +// ignore-gnu - vectorcall is not supported by GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485 #![crate_type = "cdylib"] #![feature(abi_vectorcall)] From 7a70647f195f6b0a0f1ebd72b1542ba91a32f43a Mon Sep 17 00:00:00 2001 From: The 8472 Date: Mon, 3 Apr 2023 15:29:46 +0200 Subject: [PATCH 052/267] llvm 16 finally reconizes some additional vec in-place conversions as noops --- tests/codegen/vec-in-place.rs | 42 ++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs index 9992604221bc..d68067ceb19f 100644 --- a/tests/codegen/vec-in-place.rs +++ b/tests/codegen/vec-in-place.rs @@ -1,11 +1,13 @@ // ignore-debug: the debug assertions get in the way // compile-flags: -O -Z merge-functions=disabled +// min-llvm-version: 16 #![crate_type = "lib"] // Ensure that trivial casts of vec elements are O(1) pub struct Wrapper(T); +// previously repr(C) caused the optimization to fail #[repr(C)] pub struct Foo { a: u64, @@ -14,9 +16,8 @@ pub struct Foo { d: u64, } -// Going from an aggregate struct to another type currently requires Copy to -// enable the TrustedRandomAccess specialization. Without it optimizations do not yet -// reliably recognize the loops as noop for repr(C) or non-Copy structs. +// implementing Copy exercises the TrustedRandomAccess specialization inside the in-place +// specialization #[derive(Copy, Clone)] pub struct Bar { a: u64, @@ -25,6 +26,14 @@ pub struct Bar { d: u64, } +// this exercises the try-fold codepath +pub struct Baz { + a: u64, + b: u64, + c: u64, + d: u64, +} + // CHECK-LABEL: @vec_iterator_cast_primitive #[no_mangle] pub fn vec_iterator_cast_primitive(vec: Vec) -> Vec { @@ -52,18 +61,29 @@ pub fn vec_iterator_cast_unwrap(vec: Vec>) -> Vec { // CHECK-LABEL: @vec_iterator_cast_aggregate #[no_mangle] pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec { - // FIXME These checks should be the same as other functions. - // CHECK-NOT: @__rust_alloc - // CHECK-NOT: @__rust_alloc + // CHECK-NOT: loop + // CHECK-NOT: call vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect() } -// CHECK-LABEL: @vec_iterator_cast_deaggregate +// CHECK-LABEL: @vec_iterator_cast_deaggregate_tra #[no_mangle] -pub fn vec_iterator_cast_deaggregate(vec: Vec) -> Vec<[u64; 4]> { - // FIXME These checks should be the same as other functions. - // CHECK-NOT: @__rust_alloc - // CHECK-NOT: @__rust_alloc +pub fn vec_iterator_cast_deaggregate_tra(vec: Vec) -> Vec<[u64; 4]> { + // CHECK-NOT: loop + // CHECK-NOT: call + + // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4]. + // This currently is not guaranteed for repr(Rust) types, but it happens to work here and + // the UCG may add additional guarantees for homogenous types in the future that would make this + // correct. + vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect() +} + +// CHECK-LABEL: @vec_iterator_cast_deaggregate_fold +#[no_mangle] +pub fn vec_iterator_cast_deaggregate_fold(vec: Vec) -> Vec<[u64; 4]> { + // CHECK-NOT: loop + // CHECK-NOT: call // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4]. // This currently is not guaranteed for repr(Rust) types, but it happens to work here and From fea7b59d12ad34f18e03c2c6646cd8971dc2f216 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 26 Feb 2023 20:48:50 +0000 Subject: [PATCH 053/267] Make check_match take a LocalDefId. --- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 6 +++--- .../rustc_mir_build/src/thir/pattern/check_match.rs | 10 +++------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 413b40ab808e..8d4892470ac7 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -765,7 +765,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { parallel!( { sess.time("match_checking", || { - tcx.hir().par_body_owners(|def_id| tcx.ensure().check_match(def_id.to_def_id())) + tcx.hir().par_body_owners(|def_id| tcx.ensure().check_match(def_id)) }); }, { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9203dd59a7e6..d31b11f08927 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1114,9 +1114,9 @@ rustc_queries! { desc { "converting literal to mir constant" } } - query check_match(key: DefId) { - desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + query check_match(key: LocalDefId) { + desc { |tcx| "match-checking `{}`", tcx.def_path_str(key.to_def_id()) } + cache_on_disk_if { true } } /// Performs part of the privacy check and computes effective visibilities. diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 2640ca56b00e..59a7253ea499 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -14,7 +14,7 @@ use rustc_errors::{ }; use rustc_hir as hir; use rustc_hir::def::*; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{HirId, Pat}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -27,12 +27,8 @@ use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_span::{BytePos, Span}; -pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { - let body_id = match def_id.as_local() { - None => return, - Some(def_id) => tcx.hir().body_owned_by(def_id), - }; - +pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) { + let body_id = tcx.hir().body_owned_by(def_id); let pattern_arena = TypedArena::default(); let mut visitor = MatchVisitor { tcx, From 28d74a9b7286c7e93484541326c92bdddb587f1a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 27 Feb 2023 17:39:02 +0000 Subject: [PATCH 054/267] Shrink binding span. --- .../src/thir/pattern/check_match.rs | 25 ++- ...atterns-slice-patterns-box-patterns.stderr | 10 +- ...can-live-while-the-other-survives-1.stderr | 20 +- .../borrowck-pat-at-and-box.stderr | 40 ++-- ...t-by-move-and-ref-inverse-promotion.stderr | 5 +- ...orrowck-pat-by-move-and-ref-inverse.stderr | 125 +++++------- .../borrowck-pat-by-move-and-ref.stderr | 125 +++++------- .../borrowck-pat-ref-mut-and-ref.stderr | 160 ++++++--------- .../borrowck-pat-ref-mut-twice.stderr | 186 +++++++----------- ...inding-modes-both-sides-independent.stderr | 25 +-- .../ui/suggestions/ref-pattern-binding.stderr | 20 +- 11 files changed, 302 insertions(+), 439 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 59a7253ea499..2fee1721f994 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -879,17 +879,25 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa hir::PatKind::Binding(.., name, Some(sub)) => (*name, sub), _ => return, }; - let binding_span = pat.span.with_hi(name.span.hi()); + let mk_span = |pat_span, ident_span: Span| { + if let Some(ident_span) = ident_span.find_ancestor_inside(pat_span) { + pat_span.with_hi(ident_span.hi()) + } else { + pat_span + } + }; + let binding_span = mk_span(pat.span, name.span); let typeck_results = cx.typeck_results; let sess = cx.tcx.sess; // Get the binding move, extract the mutability if by-ref. - let mut_outer = match typeck_results.extract_binding_mode(sess, pat.hir_id, pat.span) { + let mut_outer = match typeck_results.extract_binding_mode(sess, pat.hir_id, binding_span) { Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id) => { // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. let mut conflicts_ref = Vec::new(); - sub.each_binding(|_, hir_id, span, _| { + sub.each_binding(|_, hir_id, span, ident| { + let span = mk_span(span, ident.span); match typeck_results.extract_binding_mode(sess, hir_id, span) { Some(ty::BindByValue(_)) | None => {} Some(ty::BindByReference(_)) => conflicts_ref.push(span), @@ -897,7 +905,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa }); if !conflicts_ref.is_empty() { sess.emit_err(BorrowOfMovedValue { - span: pat.span, + span: binding_span, binding_span, conflicts_ref, name, @@ -920,6 +928,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa let mut conflicts_mut_mut = Vec::new(); let mut conflicts_mut_ref = Vec::new(); sub.each_binding(|_, hir_id, span, name| { + let span = mk_span(span, name.span); match typeck_results.extract_binding_mode(sess, hir_id, span) { Some(ty::BindByReference(mut_inner)) => match (mut_outer, mut_inner) { // Both sides are `ref`. @@ -957,20 +966,20 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa // Report errors if any. if report_mut_mut { // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. - sess.emit_err(MultipleMutBorrows { span: pat.span, occurences }); + sess.emit_err(MultipleMutBorrows { span: binding_span, occurences }); } else if report_mut_ref { // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. match mut_outer { Mutability::Mut => { - sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurences }); + sess.emit_err(AlreadyMutBorrowed { span: binding_span, occurences }); } Mutability::Not => { - sess.emit_err(AlreadyBorrowed { span: pat.span, occurences }); + sess.emit_err(AlreadyBorrowed { span: binding_span, occurences }); } }; } else if report_move_conflict { // Report by-ref and by-move conflicts, e.g. `ref x @ y`. - sess.emit_err(MovedWhileBorrowed { span: pat.span, occurences }); + sess.emit_err(MovedWhileBorrowed { span: binding_span, occurences }); } } diff --git a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr index 5835f06753bb..0ca14c3f3bc6 100644 --- a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr +++ b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr @@ -2,18 +2,16 @@ error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:36:9 | LL | ref foo @ [.., ref mut bar] => (), - | -------^^^^^^^^-----------^ - | | | - | | value is mutably borrowed by `bar` here + | ^^^^^^^ ----------- value is mutably borrowed by `bar` here + | | | value is borrowed by `foo` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:120:9 | LL | ref foo @ Some(box ref mut s) => (), - | -------^^^^^^^^^^^^---------^ - | | | - | | value is mutably borrowed by `s` here + | ^^^^^^^ --------- value is mutably borrowed by `s` here + | | | value is borrowed by `foo` here error[E0382]: borrow of moved value: `x` diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr index 29cd6c45c34b..25838fbf0abd 100644 --- a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr @@ -2,18 +2,16 @@ error: cannot move out of value because it is borrowed --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14 | LL | Some(ref _y @ _z) => {} - | ------^^^-- - | | | - | | value is moved into `_z` here + | ^^^^^^ -- value is moved into `_z` here + | | | value is borrowed by `_y` here error: borrow of moved value --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:19:14 | LL | Some(_z @ ref _y) => {} - | --^^^------ - | | | - | | value borrowed here after move + | ^^ ------ value borrowed here after move + | | | value moved into `_z` here | move occurs because `_z` has type `X` which does not implement the `Copy` trait | @@ -26,18 +24,16 @@ error: cannot move out of value because it is borrowed --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14 | LL | Some(ref mut _y @ _z) => {} - | ----------^^^-- - | | | - | | value is moved into `_z` here + | ^^^^^^^^^^ -- value is moved into `_z` here + | | | value is mutably borrowed by `_y` here error: borrow of moved value --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:33:14 | LL | Some(_z @ ref mut _y) => {} - | --^^^---------- - | | | - | | value borrowed here after move + | ^^ ---------- value borrowed here after move + | | | value moved into `_z` here | move occurs because `_z` has type `X` which does not implement the `Copy` trait | diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr index 2c123b01e173..9305facc406f 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr @@ -2,72 +2,64 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-at-and-box.rs:31:9 | LL | let ref a @ box b = Box::new(NC); - | -----^^^^^^^- - | | | - | | value is moved into `b` here + | ^^^^^ - value is moved into `b` here + | | | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-at-and-box.rs:34:9 | LL | let ref a @ box ref mut b = Box::new(nc()); - | -----^^^^^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-at-and-box.rs:36:9 | LL | let ref a @ box ref mut b = Box::new(NC); - | -----^^^^^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-at-and-box.rs:38:9 | LL | let ref a @ box ref mut b = Box::new(NC); - | -----^^^^^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-at-and-box.rs:42:9 | LL | let ref a @ box ref mut b = Box::new(NC); - | -----^^^^^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:48:9 | LL | let ref mut a @ box ref b = Box::new(NC); - | ---------^^^^^^^----- - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:62:9 | LL | ref mut a @ box ref b => { - | ---------^^^^^^^----- - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:54:11 | LL | fn f5(ref mut a @ box ref b: Box) { - | ---------^^^^^^^----- - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error[E0382]: borrow of moved value diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr index d6474f1b49fb..c440f4619f52 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr @@ -2,9 +2,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:6:9 | LL | let a @ ref b = U; - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `a` here | move occurs because `a` has type `U` which does not implement the `Copy` trait | diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr index 389e86e64645..13989ebadcb5 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -2,9 +2,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:22:9 | LL | let a @ ref b = U; - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `a` here | move occurs because `a` has type `U` which does not implement the `Copy` trait | @@ -17,9 +16,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9 | LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); - | -^^^^^^^^^^^^---------^^^^^^-----^ - | | | | - | | | value borrowed here after move + | ^ --------- ----- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait @@ -33,9 +31,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:14 | LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); - | -----^^^--------- - | | | - | | value borrowed here after move + | ^^^^^ --------- value borrowed here after move + | | | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait | @@ -48,9 +45,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:33 | LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait | @@ -63,9 +59,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9 | LL | let a @ [ref mut b, ref c] = [U, U]; - | -^^^^---------^^-----^ - | | | | - | | | value borrowed here after move + | ^ --------- ----- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait @@ -79,9 +74,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9 | LL | let a @ ref b = u(); - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `a` here | move occurs because `a` has type `U` which does not implement the `Copy` trait | @@ -94,9 +88,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9 | LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); - | -^^^^^^^^^^^^---------^^^^^^-----^ - | | | | - | | | value borrowed here after move + | ^ --------- ----- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait @@ -110,9 +103,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:14 | LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); - | -----^^^--------- - | | | - | | value borrowed here after move + | ^^^^^ --------- value borrowed here after move + | | | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait | @@ -125,9 +117,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:33 | LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait | @@ -140,9 +131,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9 | LL | let a @ [ref mut b, ref c] = [u(), u()]; - | -^^^^---------^^-----^ - | | | | - | | | value borrowed here after move + | ^ --------- ----- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait @@ -156,9 +146,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:42:9 | LL | a @ Some(ref b) => {} - | -^^^^^^^^-----^ - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `a` here | move occurs because `a` has type `Option` which does not implement the `Copy` trait | @@ -171,9 +160,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^ - | | | | - | | | value borrowed here after move + | ^ --------- ----- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait @@ -187,9 +175,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:19 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | -----^^^--------- - | | | - | | value borrowed here after move + | ^^^^^ --------- value borrowed here after move + | | | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait | @@ -202,9 +189,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait | @@ -217,9 +203,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9 | LL | mut a @ Some([ref b, ref mut c]) => {} - | -----^^^^^^^^^-----^^---------^^ - | | | | - | | | value borrowed here after move + | ^^^^^ ----- --------- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait @@ -233,9 +218,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9 | LL | a @ Some(ref b) => {} - | -^^^^^^^^-----^ - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `a` here | move occurs because `a` has type `Option` which does not implement the `Copy` trait | @@ -248,9 +232,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^ - | | | | - | | | value borrowed here after move + | ^ --------- ----- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait @@ -264,9 +247,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | -----^^^--------- - | | | - | | value borrowed here after move + | ^^^^^ --------- value borrowed here after move + | | | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait | @@ -279,9 +261,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait | @@ -294,9 +275,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9 | LL | mut a @ Some([ref b, ref mut c]) => {} - | -----^^^^^^^^^-----^^---------^^ - | | | | - | | | value borrowed here after move + | ^^^^^ ----- --------- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait @@ -310,9 +290,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11 | LL | fn f1(a @ ref b: U) {} - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `a` here | move occurs because `a` has type `U` which does not implement the `Copy` trait | @@ -325,9 +304,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11 | LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} - | -----^^^^^^^^-----^^^^^^^^^^-----^ - | | | | - | | | value borrowed here after move + | ^^^^^ ----- ----- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait @@ -341,9 +319,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:20 | LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait | @@ -356,9 +333,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:31 | LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} - | -----^^^----- - | | | - | | value borrowed here after move + | ^^^^^ ----- value borrowed here after move + | | | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait | @@ -371,9 +347,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:19:11 | LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {} - | -^^^^---------^^-----^ - | | | | - | | | value borrowed here after move + | ^ --------- ----- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr index 4f7fbc9e04b0..00593b2a98f2 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr @@ -2,18 +2,16 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:24:9 | LL | let ref a @ b = U; - | -----^^^- - | | | - | | value is moved into `b` here + | ^^^^^ - value is moved into `b` here + | | | value is borrowed by `a` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:26:9 | LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); - | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ - | | | | - | | | value is moved into `e` here + | ^^^^^ ----- - value is moved into `e` here + | | | | | value is moved into `c` here | value is borrowed by `a` here @@ -21,27 +19,24 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:26:18 | LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); - | -----^^^----- - | | | - | | value is moved into `c` here + | ^^^^^ ----- value is moved into `c` here + | | | value is borrowed by `b` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:26:33 | LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); - | -----^^^- - | | | - | | value is moved into `e` here + | ^^^^^ - value is moved into `e` here + | | | value is borrowed by `d` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9 | LL | let ref mut a @ [b, mut c] = [U, U]; - | ---------^^^^-^^-----^ - | | | | - | | | value is moved into `c` here + | ^^^^^^^^^ - ----- value is moved into `c` here + | | | | | value is moved into `b` here | value is mutably borrowed by `a` here @@ -49,18 +44,16 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9 | LL | let ref a @ b = u(); - | -----^^^- - | | | - | | value is moved into `b` here + | ^^^^^ - value is moved into `b` here + | | | value is borrowed by `a` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:36:9 | LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); - | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ - | | | | - | | | value is moved into `e` here + | ^^^^^ ----- - value is moved into `e` here + | | | | | value is moved into `c` here | value is borrowed by `a` here @@ -68,27 +61,24 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18 | LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); - | -----^^^----- - | | | - | | value is moved into `c` here + | ^^^^^ ----- value is moved into `c` here + | | | value is borrowed by `b` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33 | LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); - | -----^^^- - | | | - | | value is moved into `e` here + | ^^^^^ - value is moved into `e` here + | | | value is borrowed by `d` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9 | LL | let ref mut a @ [b, mut c] = [u(), u()]; - | ---------^^^^-^^-----^ - | | | | - | | | value is moved into `c` here + | ^^^^^^^^^ - ----- value is moved into `c` here + | | | | | value is moved into `b` here | value is mutably borrowed by `a` here @@ -96,18 +86,16 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:47:9 | LL | ref a @ Some(b) => {} - | -----^^^^^^^^-^ - | | | - | | value is moved into `b` here + | ^^^^^ - value is moved into `b` here + | | | value is borrowed by `a` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:52:9 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} - | -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^ - | | | | - | | | value is moved into `e` here + | ^^^^^ ----- - value is moved into `e` here + | | | | | value is moved into `c` here | value is borrowed by `a` here @@ -115,27 +103,24 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:52:23 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} - | -----^^^----- - | | | - | | value is moved into `c` here + | ^^^^^ ----- value is moved into `c` here + | | | value is borrowed by `b` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:52:38 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} - | -----^^^- - | | | - | | value is moved into `e` here + | ^^^^^ - value is moved into `e` here + | | | value is borrowed by `d` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:59:9 | LL | ref mut a @ Some([b, mut c]) => {} - | ---------^^^^^^^^^-^^-----^^ - | | | | - | | | value is moved into `c` here + | ^^^^^^^^^ - ----- value is moved into `c` here + | | | | | value is moved into `b` here | value is mutably borrowed by `a` here @@ -143,18 +128,16 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:64:9 | LL | ref a @ Some(b) => {} - | -----^^^^^^^^-^ - | | | - | | value is moved into `b` here + | ^^^^^ - value is moved into `b` here + | | | value is borrowed by `a` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:69:9 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} - | -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^ - | | | | - | | | value is moved into `e` here + | ^^^^^ ----- - value is moved into `e` here + | | | | | value is moved into `c` here | value is borrowed by `a` here @@ -162,27 +145,24 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} - | -----^^^----- - | | | - | | value is moved into `c` here + | ^^^^^ ----- value is moved into `c` here + | | | value is borrowed by `b` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} - | -----^^^- - | | | - | | value is moved into `e` here + | ^^^^^ - value is moved into `e` here + | | | value is borrowed by `d` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:78:9 | LL | ref mut a @ Some([b, mut c]) => {} - | ---------^^^^^^^^^-^^-----^^ - | | | | - | | | value is moved into `c` here + | ^^^^^^^^^ - ----- value is moved into `c` here + | | | | | value is moved into `b` here | value is mutably borrowed by `a` here @@ -190,18 +170,16 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11 | LL | fn f1(ref a @ b: U) {} - | -----^^^- - | | | - | | value is moved into `b` here + | ^^^^^ - value is moved into `b` here + | | | value is borrowed by `a` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:14:11 | LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} - | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ - | | | | - | | | value is moved into `e` here + | ^^^^^ ----- - value is moved into `e` here + | | | | | value is moved into `c` here | value is borrowed by `a` here @@ -209,27 +187,24 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20 | LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} - | -----^^^----- - | | | - | | value is moved into `c` here + | ^^^^^ ----- value is moved into `c` here + | | | value is borrowed by `b` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35 | LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} - | -----^^^- - | | | - | | value is moved into `e` here + | ^^^^^ - value is moved into `e` here + | | | value is borrowed by `d` here error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11 | LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {} - | ---------^^^^-^^-----^ - | | | | - | | | value is moved into `c` here + | ^^^^^^^^^ - ----- value is moved into `c` here + | | | | | value is moved into `b` here | value is mutably borrowed by `a` here diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index f51b5041858c..d6409d1b643b 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -2,18 +2,16 @@ error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:9 | LL | ref mut z @ &mut Some(ref a) => { - | ---------^^^^^^^^^^^^^-----^ - | | | - | | value is borrowed by `a` here + | ^^^^^^^^^ ----- value is borrowed by `a` here + | | | value is mutably borrowed by `z` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:9 | LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub - | ---------^^^^-----------------^ - | | | | - | | | value is mutably borrowed by `c` here + | ^^^^^^^^^ ----- --------- value is mutably borrowed by `c` here + | | | | | value is borrowed by `b` here | value is mutably borrowed by `a` here @@ -21,36 +19,32 @@ error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:22 | LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub - | -----^^^--------- - | | | - | | value is mutably borrowed by `c` here + | ^^^^^ --------- value is mutably borrowed by `c` here + | | | value is borrowed by `b` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9 | LL | let ref a @ ref mut b = U; - | -----^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9 | LL | let ref mut a @ ref b = U; - | ---------^^^----- - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); - | -----^^^^---------^^---------^ - | | | | - | | | value is mutably borrowed by `c` here + | ^^^^^ --------- --------- value is mutably borrowed by `c` here + | | | | | value is mutably borrowed by `b` here | value is borrowed by `a` here @@ -58,9 +52,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); - | ---------^^^^-----^^-----^ - | | | | - | | | value is borrowed by `c` here + | ^^^^^^^^^ ----- ----- value is borrowed by `c` here + | | | | | value is borrowed by `b` here | value is mutably borrowed by `a` here @@ -68,153 +61,136 @@ error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9 | LL | let ref mut a @ ref b = u(); - | ---------^^^----- - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:51:9 | LL | let ref a @ ref mut b = u(); - | -----^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:57:9 | LL | let ref mut a @ ref b = U; - | ---------^^^----- - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:61:9 | LL | let ref a @ ref mut b = U; - | -----^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { - | ---------^^^^^^-----^ - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { - | ---------^^^^^^^-----^ - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { - | -----^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { - | -----^^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} - | -----^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} - | -----^^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} - | ---------^^^^^^-----^ - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} - | ---------^^^^^^^-----^ - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} - | -----^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} - | -----^^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} - | ---------^^^^^^-----^ - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} - | ---------^^^^^^^-----^ - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); - | -----^^^^---------^^---------^ - | | | | - | | | value is mutably borrowed by `c` here + | ^^^^^ --------- --------- value is mutably borrowed by `c` here + | | | | | value is mutably borrowed by `b` here | value is borrowed by `a` here @@ -222,9 +198,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); - | -----^^^^---------^^---------^ - | | | | - | | | value is mutably borrowed by `c` here + | ^^^^^ --------- --------- value is mutably borrowed by `c` here + | | | | | value is mutably borrowed by `b` here | value is borrowed by `a` here @@ -232,9 +207,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); - | -----^^^^---------^^---------^ - | | | | - | | | value is mutably borrowed by `c` here + | ^^^^^ --------- --------- value is mutably borrowed by `c` here + | | | | | value is mutably borrowed by `b` here | value is borrowed by `a` here @@ -242,9 +216,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:134:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); - | ---------^^^^-----^^-----^ - | | | | - | | | value is borrowed by `c` here + | ^^^^^^^^^ ----- ----- value is borrowed by `c` here + | | | | | value is borrowed by `b` here | value is mutably borrowed by `a` here @@ -252,36 +225,32 @@ error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:22:11 | LL | fn f1(ref a @ ref mut b: U) {} - | -----^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^ --------- value is mutably borrowed by `b` here + | | | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11 | LL | fn f2(ref mut a @ ref b: U) {} - | ---------^^^----- - | | | - | | value is borrowed by `b` here + | ^^^^^^^^^ ----- value is borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11 | LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {} - | -----^^^^^^^^^^^----------------^^^^^^^^ - | | | - | | value is mutably borrowed by `mid` here + | ^^^^^ ----------- value is mutably borrowed by `mid` here + | | | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:22 | LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} - | -----^^^------------- - | | | | - | | | value is moved into `c` here + | ^^^^^ --------- - value is moved into `c` here + | | | | | value is mutably borrowed by `b` here | value is borrowed by `a` here @@ -289,9 +258,8 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30 | LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} - | ---------^^^- - | | | - | | value is moved into `c` here + | ^^^^^^^^^ - value is moved into `c` here + | | | value is mutably borrowed by `b` here error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr index a0cb04a064e0..24189d0615c7 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -2,98 +2,80 @@ error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:26:9 | LL | let ref mut a @ ref mut b = U; - | ---------^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9 | LL | let ref mut a @ ref mut b = U; - | ---------^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:33:9 | LL | let ref mut a @ ref mut b = U; - | ---------^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:36:9 | LL | let ref mut a @ ref mut b = U; - | ---------^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9 | LL | let ref mut a @ ref mut b = U; - | ---------^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:44:9 | -LL | let ref mut a @ ( - | ^-------- - | | - | _________value is mutably borrowed by `a` here - | | -LL | | -LL | | ref mut b, - | | --------- value is mutably borrowed by `b` here -LL | | [ -LL | | ref mut c, - | | --------- value is mutably borrowed by `c` here -LL | | ref mut d, - | | --------- value is mutably borrowed by `d` here -LL | | ref e, - | | ----- value is borrowed by `e` here -LL | | ] -LL | | ) = (U, [U, U, U]); - | |_____^ +LL | let ref mut a @ ( + | ^^^^^^^^^ value is mutably borrowed by `a` here +LL | +LL | ref mut b, + | --------- value is mutably borrowed by `b` here +LL | [ +LL | ref mut c, + | --------- value is mutably borrowed by `c` here +LL | ref mut d, + | --------- value is mutably borrowed by `d` here +LL | ref e, + | ----- value is borrowed by `e` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:54:9 | -LL | let ref mut a @ ( - | ^-------- - | | - | _________value is mutably borrowed by `a` here - | | -LL | | -LL | | ref mut b, - | | --------- value is mutably borrowed by `b` here -LL | | [ -LL | | ref mut c, - | | --------- value is mutably borrowed by `c` here -LL | | ref mut d, - | | --------- value is mutably borrowed by `d` here -LL | | ref e, - | | ----- value is borrowed by `e` here -LL | | ] -LL | | ) = (u(), [u(), u(), u()]); - | |_________^ +LL | let ref mut a @ ( + | ^^^^^^^^^ value is mutably borrowed by `a` here +LL | +LL | ref mut b, + | --------- value is mutably borrowed by `b` here +LL | [ +LL | ref mut c, + | --------- value is mutably borrowed by `c` here +LL | ref mut d, + | --------- value is mutably borrowed by `d` here +LL | ref e, + | ----- value is borrowed by `e` here error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:64:9 | LL | let a @ (ref mut b, ref mut c) = (U, U); - | -^^^^---------^^---------^ - | | | | - | | | value borrowed here after move + | ^ --------- --------- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait @@ -107,9 +89,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9 | LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- - | -^^^^-^^^-^^-^^ - | | | | | - | | | | value borrowed here after move + | ^ - - - value borrowed here after move + | | | | | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here @@ -124,9 +105,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9 | LL | let a @ &mut ref mut b = &mut U; - | -^^^^^^^^--------- - | | | - | | value borrowed here after move + | ^ --------- value borrowed here after move + | | | value moved into `a` here | move occurs because `a` has type `&mut U` which does not implement the `Copy` trait | @@ -139,9 +119,8 @@ error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:72:9 | LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); - | -^^^^^^^^^---------^^---------^ - | | | | - | | | value borrowed here after move + | ^ --------- --------- value borrowed here after move + | | | | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait @@ -155,117 +134,99 @@ error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:76:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | ---------^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:76:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | ---------^^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | ---------^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | ---------^^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:89:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | ---------^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:89:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | ---------^^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:101:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | ---------^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:101:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | ---------^^^^^^^---------^ - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11 | LL | fn f1(ref mut a @ ref mut b: U) {} - | ---------^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11 | LL | fn f2(ref mut a @ ref mut b: U) {} - | ---------^^^--------- - | | | - | | value is mutably borrowed by `b` here + | ^^^^^^^^^ --------- value is mutably borrowed by `b` here + | | | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:13:9 | -LL | ref mut a @ [ - | ^-------- - | | - | _________value is mutably borrowed by `a` here - | | -LL | | -LL | | [ref b @ .., _], - | | ---------- value is borrowed by `b` here -LL | | [_, ref mut mid @ ..], - | | ---------------- value is mutably borrowed by `mid` here -LL | | .., -LL | | [..], -LL | | ] : [[U; 4]; 5] - | |_________^ +LL | ref mut a @ [ + | ^^^^^^^^^ value is mutably borrowed by `a` here +LL | +LL | [ref b @ .., _], + | ----- value is borrowed by `b` here +LL | [_, ref mut mid @ ..], + | ----------- value is mutably borrowed by `mid` here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:21:22 | LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} - | ---------^^^------------- - | | | | - | | | value is moved into `c` here + | ^^^^^^^^^ --------- - value is moved into `c` here + | | | | | value is mutably borrowed by `b` here | value is mutably borrowed by `a` here @@ -273,9 +234,8 @@ error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34 | LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} - | ---------^^^- - | | | - | | value is moved into `c` here + | ^^^^^^^^^ - value is moved into `c` here + | | | value is mutably borrowed by `b` here error[E0499]: cannot borrow value as mutable more than once at a time diff --git a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr index 73ebbf48118d..36515c1a29bb 100644 --- a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr +++ b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr @@ -2,36 +2,32 @@ error: cannot move out of value because it is borrowed --> $DIR/default-binding-modes-both-sides-independent.rs:26:9 | LL | let ref a @ b = NotCopy; - | -----^^^- - | | | - | | value is moved into `b` here + | ^^^^^ - value is moved into `b` here + | | | value is borrowed by `a` here error: cannot move out of value because it is borrowed --> $DIR/default-binding-modes-both-sides-independent.rs:29:9 | LL | let ref mut a @ b = NotCopy; - | ---------^^^- - | | | - | | value is moved into `b` here + | ^^^^^^^^^ - value is moved into `b` here + | | | value is mutably borrowed by `a` here error: cannot move out of value because it is borrowed --> $DIR/default-binding-modes-both-sides-independent.rs:34:12 | LL | Ok(ref a @ b) | Err(b @ ref a) => { - | -----^^^- - | | | - | | value is moved into `b` here + | ^^^^^ - value is moved into `b` here + | | | value is borrowed by `a` here error: borrow of moved value --> $DIR/default-binding-modes-both-sides-independent.rs:34:29 | LL | Ok(ref a @ b) | Err(b @ ref a) => { - | -^^^----- - | | | - | | value borrowed here after move + | ^ ----- value borrowed here after move + | | | value moved into `b` here | move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait | @@ -44,9 +40,8 @@ error: cannot move out of value because it is borrowed --> $DIR/default-binding-modes-both-sides-independent.rs:42:9 | LL | ref a @ b => { - | -----^^^- - | | | - | | value is moved into `b` here + | ^^^^^ - value is moved into `b` here + | | | value is borrowed by `a` here error[E0382]: borrow of moved value diff --git a/tests/ui/suggestions/ref-pattern-binding.stderr b/tests/ui/suggestions/ref-pattern-binding.stderr index 7b194259349b..69ce5d440af8 100644 --- a/tests/ui/suggestions/ref-pattern-binding.stderr +++ b/tests/ui/suggestions/ref-pattern-binding.stderr @@ -2,9 +2,8 @@ error: borrow of moved value --> $DIR/ref-pattern-binding.rs:10:9 | LL | let _moved @ ref _from = String::from("foo"); - | ------^^^--------- - | | | - | | value borrowed here after move + | ^^^^^^ --------- value borrowed here after move + | | | value moved into `_moved` here | move occurs because `_moved` has type `String` which does not implement the `Copy` trait | @@ -17,27 +16,24 @@ error: cannot move out of value because it is borrowed --> $DIR/ref-pattern-binding.rs:11:9 | LL | let ref _moved @ _from = String::from("foo"); - | ----------^^^----- - | | | - | | value is moved into `_from` here + | ^^^^^^^^^^ ----- value is moved into `_from` here + | | | value is borrowed by `_moved` here error: cannot move out of value because it is borrowed --> $DIR/ref-pattern-binding.rs:15:9 | LL | let ref _moved @ S { f } = S { f: String::from("foo") }; - | ----------^^^^^^^-^^ - | | | - | | value is moved into `f` here + | ^^^^^^^^^^ - value is moved into `f` here + | | | value is borrowed by `_moved` here error: borrow of moved value --> $DIR/ref-pattern-binding.rs:18:9 | LL | let _moved @ S { ref f } = S { f: String::from("foo") }; - | ------^^^^^^^-----^^ - | | | - | | value borrowed here after move + | ^^^^^^ ----- value borrowed here after move + | | | value moved into `_moved` here | move occurs because `_moved` has type `S` which does not implement the `Copy` trait | From 3b47cdc4398c8d7b422077372bb65e95ecc637d8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 26 Feb 2023 21:35:54 +0000 Subject: [PATCH 055/267] Add Span to StmtKind::Let. --- compiler/rustc_middle/src/mir/mod.rs | 7 +++ compiler/rustc_middle/src/thir.rs | 56 ++++++++++++++++++- compiler/rustc_middle/src/thir/visit.rs | 1 + compiler/rustc_mir_build/src/build/block.rs | 2 + compiler/rustc_mir_build/src/thir/cx/block.rs | 5 ++ compiler/rustc_mir_build/src/thir/print.rs | 2 + 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index de7e8bc861d2..a3dbe931daac 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1984,6 +1984,13 @@ impl<'tcx> Rvalue<'tcx> { } impl BorrowKind { + pub fn mutability(&self) -> Mutability { + match *self { + BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => Mutability::Not, + BorrowKind::Mut { .. } => Mutability::Mut, + } + } + pub fn allows_two_phase_borrow(&self) -> bool { match *self { BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 82a7cf785173..7d79a13d3fde 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -227,6 +227,9 @@ pub enum StmtKind<'tcx> { /// The lint level for this `let` statement. lint_level: LintLevel, + + /// Span of the `let = ` part. + span: Span, }, } @@ -594,6 +597,55 @@ impl<'tcx> Pat<'tcx> { _ => None, } } + + /// Call `f` on every "binding" in a pattern, e.g., on `a` in + /// `match foo() { Some(a) => (), None => () }` + pub fn each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span)) { + self.walk_always(|p| { + if let PatKind::Binding { name, mode, ty, .. } = p.kind { + f(name, mode, ty, p.span); + } + }); + } + + /// Walk the pattern in left-to-right order. + /// + /// If `it(pat)` returns `false`, the children are not visited. + pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) { + self.walk_(&mut it) + } + + fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) { + if !it(self) { + return; + } + + use PatKind::*; + match &self.kind { + Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {} + AscribeUserType { subpattern, .. } + | Binding { subpattern: Some(subpattern), .. } + | Deref { subpattern } => subpattern.walk_(it), + Leaf { subpatterns } | Variant { subpatterns, .. } => { + subpatterns.iter().for_each(|field| field.pattern.walk_(it)) + } + Or { pats } => pats.iter().for_each(|p| p.walk_(it)), + Array { box ref prefix, ref slice, box ref suffix } + | Slice { box ref prefix, ref slice, box ref suffix } => { + prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it)) + } + } + } + + /// Walk the pattern in left-to-right order. + /// + /// If you always want to recurse, prefer this method over `walk`. + pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) { + self.walk(|p| { + it(p); + true + }) + } } impl<'tcx> IntoDiagnosticArg for Pat<'tcx> { @@ -879,7 +931,7 @@ mod size_asserts { static_assert_size!(ExprKind<'_>, 40); static_assert_size!(Pat<'_>, 72); static_assert_size!(PatKind<'_>, 56); - static_assert_size!(Stmt<'_>, 48); - static_assert_size!(StmtKind<'_>, 40); + static_assert_size!(Stmt<'_>, 56); + static_assert_size!(StmtKind<'_>, 48); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 79a0e75aa7c7..5614528c4cb2 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -175,6 +175,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm ref pattern, lint_level: _, else_block, + span: _, } => { if let Some(init) = initializer { visitor.visit_expr(&visitor.thir()[*init]); diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 2643d33cee00..609ab19289c9 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -115,6 +115,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { initializer: Some(initializer), lint_level, else_block: Some(else_block), + span: _, } => { // When lowering the statement `let = else { };`, // the `` block is nested in the parent scope enclosing this statement. @@ -278,6 +279,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { initializer, lint_level, else_block: None, + span: _, } => { let ignores_expr_result = matches!(pattern.kind, PatKind::Wild); this.block_context.push(BlockFrame::Statement { ignores_expr_result }); diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 321353ca20ba..8aacec53f945 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -105,6 +105,10 @@ impl<'tcx> Cx<'tcx> { } } + let span = match local.init { + Some(init) => local.span.with_hi(init.span.hi()), + None => local.span, + }; let stmt = Stmt { kind: StmtKind::Let { remainder_scope, @@ -116,6 +120,7 @@ impl<'tcx> Cx<'tcx> { initializer: local.init.map(|init| self.mirror_expr(init)), else_block, lint_level: LintLevel::Explicit(local.hir_id), + span, }, opt_destruction_scope: opt_dxn_ext, }; diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 8028227aafd2..ed61d6ee78b1 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -151,6 +151,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { initializer, else_block, lint_level, + span, } => { print_indented!(self, "kind: Let {", depth_lvl + 1); print_indented!( @@ -181,6 +182,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { } print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 2); + print_indented!(self, format!("span: {:?}", span), depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } } From 05082f57afbf5d2e8fd7fb67719336d78b58e759 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 27 Feb 2023 17:43:39 +0000 Subject: [PATCH 056/267] Perform match checking on THIR. --- compiler/rustc_hir/src/pat_util.rs | 11 - compiler/rustc_mir_build/messages.ftl | 12 +- compiler/rustc_mir_build/src/build/mod.rs | 1 + compiler/rustc_mir_build/src/errors.rs | 23 +- .../src/thir/pattern/check_match.rs | 717 ++++++++---------- .../rustc_mir_build/src/thir/pattern/mod.rs | 25 +- tests/ui/chalkify/bugs/async.stderr | 17 +- .../const-eval/const-eval-overflow-2.rs | 1 - .../const-eval/const-eval-overflow-2.stderr | 8 +- .../const-eval/ref_to_int_match.32bit.stderr | 10 +- .../const-eval/ref_to_int_match.64bit.stderr | 10 +- .../ui/consts/const-eval/ref_to_int_match.rs | 1 - .../ui/consts/const-match-check.eval1.stderr | 4 +- .../ui/consts/const-match-check.eval2.stderr | 4 +- .../consts/const-match-check.matchck.stderr | 16 +- tests/ui/consts/const-pattern-irrefutable.rs | 9 +- .../consts/const-pattern-irrefutable.stderr | 49 +- .../const_in_pattern/incomplete-slice.stderr | 2 +- tests/ui/consts/issue-43105.rs | 1 - tests/ui/consts/issue-43105.stderr | 8 +- tests/ui/consts/issue-73976-polymorphic.rs | 2 - .../ui/consts/issue-73976-polymorphic.stderr | 16 +- tests/ui/consts/issue-78655.rs | 1 - tests/ui/consts/issue-78655.stderr | 8 +- tests/ui/consts/issue-79137-toogeneric.rs | 1 - tests/ui/consts/issue-79137-toogeneric.stderr | 8 +- ..._refers_to_static_cross_crate.32bit.stderr | 32 +- ..._refers_to_static_cross_crate.64bit.stderr | 32 +- .../const_refers_to_static_cross_crate.rs | 4 - tests/ui/error-codes/E0004.stderr | 2 +- tests/ui/error-codes/E0030-teach.rs | 1 - tests/ui/error-codes/E0030-teach.stderr | 8 +- tests/ui/error-codes/E0030.rs | 1 - tests/ui/error-codes/E0030.stderr | 8 +- ...on_exhaustive_omitted_patterns_lint.stderr | 2 +- ...-gate-precise_pointer_size_matching.stderr | 4 +- .../half-open-range-pats-thir-lower-empty.rs | 13 - ...lf-open-range-pats-thir-lower-empty.stderr | 102 +-- tests/ui/impl-trait/auto-trait-leak.stderr | 10 + .../inline-const/const-match-pat-generic.rs | 2 - .../const-match-pat-generic.stderr | 16 +- tests/ui/match/match-range-fail-2.rs | 9 +- tests/ui/match/match-range-fail-2.stderr | 24 +- .../ui/never_type/exhaustive_patterns.stderr | 4 +- .../exhaustiveness-non-exhaustive.stderr | 6 +- ...een-expanded-earlier-non-exhaustive.stderr | 6 +- tests/ui/pattern/issue-106552.stderr | 6 +- .../issue-68393-let-pat-assoc-constant.stderr | 12 +- ...e-missing-pattern-excluding-comments.fixed | 2 +- ...-missing-pattern-excluding-comments.stderr | 2 +- .../pattern/usefulness/consts-opaque.stderr | 172 ++--- .../doc-hidden-non-exhaustive.stderr | 10 +- .../empty-match.exhaustive_patterns.stderr | 16 +- .../usefulness/empty-match.normal.stderr | 16 +- tests/ui/pattern/usefulness/floats.stderr | 2 +- tests/ui/pattern/usefulness/guards.stderr | 2 +- .../integer-ranges/exhaustiveness.stderr | 4 +- .../pointer-sized-int.deny.stderr | 6 +- .../precise_pointer_matching-message.stderr | 4 +- tests/ui/pattern/usefulness/issue-2111.stderr | 2 +- .../ui/pattern/usefulness/issue-30240.stderr | 4 +- .../ui/pattern/usefulness/issue-35609.stderr | 14 +- tests/ui/pattern/usefulness/issue-3601.stderr | 2 +- .../ui/pattern/usefulness/issue-50900.stderr | 2 +- .../ui/pattern/usefulness/issue-56379.stderr | 2 +- .../match-byte-array-patterns-2.stderr | 4 +- .../usefulness/match-privately-empty.stderr | 2 +- .../usefulness/match-slice-patterns.stderr | 2 +- .../non-exhaustive-defined-here.stderr | 20 +- .../non-exhaustive-match-nested.stderr | 2 +- .../usefulness/non-exhaustive-match.stderr | 12 +- .../refutable-pattern-errors.stderr | 4 +- .../slice-patterns-exhaustiveness.stderr | 40 +- .../usefulness/stable-gated-patterns.stderr | 4 +- .../struct-like-enum-nonexhaustive.stderr | 2 +- .../usefulness/unstable-gated-patterns.stderr | 2 +- ...range-pattern-out-of-bounds-issue-68972.rs | 2 - ...e-pattern-out-of-bounds-issue-68972.stderr | 16 +- .../slice.stderr | 2 +- .../const-pat-non-exaustive-let-new-var.rs | 5 +- ...const-pat-non-exaustive-let-new-var.stderr | 15 +- 81 files changed, 668 insertions(+), 997 deletions(-) diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs index e870aa543d0b..838c123f83c8 100644 --- a/compiler/rustc_hir/src/pat_util.rs +++ b/compiler/rustc_hir/src/pat_util.rs @@ -2,7 +2,6 @@ use crate::def::{CtorOf, DefKind, Res}; use crate::def_id::DefId; use crate::hir::{self, BindingAnnotation, ByRef, HirId, PatKind}; use rustc_data_structures::fx::FxHashSet; -use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -136,14 +135,4 @@ impl hir::Pat<'_> { }); result } - - /// If the pattern is `Some()` from a desugared for loop, returns the inner pattern - pub fn for_loop_some(&self) -> Option<&Self> { - if self.span.desugaring_kind() == Some(DesugaringKind::ForLoop) { - if let hir::PatKind::Struct(_, [pat_field], _) = self.kind { - return Some(pat_field.pat); - } - } - None - } } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index fcc7cbe0715f..c8172219267f 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -239,19 +239,9 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count -> } into the body mir_build_bindings_with_variant_name = - pattern binding `{$ident}` is named the same as one of the variants of the type `{$ty_path}` + pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}` .suggestion = to match on the variant, qualify the path -mir_build_irrefutable_let_patterns_generic_let = irrefutable `let` {$count -> - [one] pattern - *[other] patterns - } - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match, so the `let` is useless - .help = consider removing `let` - mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count -> [one] pattern *[other] patterns diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index e87e38fd04ca..6303f80ea5b0 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -58,6 +58,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ ty::WithOptConstParam { did, const_param_did: None } => { tcx.ensure_with_value().thir_check_unsafety(did); tcx.ensure_with_value().thir_abstract_const(did); + tcx.ensure_with_value().check_match(did); } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index cbfca77bd25d..c67a002dce1d 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -10,7 +10,8 @@ use rustc_hir::def::Res; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::thir::Pat; use rustc_middle::ty::{self, Ty}; -use rustc_span::{symbol::Ident, Span}; +use rustc_span::symbol::Symbol; +use rustc_span::Span; #[derive(LintDiagnostic)] #[diag(mir_build_unconditional_recursion)] @@ -534,18 +535,10 @@ pub struct TrailingIrrefutableLetPatterns { #[derive(LintDiagnostic)] #[diag(mir_build_bindings_with_variant_name, code = "E0170")] pub struct BindingsWithVariantName { - #[suggestion(code = "{ty_path}::{ident}", applicability = "machine-applicable")] + #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")] pub suggestion: Option, pub ty_path: String, - pub ident: Ident, -} - -#[derive(LintDiagnostic)] -#[diag(mir_build_irrefutable_let_patterns_generic_let)] -#[note] -#[help] -pub struct IrrefutableLetPatternsGenericLet { - pub count: usize, + pub name: Symbol, } #[derive(LintDiagnostic)] @@ -590,7 +583,7 @@ pub struct BorrowOfMovedValue<'tcx> { pub binding_span: Span, #[label(mir_build_value_borrowed_label)] pub conflicts_ref: Vec, - pub name: Ident, + pub name: Symbol, pub ty: Ty<'tcx>, #[suggestion(code = "ref ", applicability = "machine-applicable")] pub suggest_borrowing: Option, @@ -638,19 +631,19 @@ pub enum Conflict { Mut { #[primary_span] span: Span, - name: Ident, + name: Symbol, }, #[label(mir_build_borrow)] Ref { #[primary_span] span: Span, - name: Ident, + name: Symbol, }, #[label(mir_build_moved)] Moved { #[primary_span] span: Span, - name: Ident, + name: Symbol, }, } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 2fee1721f994..b1f85f039893 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -2,41 +2,48 @@ use super::deconstruct_pat::{Constructor, DeconstructedPat}; use super::usefulness::{ compute_match_usefulness, MatchArm, MatchCheckCtxt, Reachability, UsefulnessReport, }; -use super::{PatCtxt, PatternError}; use crate::errors::*; -use hir::{ExprKind, PatKind}; use rustc_arena::TypedArena; -use rustc_ast::{LitKind, Mutability}; +use rustc_ast::Mutability; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{HirId, Pat}; +use rustc_hir::HirId; +use rustc_middle::thir::visit::{self, Visitor}; +use rustc_middle::thir::*; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; - use rustc_session::lint::builtin::{ BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS, }; use rustc_session::Session; -use rustc_span::source_map::Spanned; -use rustc_span::{BytePos, Span}; +use rustc_span::hygiene::DesugaringKind; +use rustc_span::Span; pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let body_id = tcx.hir().body_owned_by(def_id); + let Ok((thir, expr)) = tcx.thir_body(ty::WithOptConstParam::unknown(def_id)) else { return }; + let thir = thir.borrow(); let pattern_arena = TypedArena::default(); let mut visitor = MatchVisitor { tcx, - typeck_results: tcx.typeck_body(body_id), + thir: &*thir, param_env: tcx.param_env(def_id), + lint_level: tcx.hir().local_def_id_to_hir_id(def_id), + let_source: LetSource::None, pattern_arena: &pattern_arena, }; - visitor.visit_body(tcx.hir().body(body_id)); + visitor.visit_expr(&thir[expr]); + for param in thir.params.iter() { + if let Some(box ref pattern) = param.pat { + visitor.check_irrefutable(pattern, "function argument", None); + } + } } fn create_e0004( @@ -54,77 +61,132 @@ enum RefutableFlag { } use RefutableFlag::*; +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum LetSource { + None, + IfLet, + IfLetGuard, + LetElse, + WhileLet, +} + struct MatchVisitor<'a, 'p, 'tcx> { tcx: TyCtxt<'tcx>, - typeck_results: &'a ty::TypeckResults<'tcx>, param_env: ty::ParamEnv<'tcx>, + thir: &'a Thir<'tcx>, + lint_level: HirId, + let_source: LetSource, pattern_arena: &'p TypedArena>, } -impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> { - fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { - intravisit::walk_expr(self, ex); - match &ex.kind { - hir::ExprKind::Match(scrut, arms, source) => { - self.check_match(scrut, arms, *source, ex.span) +impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { + fn thir(&self) -> &'a Thir<'tcx> { + self.thir + } + + #[instrument(level = "trace", skip(self))] + fn visit_arm(&mut self, arm: &Arm<'tcx>) { + match arm.guard { + Some(Guard::If(expr)) => { + self.with_let_source(LetSource::IfLetGuard, |this| { + this.visit_expr(&this.thir[expr]) + }); } - hir::ExprKind::Let(hir::Let { pat, init, span, .. }) => { - self.check_let(pat, init, *span) + Some(Guard::IfLet(ref pat, expr)) => { + self.with_let_source(LetSource::IfLetGuard, |this| { + this.check_let(pat, expr, LetSource::IfLetGuard, pat.span); + this.visit_pat(pat); + this.visit_expr(&this.thir[expr]); + }); + } + None => {} + } + self.visit_pat(&arm.pattern); + self.visit_expr(&self.thir[arm.body]); + } + + #[instrument(level = "trace", skip(self))] + fn visit_expr(&mut self, ex: &Expr<'tcx>) { + match ex.kind { + ExprKind::Scope { value, lint_level, .. } => { + let old_lint_level = self.lint_level; + if let LintLevel::Explicit(hir_id) = lint_level { + self.lint_level = hir_id; + } + self.visit_expr(&self.thir[value]); + self.lint_level = old_lint_level; + return; + } + ExprKind::If { cond, then, else_opt, if_then_scope: _ } => { + // Give a specific `let_source` for the condition. + let let_source = match ex.span.desugaring_kind() { + Some(DesugaringKind::WhileLoop) => LetSource::WhileLet, + _ => LetSource::IfLet, + }; + self.with_let_source(let_source, |this| this.visit_expr(&self.thir[cond])); + self.with_let_source(LetSource::None, |this| { + this.visit_expr(&this.thir[then]); + if let Some(else_) = else_opt { + this.visit_expr(&this.thir[else_]); + } + }); + return; + } + ExprKind::Match { scrutinee, box ref arms } => { + let source = match ex.span.desugaring_kind() { + Some(DesugaringKind::ForLoop) => hir::MatchSource::ForLoopDesugar, + Some(DesugaringKind::QuestionMark) => hir::MatchSource::TryDesugar, + Some(DesugaringKind::Await) => hir::MatchSource::AwaitDesugar, + _ => hir::MatchSource::Normal, + }; + self.check_match(scrutinee, arms, source, ex.span); + } + ExprKind::Let { box ref pat, expr } => { + self.check_let(pat, expr, self.let_source, ex.span); + } + ExprKind::LogicalOp { op: LogicalOp::And, .. } => { + self.check_let_chain(ex, self.let_source); + } + _ => {} + }; + self.with_let_source(LetSource::None, |this| visit::walk_expr(this, ex)); + } + + fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) { + let old_lint_level = self.lint_level; + match stmt.kind { + StmtKind::Let { + box ref pattern, initializer, else_block, lint_level, span, .. + } => { + if let LintLevel::Explicit(lint_level) = lint_level { + self.lint_level = lint_level; + } + + if let Some(initializer) = initializer && else_block.is_some() { + self.check_let(pattern, initializer, LetSource::LetElse, span); + } + + if else_block.is_none() { + self.check_irrefutable(pattern, "local binding", Some(span)); + } } _ => {} } - } - - fn visit_local(&mut self, loc: &'tcx hir::Local<'tcx>) { - intravisit::walk_local(self, loc); - let els = loc.els; - if let Some(init) = loc.init && els.is_some() { - // Build a span without the else { ... } as we don't want to underline - // the entire else block in the IDE setting. - let span = loc.span.with_hi(init.span.hi()); - self.check_let(&loc.pat, init, span); - } - - let (msg, sp) = match loc.source { - hir::LocalSource::Normal => ("local binding", Some(loc.span)), - hir::LocalSource::AsyncFn => ("async fn binding", None), - hir::LocalSource::AwaitDesugar => ("`await` future binding", None), - hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None), - }; - if els.is_none() { - self.check_irrefutable(&loc.pat, msg, sp); - } - } - - fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - intravisit::walk_param(self, param); - self.check_irrefutable(¶m.pat, "function argument", None); - } -} - -impl PatCtxt<'_, '_> { - fn report_inlining_errors(&self) { - for error in &self.errors { - match *error { - PatternError::StaticInPattern(span) => { - self.tcx.sess.emit_err(StaticInPattern { span }); - } - PatternError::AssocConstInPattern(span) => { - self.tcx.sess.emit_err(AssocConstInPattern { span }); - } - PatternError::ConstParamInPattern(span) => { - self.tcx.sess.emit_err(ConstParamInPattern { span }); - } - PatternError::NonConstPath(span) => { - self.tcx.sess.emit_err(NonConstPath { span }); - } - } - } + visit::walk_stmt(self, stmt); + self.lint_level = old_lint_level; } } impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { - fn check_patterns(&self, pat: &Pat<'_>, rf: RefutableFlag) { + #[instrument(level = "trace", skip(self, f))] + fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) { + let old_let_source = self.let_source; + self.let_source = let_source; + ensure_sufficient_stack(|| f(self)); + self.let_source = old_let_source; + } + + fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) { pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat)); check_for_bindings_named_same_as_variants(self, pat, rf); } @@ -132,18 +194,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { fn lower_pattern( &self, cx: &mut MatchCheckCtxt<'p, 'tcx>, - pat: &'tcx hir::Pat<'tcx>, - have_errors: &mut bool, + pattern: &Pat<'tcx>, ) -> &'p DeconstructedPat<'p, 'tcx> { - let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.typeck_results); - patcx.include_lint_checks(); - let pattern = patcx.lower_pattern(pat); - let pattern: &_ = cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern)); - if !patcx.errors.is_empty() { - *have_errors = true; - patcx.report_inlining_errors(); - } - pattern + cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern)) } fn new_cx(&self, hir_id: HirId) -> MatchCheckCtxt<'p, 'tcx> { @@ -155,50 +208,48 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } } - fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, scrutinee: &hir::Expr<'_>, span: Span) { + #[instrument(level = "trace", skip(self))] + fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: ExprId, source: LetSource, span: Span) { + if let LetSource::None = source { + return; + } self.check_patterns(pat, Refutable); - let mut cx = self.new_cx(scrutinee.hir_id); - let tpat = self.lower_pattern(&mut cx, pat, &mut false); - self.check_let_reachability(&mut cx, pat.hir_id, tpat, span); + let mut cx = self.new_cx(self.lint_level); + let tpat = self.lower_pattern(&mut cx, pat); + self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span); } fn check_match( &mut self, - scrut: &hir::Expr<'_>, - hir_arms: &'tcx [hir::Arm<'tcx>], + scrut: ExprId, + arms: &[ArmId], source: hir::MatchSource, expr_span: Span, ) { - let mut cx = self.new_cx(scrut.hir_id); + let mut cx = self.new_cx(self.lint_level); - for arm in hir_arms { + for &arm in arms { // Check the arm for some things unrelated to exhaustiveness. - self.check_patterns(&arm.pat, Refutable); - if let Some(hir::Guard::IfLet(ref let_expr)) = arm.guard { - self.check_patterns(let_expr.pat, Refutable); - let tpat = self.lower_pattern(&mut cx, let_expr.pat, &mut false); - self.check_let_reachability(&mut cx, let_expr.pat.hir_id, tpat, tpat.span()); - } + let arm = &self.thir.arms[arm]; + self.check_patterns(&arm.pattern, Refutable); } - let mut have_errors = false; - - let arms: Vec<_> = hir_arms + let tarms: Vec<_> = arms .iter() - .map(|hir::Arm { pat, guard, .. }| MatchArm { - pat: self.lower_pattern(&mut cx, pat, &mut have_errors), - hir_id: pat.hir_id, - has_guard: guard.is_some(), + .map(|&arm| { + let arm = &self.thir.arms[arm]; + let hir_id = match arm.lint_level { + LintLevel::Explicit(hir_id) => hir_id, + LintLevel::Inherited => self.lint_level, + }; + let pat = self.lower_pattern(&mut cx, &arm.pattern); + MatchArm { pat, hir_id, has_guard: arm.guard.is_some() } }) .collect(); - // Bail out early if lowering failed. - if have_errors { - return; - } - - let scrut_ty = self.typeck_results.expr_ty_adjusted(scrut); - let report = compute_match_usefulness(&cx, &arms, scrut.hir_id, scrut_ty); + let scrut = &self.thir[scrut]; + let scrut_ty = scrut.ty; + let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty); match source { // Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }` @@ -215,12 +266,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { // Check if the match is exhaustive. let witnesses = report.non_exhaustiveness_witnesses; if !witnesses.is_empty() { - if source == hir::MatchSource::ForLoopDesugar && hir_arms.len() == 2 { + if source == hir::MatchSource::ForLoopDesugar && arms.len() == 2 { // the for loop pattern is not irrefutable - let pat = hir_arms[1].pat.for_loop_some().unwrap(); - self.check_irrefutable(pat, "`for` loop binding", None); + let pat = &self.thir[arms[1]].pattern; + // `pat` should be `Some()` from a desugared for loop. + debug_assert_eq!(pat.span.desugaring_kind(), Some(DesugaringKind::ForLoop)); + let PatKind::Variant { ref subpatterns, .. } = pat.kind else { bug!() }; + let [pat_field] = &subpatterns[..] else { bug!() }; + self.check_irrefutable(&pat_field.pattern, "`for` loop binding", None); } else { - non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, hir_arms, expr_span); + non_exhaustive_match( + &cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span, + ); } } } @@ -229,114 +286,92 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { &mut self, cx: &mut MatchCheckCtxt<'p, 'tcx>, pat_id: HirId, + source: LetSource, pat: &'p DeconstructedPat<'p, 'tcx>, span: Span, ) { - if self.check_let_chain(cx, pat_id) { - return; - } - if is_let_irrefutable(cx, pat_id, pat) { - irrefutable_let_pattern(cx.tcx, pat_id, span); + irrefutable_let_patterns(cx.tcx, pat_id, source, 1, span); } } - fn check_let_chain(&mut self, cx: &mut MatchCheckCtxt<'p, 'tcx>, pat_id: HirId) -> bool { - let hir = self.tcx.hir(); - let parent = hir.parent_id(pat_id); - - // First, figure out if the given pattern is part of a let chain, - // and if so, obtain the top node of the chain. - let mut top = parent; - let mut part_of_chain = false; - loop { - let new_top = hir.parent_id(top); - if let hir::Node::Expr( - hir::Expr { - kind: hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, lhs, rhs), - .. - }, - .., - ) = hir.get(new_top) - { - // If this isn't the first iteration, we need to check - // if there is a let expr before us in the chain, so - // that we avoid doubly checking the let chain. - - // The way a chain of &&s is encoded is ((let ... && let ...) && let ...) && let ... - // as && is left-to-right associative. Thus, we need to check rhs. - if part_of_chain && matches!(rhs.kind, hir::ExprKind::Let(..)) { - return true; - } - // If there is a let at the lhs, and we provide the rhs, we don't do any checking either. - if !part_of_chain && matches!(lhs.kind, hir::ExprKind::Let(..)) && rhs.hir_id == top - { - return true; - } - } else { - // We've reached the top. - break; - } - - // Since this function is called within a let context, it is reasonable to assume that any parent - // `&&` infers a let chain - part_of_chain = true; - top = new_top; - } - if !part_of_chain { - return false; + #[instrument(level = "trace", skip(self))] + fn check_let_chain(&mut self, top_expr: &Expr<'tcx>, let_source: LetSource) { + if let LetSource::None = let_source { + return; } - // Second, obtain the refutabilities of all exprs in the chain, + let ExprKind::LogicalOp { op: LogicalOp::And, mut lhs, rhs } = top_expr.kind else { bug!() }; + + // Lint level enclosing the next `lhs`. + let mut cur_lint_level = self.lint_level; + + // Obtain the refutabilities of all exprs in the chain, // and record chain members that aren't let exprs. let mut chain_refutabilities = Vec::new(); - let hir::Node::Expr(top_expr) = hir.get(top) else { - // We ensure right above that it's an Expr - unreachable!() - }; - let mut cur_expr = top_expr; - loop { - let mut add = |expr: &hir::Expr<'tcx>| { - let refutability = match expr.kind { - hir::ExprKind::Let(hir::Let { pat, init, span, .. }) => { - let mut ncx = self.new_cx(init.hir_id); - let tpat = self.lower_pattern(&mut ncx, pat, &mut false); - let refutable = !is_let_irrefutable(&mut ncx, pat.hir_id, tpat); - Some((*span, refutable)) - } - _ => None, - }; - chain_refutabilities.push(refutability); - }; - if let hir::Expr { - kind: hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, lhs, rhs), - .. - } = cur_expr + let add = |expr: ExprId, mut local_lint_level| { + // `local_lint_level` is the lint level enclosing the pattern inside `expr`. + let mut expr = &self.thir[expr]; + debug!(?expr, ?local_lint_level, "add"); + // Fast-forward through scopes. + while let ExprKind::Scope { value, lint_level, .. } = expr.kind { + if let LintLevel::Explicit(hir_id) = lint_level { + local_lint_level = hir_id + } + expr = &self.thir[value]; + } + debug!(?expr, ?local_lint_level, "after scopes"); + match expr.kind { + ExprKind::Let { box ref pat, expr: _ } => { + let mut ncx = self.new_cx(local_lint_level); + let tpat = self.lower_pattern(&mut ncx, pat); + let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat); + Some((expr.span, refutable)) + } + ExprKind::LogicalOp { op: LogicalOp::And, .. } => { + bug!() + } + _ => None, + } + }; + + // Let chains recurse on the left, so we start by adding the rightmost. + chain_refutabilities.push(add(rhs, cur_lint_level)); + + loop { + while let ExprKind::Scope { value, lint_level, .. } = self.thir[lhs].kind { + if let LintLevel::Explicit(hir_id) = lint_level { + cur_lint_level = hir_id + } + lhs = value; + } + if let ExprKind::LogicalOp { op: LogicalOp::And, lhs: new_lhs, rhs: expr } = + self.thir[lhs].kind { - add(rhs); - cur_expr = lhs; + chain_refutabilities.push(add(expr, cur_lint_level)); + lhs = new_lhs; } else { - add(cur_expr); + chain_refutabilities.push(add(lhs, cur_lint_level)); break; } } + debug!(?chain_refutabilities); chain_refutabilities.reverse(); // Third, emit the actual warnings. - if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, false)))) { // The entire chain is made up of irrefutable `let` statements - let let_source = let_source_parent(self.tcx, top, None); irrefutable_let_patterns( - cx.tcx, - top, + self.tcx, + self.lint_level, let_source, chain_refutabilities.len(), top_expr.span, ); - return true; + return; } + if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 { // The chain has a non-zero prefix of irrefutable `let` statements. @@ -346,7 +381,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { // so can't always be moved out. // FIXME: Add checking whether the bindings are actually used in the prefix, // and lint if they are not. - let let_source = let_source_parent(self.tcx, top, None); if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) { // Emit the lint let prefix = &chain_refutabilities[..until]; @@ -354,9 +388,10 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let span_end = prefix.last().unwrap().unwrap().0; let span = span_start.to(span_end); let count = prefix.len(); - cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, LeadingIrrefutableLetPatterns { count }); + self.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, self.lint_level, span, LeadingIrrefutableLetPatterns { count }); } } + if let Some(from) = chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) && from != (chain_refutabilities.len() - 1) { // The chain has a non-empty suffix of irrefutable `let` statements let suffix = &chain_refutabilities[from + 1..]; @@ -364,18 +399,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let span_end = suffix.last().unwrap().unwrap().0; let span = span_start.to(span_end); let count = suffix.len(); - cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, TrailingIrrefutableLetPatterns { count }); + self.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, self.lint_level, span, TrailingIrrefutableLetPatterns { count }); } - true } - fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option) { - let mut cx = self.new_cx(pat.hir_id); + #[instrument(level = "trace", skip(self))] + fn check_irrefutable(&self, pat: &Pat<'tcx>, origin: &str, sp: Option) { + let mut cx = self.new_cx(self.lint_level); - let pattern = self.lower_pattern(&mut cx, pat, &mut false); + let pattern = self.lower_pattern(&mut cx, pat); let pattern_ty = pattern.ty(); - let arm = MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false }; - let report = compute_match_usefulness(&cx, &[arm], pat.hir_id, pattern_ty); + let arm = MatchArm { pat: pattern, hir_id: self.lint_level, has_guard: false }; + let report = compute_match_usefulness(&cx, &[arm], self.lint_level, pattern_ty); // Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We // only care about exhaustiveness here. @@ -386,58 +421,36 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { return; } - let (inform, interpreted_as_const, res_defined_here,let_suggestion, misc_suggestion) = - if let hir::PatKind::Path(hir::QPath::Resolved( - None, - hir::Path { - segments: &[hir::PathSegment { args: None, res, ident, .. }], - .. - }, - )) = &pat.kind + let inform = sp.is_some().then_some(Inform); + let mut let_suggestion = None; + let mut misc_suggestion = None; + if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) { + let mut bindings= vec![]; + pat.each_binding(|name, _, _, _| { + bindings.push(name); + }); + let semi_span = span.shrink_to_hi(); + let start_span = span.shrink_to_lo(); + let end_span = semi_span.shrink_to_lo(); + let count = witnesses.len(); + + // If the pattern to match is an integer literal: + if bindings.is_empty() + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) + && snippet.chars().all(|c| c.is_digit(10)) { - ( - None, - Some(InterpretedAsConst { - span: pat.span, - article: res.article(), - variable: ident.to_string().to_lowercase(), - res, - }), - try { - ResDefinedHere { - def_span: cx.tcx.hir().res_span(res)?, - res, - } - }, - None, - None, - ) - } else if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) { - let mut bindings = vec![]; - pat.walk_always(&mut |pat: &hir::Pat<'_>| { - if let hir::PatKind::Binding(_, _, ident, _) = pat.kind { - bindings.push(ident); - } + // Then give a suggestion, the user might've meant to create a binding instead. + misc_suggestion = Some(MiscPatternSuggestion::AttemptedIntegerLiteral { + start_span: pat.span.shrink_to_lo() }); - let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1)); - let start_span = span.shrink_to_lo(); - let end_span = semi_span.shrink_to_lo(); - let count = witnesses.len(); + } - // If the pattern to match is an integer literal: - let int_suggestion = if - let PatKind::Lit(expr) = &pat.kind - && bindings.is_empty() - && let ExprKind::Lit(Spanned { node: LitKind::Int(_, _), span }) = expr.kind { - // Then give a suggestion, the user might've meant to create a binding instead. - Some(MiscPatternSuggestion::AttemptedIntegerLiteral { start_span: span.shrink_to_lo() }) - } else { None }; - - let let_suggestion = if bindings.is_empty() {SuggestLet::If{start_span, semi_span, count}} else{ SuggestLet::Else{end_span, count }}; - (sp.map(|_|Inform), None, None, Some(let_suggestion), int_suggestion) - } else{ - (sp.map(|_|Inform), None, None, None, None) - }; + let_suggestion = Some(if bindings.is_empty() { + SuggestLet::If {start_span, semi_span, count } + } else { + SuggestLet::Else { end_span, count } + }); + }; let adt_defined_here = try { let ty = pattern_ty.peel_refs(); @@ -456,12 +469,12 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { origin, uncovered: Uncovered::new(pat.span, &cx, witnesses), inform, - interpreted_as_const, + interpreted_as_const: None, _p: (), pattern_ty, let_suggestion, misc_suggestion, - res_defined_here, + res_defined_here: None, adt_defined_here, }); } @@ -473,14 +486,18 @@ fn check_for_bindings_named_same_as_variants( rf: RefutableFlag, ) { pat.walk_always(|p| { - if let hir::PatKind::Binding(_, _, ident, None) = p.kind - && let Some(ty::BindByValue(hir::Mutability::Not)) = - cx.typeck_results.extract_binding_mode(cx.tcx.sess, p.hir_id, p.span) - && let pat_ty = cx.typeck_results.pat_ty(p).peel_refs() - && let ty::Adt(edef, _) = pat_ty.kind() + if let PatKind::Binding { + name, + mode: BindingMode::ByValue, + mutability: Mutability::Not, + subpattern: None, + ty, + .. + } = p.kind + && let ty::Adt(edef, _) = ty.peel_refs().kind() && edef.is_enum() && edef.variants().iter().any(|variant| { - variant.ident(cx.tcx) == ident && variant.ctor_kind() == Some(CtorKind::Const) + variant.name == name && variant.ctor_kind() == Some(CtorKind::Const) }) { let variant_count = edef.variants().len(); @@ -489,7 +506,7 @@ fn check_for_bindings_named_same_as_variants( }); cx.tcx.emit_spanned_lint( BINDINGS_WITH_VARIANT_NAME, - p.hir_id, + cx.lint_level, p.span, BindingsWithVariantName { // If this is an irrefutable pattern, and there's > 1 variant, @@ -499,7 +516,7 @@ fn check_for_bindings_named_same_as_variants( Some(p.span) } else { None }, ty_path, - ident, + name, }, ) } @@ -525,11 +542,6 @@ fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option< ); } -fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) { - let source = let_source(tcx, id); - irrefutable_let_patterns(tcx, id, source, 1, span); -} - fn irrefutable_let_patterns( tcx: TyCtxt<'_>, id: HirId, @@ -544,7 +556,7 @@ fn irrefutable_let_patterns( } match source { - LetSource::GenericLet => emit_diag!(IrrefutableLetPatternsGenericLet), + LetSource::None => bug!(), LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet), LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse), @@ -600,10 +612,11 @@ fn report_arm_reachability<'p, 'tcx>( /// Report that a match is not exhaustive. fn non_exhaustive_match<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, + thir: &Thir<'tcx>, scrut_ty: Ty<'tcx>, sp: Span, witnesses: Vec>, - arms: &[hir::Arm<'tcx>], + arms: &[ArmId], expr_span: Span, ) { let is_empty_match = arms.is_empty(); @@ -701,6 +714,7 @@ fn non_exhaustive_match<'p, 'tcx>( )); } [only] => { + let only = &thir[*only]; let (pre_indentation, is_multiline) = if let Some(snippet) = sm.indentation_before(only.span) && let Ok(with_trailing) = sm.span_extend_while(only.span, |c| c.is_whitespace() || c == ',') && sm.is_multiline(with_trailing) @@ -709,8 +723,9 @@ fn non_exhaustive_match<'p, 'tcx>( } else { (" ".to_string(), false) }; - let comma = if matches!(only.body.kind, hir::ExprKind::Block(..)) - && only.span.eq_ctxt(only.body.span) + let only_body = &thir[only.body]; + let comma = if matches!(only_body.kind, ExprKind::Block { .. }) + && only.span.eq_ctxt(only_body.span) && is_multiline { "" @@ -722,24 +737,29 @@ fn non_exhaustive_match<'p, 'tcx>( format!("{}{}{} => todo!()", comma, pre_indentation, pattern), )); } - [.., prev, last] if prev.span.eq_ctxt(last.span) => { - let comma = if matches!(last.body.kind, hir::ExprKind::Block(..)) - && last.span.eq_ctxt(last.body.span) - { - "" - } else { - "," - }; - let spacing = if sm.is_multiline(prev.span.between(last.span)) { - sm.indentation_before(last.span).map(|indent| format!("\n{indent}")) - } else { - Some(" ".to_string()) - }; - if let Some(spacing) = spacing { - suggestion = Some(( - last.span.shrink_to_hi(), - format!("{}{}{} => todo!()", comma, spacing, pattern), - )); + [.., prev, last] => { + let prev = &thir[*prev]; + let last = &thir[*last]; + if prev.span.eq_ctxt(last.span) { + let last_body = &thir[last.body]; + let comma = if matches!(last_body.kind, ExprKind::Block { .. }) + && last.span.eq_ctxt(last_body.span) + { + "" + } else { + "," + }; + let spacing = if sm.is_multiline(prev.span.between(last.span)) { + sm.indentation_before(last.span).map(|indent| format!("\n{indent}")) + } else { + Some(" ".to_string()) + }; + if let Some(spacing) = spacing { + suggestion = Some(( + last.span.shrink_to_hi(), + format!("{}{}{} => todo!()", comma, spacing, pattern), + )); + } } } _ => {} @@ -859,10 +879,6 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( } /// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. -fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId) -> bool { - !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx, cx.param_env) -} - /// Check that there are no borrow or move conflicts in `binding @ subpat` patterns. /// /// For example, this would reject: @@ -873,43 +889,31 @@ fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId) -> bool { /// - `x @ Some(ref mut? y)`. /// /// This analysis is *not* subsumed by NLL. -fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pat<'_>) { +fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) { // Extract `sub` in `binding @ sub`. - let (name, sub) = match &pat.kind { - hir::PatKind::Binding(.., name, Some(sub)) => (*name, sub), - _ => return, - }; - let mk_span = |pat_span, ident_span: Span| { - if let Some(ident_span) = ident_span.find_ancestor_inside(pat_span) { - pat_span.with_hi(ident_span.hi()) - } else { - pat_span - } - }; - let binding_span = mk_span(pat.span, name.span); + let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { return }; + let binding_span = pat.span; //.with_hi(name.span.hi()); + + let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); - let typeck_results = cx.typeck_results; let sess = cx.tcx.sess; // Get the binding move, extract the mutability if by-ref. - let mut_outer = match typeck_results.extract_binding_mode(sess, pat.hir_id, binding_span) { - Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id) => { + let mut_outer = match mode { + BindingMode::ByValue if is_binding_by_move(ty) => { // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. let mut conflicts_ref = Vec::new(); - sub.each_binding(|_, hir_id, span, ident| { - let span = mk_span(span, ident.span); - match typeck_results.extract_binding_mode(sess, hir_id, span) { - Some(ty::BindByValue(_)) | None => {} - Some(ty::BindByReference(_)) => conflicts_ref.push(span), - } + sub.each_binding(|_, mode, _, span| match mode { + BindingMode::ByValue => {} + BindingMode::ByRef(_) => conflicts_ref.push(span), }); if !conflicts_ref.is_empty() { sess.emit_err(BorrowOfMovedValue { - span: binding_span, + span: pat.span, binding_span, conflicts_ref, name, - ty: typeck_results.node_type(pat.hir_id), + ty, suggest_borrowing: pat .span .contains(binding_span) @@ -918,8 +922,8 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa } return; } - Some(ty::BindByValue(_)) | None => return, - Some(ty::BindByReference(m)) => m, + BindingMode::ByValue => return, + BindingMode::ByRef(m) => m.mutability(), }; // We now have `ref $mut_outer binding @ sub` (semantically). @@ -927,10 +931,9 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa let mut conflicts_move = Vec::new(); let mut conflicts_mut_mut = Vec::new(); let mut conflicts_mut_ref = Vec::new(); - sub.each_binding(|_, hir_id, span, name| { - let span = mk_span(span, name.span); - match typeck_results.extract_binding_mode(sess, hir_id, span) { - Some(ty::BindByReference(mut_inner)) => match (mut_outer, mut_inner) { + sub.each_binding(|name, mode, ty, span| { + match mode { + BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) { // Both sides are `ref`. (Mutability::Not, Mutability::Not) => {} // 2x `ref mut`. @@ -944,10 +947,10 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa conflicts_mut_ref.push(Conflict::Ref { span, name }) } }, - Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id) => { + BindingMode::ByValue if is_binding_by_move(ty) => { conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict. } - Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine. + BindingMode::ByValue => {} // `ref mut?` + by-copy is fine. } }); @@ -966,81 +969,19 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa // Report errors if any. if report_mut_mut { // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. - sess.emit_err(MultipleMutBorrows { span: binding_span, occurences }); + sess.emit_err(MultipleMutBorrows { span: pat.span, occurences }); } else if report_mut_ref { // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. match mut_outer { Mutability::Mut => { - sess.emit_err(AlreadyMutBorrowed { span: binding_span, occurences }); + sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurences }); } Mutability::Not => { - sess.emit_err(AlreadyBorrowed { span: binding_span, occurences }); + sess.emit_err(AlreadyBorrowed { span: pat.span, occurences }); } }; } else if report_move_conflict { // Report by-ref and by-move conflicts, e.g. `ref x @ y`. - sess.emit_err(MovedWhileBorrowed { span: binding_span, occurences }); + sess.emit_err(MovedWhileBorrowed { span: pat.span, occurences }); } } - -#[derive(Clone, Copy, Debug)] -pub enum LetSource { - GenericLet, - IfLet, - IfLetGuard, - LetElse, - WhileLet, -} - -fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource { - let hir = tcx.hir(); - - let parent = hir.parent_id(pat_id); - let_source_parent(tcx, parent, Some(pat_id)) -} - -fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option) -> LetSource { - let hir = tcx.hir(); - - let parent_node = hir.get(parent); - - match parent_node { - hir::Node::Arm(hir::Arm { - guard: Some(hir::Guard::IfLet(&hir::Let { pat: hir::Pat { hir_id, .. }, .. })), - .. - }) if Some(*hir_id) == pat_id => { - return LetSource::IfLetGuard; - } - _ => {} - } - - let parent_parent = hir.parent_id(parent); - let parent_parent_node = hir.get(parent_parent); - match parent_parent_node { - hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(_), .. }) => { - return LetSource::LetElse; - } - hir::Node::Arm(hir::Arm { guard: Some(hir::Guard::If(_)), .. }) => { - return LetSource::IfLetGuard; - } - _ => {} - } - - let parent_parent_parent = hir.parent_id(parent_parent); - let parent_parent_parent_parent = hir.parent_id(parent_parent_parent); - let parent_parent_parent_parent_node = hir.get(parent_parent_parent_parent); - - if let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _), - .. - }) = parent_parent_parent_parent_node - { - return LetSource::WhileLet; - } - - if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::If(..), .. }) = parent_parent_node { - return LetSource::IfLet; - } - - LetSource::GenericLet -} diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 9ac92f6e0a61..6e201b771ec6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -54,11 +54,9 @@ pub(super) fn pat_from_hir<'a, 'tcx>( pat: &'tcx hir::Pat<'tcx>, ) -> Box> { let mut pcx = PatCtxt::new(tcx, param_env, typeck_results); + pcx.include_lint_checks(); let result = pcx.lower_pattern(pat); - if !pcx.errors.is_empty() { - let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors); - tcx.sess.delay_span_bug(pat.span, &msg); - } + pcx.report_inlining_errors(); debug!("pat_from_hir({:?}) = {:?}", pat, result); result } @@ -77,6 +75,25 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self } + fn report_inlining_errors(&self) { + for error in &self.errors { + match *error { + PatternError::StaticInPattern(span) => { + self.tcx.sess.emit_err(StaticInPattern { span }); + } + PatternError::AssocConstInPattern(span) => { + self.tcx.sess.emit_err(AssocConstInPattern { span }); + } + PatternError::ConstParamInPattern(span) => { + self.tcx.sess.emit_err(ConstParamInPattern { span }); + } + PatternError::NonConstPath(span) => { + self.tcx.sess.emit_err(NonConstPath { span }); + } + } + } + } + fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { // When implicit dereferences have been inserted in this pattern, the unadjusted lowered // pattern has the type that results *after* dereferencing. For example, in this code: diff --git a/tests/ui/chalkify/bugs/async.stderr b/tests/ui/chalkify/bugs/async.stderr index 9c559640b230..36606fd49f27 100644 --- a/tests/ui/chalkify/bugs/async.stderr +++ b/tests/ui/chalkify/bugs/async.stderr @@ -14,14 +14,15 @@ LL | async fn foo(x: u32) -> u32 { | ^^^query stack during panic: #0 [typeck] type-checking `foo` #1 [thir_body] building THIR for `foo` -#2 [mir_built] building MIR for `foo` -#3 [unsafety_check_result] unsafety-checking `foo` -#4 [mir_const] preparing `foo` for borrow checking -#5 [mir_promoted] processing MIR for `foo` -#6 [mir_borrowck] borrow-checking `foo` -#7 [type_of] computing type of `foo::{opaque#0}` -#8 [check_mod_item_types] checking item types in top-level module -#9 [analysis] running analysis passes on this crate +#2 [check_match] match-checking `foo` +#3 [mir_built] building MIR for `foo` +#4 [unsafety_check_result] unsafety-checking `foo` +#5 [mir_const] preparing `foo` for borrow checking +#6 [mir_promoted] processing MIR for `foo` +#7 [mir_borrowck] borrow-checking `foo` +#8 [type_of] computing type of `foo::{opaque#0}` +#9 [check_mod_item_types] checking item types in top-level module +#10 [analysis] running analysis passes on this crate end of query stack error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.rs b/tests/ui/consts/const-eval/const-eval-overflow-2.rs index 535d91359163..c19a0c443ec5 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-2.rs +++ b/tests/ui/consts/const-eval/const-eval-overflow-2.rs @@ -14,7 +14,6 @@ fn main() { match -128i8 { NEG_NEG_128 => println!("A"), //~^ ERROR could not evaluate constant pattern - //~| ERROR could not evaluate constant pattern _ => println!("B"), } } diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr index 7b1fe49d4346..fc0baf11051b 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr +++ b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr @@ -10,12 +10,6 @@ error: could not evaluate constant pattern LL | NEG_NEG_128 => println!("A"), | ^^^^^^^^^^^ -error: could not evaluate constant pattern - --> $DIR/const-eval-overflow-2.rs:15:9 - | -LL | NEG_NEG_128 => println!("A"), - | ^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr index 032ceb2467c2..eaa2d6b27945 100644 --- a/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr +++ b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/ref_to_int_match.rs:25:27 + --> $DIR/ref_to_int_match.rs:24:27 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; | ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes @@ -13,12 +13,6 @@ error: could not evaluate constant pattern LL | 10..=BAR => {}, | ^^^ -error: could not evaluate constant pattern - --> $DIR/ref_to_int_match.rs:7:14 - | -LL | 10..=BAR => {}, - | ^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr index 032ceb2467c2..eaa2d6b27945 100644 --- a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr +++ b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/ref_to_int_match.rs:25:27 + --> $DIR/ref_to_int_match.rs:24:27 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; | ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes @@ -13,12 +13,6 @@ error: could not evaluate constant pattern LL | 10..=BAR => {}, | ^^^ -error: could not evaluate constant pattern - --> $DIR/ref_to_int_match.rs:7:14 - | -LL | 10..=BAR => {}, - | ^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ref_to_int_match.rs b/tests/ui/consts/const-eval/ref_to_int_match.rs index 70c6e7d94ae0..a2dabde25bc8 100644 --- a/tests/ui/consts/const-eval/ref_to_int_match.rs +++ b/tests/ui/consts/const-eval/ref_to_int_match.rs @@ -5,7 +5,6 @@ fn main() { match n { 0..=10 => {}, 10..=BAR => {}, //~ ERROR could not evaluate constant pattern - //~| ERROR could not evaluate constant pattern _ => {}, } } diff --git a/tests/ui/consts/const-match-check.eval1.stderr b/tests/ui/consts/const-match-check.eval1.stderr index 08fcd1deab1d..27ff5d4cd5c6 100644 --- a/tests/ui/consts/const-match-check.eval1.stderr +++ b/tests/ui/consts/const-match-check.eval1.stderr @@ -9,8 +9,8 @@ LL | A = { let 0 = 0; 0 }, = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | A = { if let 0 = 0 { todo!() } 0 }, - | ++ ~~~~~~~~~~~ +LL | A = { if let 0 = 0 { todo!() }; 0 }, + | ++ +++++++++++ help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits | LL | A = { let _0 = 0; 0 }, diff --git a/tests/ui/consts/const-match-check.eval2.stderr b/tests/ui/consts/const-match-check.eval2.stderr index 5d86ca4bfd17..0c74a7b3dd4d 100644 --- a/tests/ui/consts/const-match-check.eval2.stderr +++ b/tests/ui/consts/const-match-check.eval2.stderr @@ -9,8 +9,8 @@ LL | let x: [i32; { let 0 = 0; 0 }] = []; = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | let x: [i32; { if let 0 = 0 { todo!() } 0 }] = []; - | ++ ~~~~~~~~~~~ +LL | let x: [i32; { if let 0 = 0 { todo!() }; 0 }] = []; + | ++ +++++++++++ help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits | LL | let x: [i32; { let _0 = 0; 0 }] = []; diff --git a/tests/ui/consts/const-match-check.matchck.stderr b/tests/ui/consts/const-match-check.matchck.stderr index c8f66bb0fc02..bcca4c2a6478 100644 --- a/tests/ui/consts/const-match-check.matchck.stderr +++ b/tests/ui/consts/const-match-check.matchck.stderr @@ -9,8 +9,8 @@ LL | const X: i32 = { let 0 = 0; 0 }; = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; - | ++ ~~~~~~~~~~~ +LL | const X: i32 = { if let 0 = 0 { todo!() }; 0 }; + | ++ +++++++++++ help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits | LL | const X: i32 = { let _0 = 0; 0 }; @@ -27,8 +27,8 @@ LL | static Y: i32 = { let 0 = 0; 0 }; = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 }; - | ++ ~~~~~~~~~~~ +LL | static Y: i32 = { if let 0 = 0 { todo!() }; 0 }; + | ++ +++++++++++ help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits | LL | static Y: i32 = { let _0 = 0; 0 }; @@ -45,8 +45,8 @@ LL | const X: i32 = { let 0 = 0; 0 }; = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; - | ++ ~~~~~~~~~~~ +LL | const X: i32 = { if let 0 = 0 { todo!() }; 0 }; + | ++ +++++++++++ help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits | LL | const X: i32 = { let _0 = 0; 0 }; @@ -63,8 +63,8 @@ LL | const X: i32 = { let 0 = 0; 0 }; = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; - | ++ ~~~~~~~~~~~ +LL | const X: i32 = { if let 0 = 0 { todo!() }; 0 }; + | ++ +++++++++++ help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits | LL | const X: i32 = { let _0 = 0; 0 }; diff --git a/tests/ui/consts/const-pattern-irrefutable.rs b/tests/ui/consts/const-pattern-irrefutable.rs index 61bdf57ffdb9..d7d8e7328397 100644 --- a/tests/ui/consts/const-pattern-irrefutable.rs +++ b/tests/ui/consts/const-pattern-irrefutable.rs @@ -12,17 +12,14 @@ fn main() { let a = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable - //~| HELP introduce a variable instead + //~| HELP you might want to use `if let` to ignore the variants that aren't matched let c = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable - //~| HELP introduce a variable instead + //~| HELP you might want to use `if let` to ignore the variants that aren't matched let d = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable - //~| HELP introduce a variable instead + //~| HELP you might want to use `if let` to ignore the variants that aren't matched fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115). } diff --git a/tests/ui/consts/const-pattern-irrefutable.stderr b/tests/ui/consts/const-pattern-irrefutable.stderr index c156ea1610c4..956a97a476c1 100644 --- a/tests/ui/consts/const-pattern-irrefutable.stderr +++ b/tests/ui/consts/const-pattern-irrefutable.stderr @@ -1,47 +1,44 @@ error[E0005]: refutable pattern in local binding --> $DIR/const-pattern-irrefutable.rs:12:9 | -LL | const a: u8 = 2; - | ----------- constant defined here -... LL | let a = 4; - | ^ - | | - | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - | missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `a_var` + | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u8` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let a = 4 { todo!() }; + | ++ +++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:17:9 + --> $DIR/const-pattern-irrefutable.rs:16:9 | -LL | pub const b: u8 = 2; - | --------------- constant defined here -... LL | let c = 4; - | ^ - | | - | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - | missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `c_var` + | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u8` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let c = 4 { todo!() }; + | ++ +++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:22:9 + --> $DIR/const-pattern-irrefutable.rs:20:9 | -LL | pub const d: u8 = 2; - | --------------- constant defined here -... LL | let d = 4; - | ^ - | | - | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - | missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `d_var` + | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u8` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let d = 4 { todo!() }; + | ++ +++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/consts/const_in_pattern/incomplete-slice.stderr b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr index b005f3220e9c..be144a87b8b3 100644 --- a/tests/ui/consts/const_in_pattern/incomplete-slice.stderr +++ b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr @@ -19,7 +19,7 @@ LL | match &[][..] { = note: the matched value is of type `&[E]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ E_SL => {} +LL ~ E_SL => {}, LL + &_ => todo!() | diff --git a/tests/ui/consts/issue-43105.rs b/tests/ui/consts/issue-43105.rs index cac12b90970f..20b78d64209e 100644 --- a/tests/ui/consts/issue-43105.rs +++ b/tests/ui/consts/issue-43105.rs @@ -7,7 +7,6 @@ fn main() { match 1 { NUM => unimplemented!(), //~^ ERROR could not evaluate constant pattern - //~| ERROR could not evaluate constant pattern _ => unimplemented!(), } } diff --git a/tests/ui/consts/issue-43105.stderr b/tests/ui/consts/issue-43105.stderr index 2d1174af71c8..856a8f0dab6c 100644 --- a/tests/ui/consts/issue-43105.stderr +++ b/tests/ui/consts/issue-43105.stderr @@ -12,12 +12,6 @@ error: could not evaluate constant pattern LL | NUM => unimplemented!(), | ^^^ -error: could not evaluate constant pattern - --> $DIR/issue-43105.rs:8:9 - | -LL | NUM => unimplemented!(), - | ^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-73976-polymorphic.rs b/tests/ui/consts/issue-73976-polymorphic.rs index 787462da9f96..2c576d1f9ef0 100644 --- a/tests/ui/consts/issue-73976-polymorphic.rs +++ b/tests/ui/consts/issue-73976-polymorphic.rs @@ -19,7 +19,6 @@ impl GetTypeId { const fn check_type_id() -> bool { matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) //~^ ERROR constant pattern depends on a generic parameter - //~| ERROR constant pattern depends on a generic parameter } pub struct GetTypeNameLen(T); @@ -31,7 +30,6 @@ impl GetTypeNameLen { const fn check_type_name_len() -> bool { matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) //~^ ERROR constant pattern depends on a generic parameter - //~| ERROR constant pattern depends on a generic parameter } fn main() { diff --git a/tests/ui/consts/issue-73976-polymorphic.stderr b/tests/ui/consts/issue-73976-polymorphic.stderr index 442ad23f2cc4..97a5fbc5747a 100644 --- a/tests/ui/consts/issue-73976-polymorphic.stderr +++ b/tests/ui/consts/issue-73976-polymorphic.stderr @@ -5,22 +5,10 @@ LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^ error: constant pattern depends on a generic parameter - --> $DIR/issue-73976-polymorphic.rs:32:42 + --> $DIR/issue-73976-polymorphic.rs:31:42 | LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: constant pattern depends on a generic parameter - --> $DIR/issue-73976-polymorphic.rs:20:37 - | -LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^ - -error: constant pattern depends on a generic parameter - --> $DIR/issue-73976-polymorphic.rs:32:42 - | -LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/consts/issue-78655.rs b/tests/ui/consts/issue-78655.rs index 82d2d7c21d85..cd95ee32c60d 100644 --- a/tests/ui/consts/issue-78655.rs +++ b/tests/ui/consts/issue-78655.rs @@ -6,5 +6,4 @@ const FOO: *const u32 = { fn main() { let FOO = FOO; //~^ ERROR could not evaluate constant pattern - //~| ERROR could not evaluate constant pattern } diff --git a/tests/ui/consts/issue-78655.stderr b/tests/ui/consts/issue-78655.stderr index 6b83fa0e5a01..5a38d023d6f1 100644 --- a/tests/ui/consts/issue-78655.stderr +++ b/tests/ui/consts/issue-78655.stderr @@ -17,12 +17,6 @@ error: could not evaluate constant pattern LL | let FOO = FOO; | ^^^ -error: could not evaluate constant pattern - --> $DIR/issue-78655.rs:7:9 - | -LL | let FOO = FOO; - | ^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/consts/issue-79137-toogeneric.rs b/tests/ui/consts/issue-79137-toogeneric.rs index 456035458cfc..a80c9f48d7bc 100644 --- a/tests/ui/consts/issue-79137-toogeneric.rs +++ b/tests/ui/consts/issue-79137-toogeneric.rs @@ -11,7 +11,6 @@ impl GetVariantCount { const fn check_variant_count() -> bool { matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) //~^ ERROR constant pattern depends on a generic parameter - //~| ERROR constant pattern depends on a generic parameter } fn main() { diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr index 579e6aa09bdb..efe4fd22e547 100644 --- a/tests/ui/consts/issue-79137-toogeneric.stderr +++ b/tests/ui/consts/issue-79137-toogeneric.stderr @@ -4,11 +4,5 @@ error: constant pattern depends on a generic parameter LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: constant pattern depends on a generic parameter - --> $DIR/issue-79137-toogeneric.rs:12:43 - | -LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index 6df2fe3d03b9..e3a0d93f09b7 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -27,7 +27,7 @@ LL | const U8_MUT: &u8 = { } error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:43:9 + --> $DIR/const_refers_to_static_cross_crate.rs:42:9 | LL | U8_MUT => true, | ^^^^^^ @@ -39,7 +39,7 @@ LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:54:9 + --> $DIR/const_refers_to_static_cross_crate.rs:52:9 | LL | U8_MUT2 => true, | ^^^^^^^ @@ -51,31 +51,7 @@ LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:62:9 - | -LL | U8_MUT3 => true, - | ^^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:34:9 - | -LL | SLICE_MUT => true, - | ^^^^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:43:9 - | -LL | U8_MUT => true, - | ^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:54:9 - | -LL | U8_MUT2 => true, - | ^^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:62:9 + --> $DIR/const_refers_to_static_cross_crate.rs:59:9 | LL | U8_MUT3 => true, | ^^^^^^^ @@ -133,6 +109,6 @@ help: skipping check that does not even have a feature gate LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors; 1 warning emitted +error: aborting due to 8 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr index 8802f3adacae..a323e9a05f09 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -27,7 +27,7 @@ LL | const U8_MUT: &u8 = { } error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:43:9 + --> $DIR/const_refers_to_static_cross_crate.rs:42:9 | LL | U8_MUT => true, | ^^^^^^ @@ -39,7 +39,7 @@ LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:54:9 + --> $DIR/const_refers_to_static_cross_crate.rs:52:9 | LL | U8_MUT2 => true, | ^^^^^^^ @@ -51,31 +51,7 @@ LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:62:9 - | -LL | U8_MUT3 => true, - | ^^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:34:9 - | -LL | SLICE_MUT => true, - | ^^^^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:43:9 - | -LL | U8_MUT => true, - | ^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:54:9 - | -LL | U8_MUT2 => true, - | ^^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:62:9 + --> $DIR/const_refers_to_static_cross_crate.rs:59:9 | LL | U8_MUT3 => true, | ^^^^^^^ @@ -133,6 +109,6 @@ help: skipping check that does not even have a feature gate LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors; 1 warning emitted +error: aborting due to 8 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs index bf4f14f4d5a1..bbaa32ddfd1b 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -33,7 +33,6 @@ pub fn test(x: &[u8; 1]) -> bool { match x { SLICE_MUT => true, //~^ ERROR could not evaluate constant pattern - //~| ERROR could not evaluate constant pattern &[1..] => false, } } @@ -42,7 +41,6 @@ pub fn test2(x: &u8) -> bool { match x { U8_MUT => true, //~^ ERROR could not evaluate constant pattern - //~| ERROR could not evaluate constant pattern &(1..) => false, } } @@ -53,7 +51,6 @@ pub fn test3(x: &u8) -> bool { match x { U8_MUT2 => true, //~^ ERROR could not evaluate constant pattern - //~| ERROR could not evaluate constant pattern &(1..) => false, } } @@ -61,7 +58,6 @@ pub fn test4(x: &u8) -> bool { match x { U8_MUT3 => true, //~^ ERROR could not evaluate constant pattern - //~| ERROR could not evaluate constant pattern &(1..) => false, } } diff --git a/tests/ui/error-codes/E0004.stderr b/tests/ui/error-codes/E0004.stderr index 4ac8c904f053..603bc5237ea2 100644 --- a/tests/ui/error-codes/E0004.stderr +++ b/tests/ui/error-codes/E0004.stderr @@ -14,7 +14,7 @@ LL | HastaLaVistaBaby, = note: the matched value is of type `Terminator` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Terminator::TalkToMyHand => {} +LL ~ Terminator::TalkToMyHand => {}, LL + Terminator::HastaLaVistaBaby => todo!() | diff --git a/tests/ui/error-codes/E0030-teach.rs b/tests/ui/error-codes/E0030-teach.rs index 8caa4f0931d5..388064fb0fae 100644 --- a/tests/ui/error-codes/E0030-teach.rs +++ b/tests/ui/error-codes/E0030-teach.rs @@ -4,6 +4,5 @@ fn main() { match 5u32 { 1000 ..= 5 => {} //~^ ERROR lower range bound must be less than or equal to upper - //~| ERROR lower range bound must be less than or equal to upper } } diff --git a/tests/ui/error-codes/E0030-teach.stderr b/tests/ui/error-codes/E0030-teach.stderr index 800f66416a81..3f1ad4af3a94 100644 --- a/tests/ui/error-codes/E0030-teach.stderr +++ b/tests/ui/error-codes/E0030-teach.stderr @@ -6,12 +6,6 @@ LL | 1000 ..= 5 => {} | = note: When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. -error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/E0030-teach.rs:5:9 - | -LL | 1000 ..= 5 => {} - | ^^^^ lower bound larger than upper bound - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0030`. diff --git a/tests/ui/error-codes/E0030.rs b/tests/ui/error-codes/E0030.rs index a5d8f87261b2..58d856b7c9d2 100644 --- a/tests/ui/error-codes/E0030.rs +++ b/tests/ui/error-codes/E0030.rs @@ -2,6 +2,5 @@ fn main() { match 5u32 { 1000 ..= 5 => {} //~^ ERROR lower range bound must be less than or equal to upper - //~| ERROR lower range bound must be less than or equal to upper } } diff --git a/tests/ui/error-codes/E0030.stderr b/tests/ui/error-codes/E0030.stderr index 8a6114024b63..db8161d8fd5d 100644 --- a/tests/ui/error-codes/E0030.stderr +++ b/tests/ui/error-codes/E0030.stderr @@ -4,12 +4,6 @@ error[E0030]: lower range bound must be less than or equal to upper LL | 1000 ..= 5 => {} | ^^^^ lower bound larger than upper bound -error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/E0030.rs:3:9 - | -LL | 1000 ..= 5 => {} - | ^^^^ lower bound larger than upper bound - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0030`. diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr index 4d79ce3c6594..fb39c404c207 100644 --- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr +++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -115,7 +115,7 @@ LL | A, B, C, = note: the matched value is of type `Foo` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Foo::B => {} +LL ~ Foo::B => {}, LL + Foo::C => todo!() | diff --git a/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr index b5510683328f..853b57052ace 100644 --- a/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr +++ b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr @@ -9,7 +9,7 @@ LL | match 0usize { = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ 0..=usize::MAX => {} +LL ~ 0..=usize::MAX => {}, LL + _ => todo!() | @@ -24,7 +24,7 @@ LL | match 0isize { = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ isize::MIN..=isize::MAX => {} +LL ~ isize::MIN..=isize::MAX => {}, LL + _ => todo!() | diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs index f55566602dba..4b14a314e7ae 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs @@ -10,44 +10,31 @@ macro_rules! m { fn main() { m!(0, ..u8::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0, ..u16::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0, ..u32::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0, ..u64::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0, ..u128::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0, ..i8::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0, ..i16::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0, ..i32::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0, ..i64::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0, ..i128::MIN); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0f32, ..f32::NEG_INFINITY); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!(0f64, ..f64::NEG_INFINITY); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper m!('a', ..'\u{0}'); //~^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr index 56b224a8542b..e9702bb380fb 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr @@ -5,155 +5,77 @@ LL | m!(0, ..u8::MIN); | ^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:13:11 | LL | m!(0, ..u16::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:15:11 | LL | m!(0, ..u32::MIN); | ^^^^^^^^^^ -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:20:11 - | -LL | m!(0, ..u64::MIN); - | ^^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11 - | -LL | m!(0, ..u128::MIN); - | ^^^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11 - | -LL | m!(0, ..i8::MIN); - | ^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11 - | -LL | m!(0, ..i16::MIN); - | ^^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:11 - | -LL | m!(0, ..i32::MIN); - | ^^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:36:11 - | -LL | m!(0, ..i64::MIN); - | ^^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:39:11 - | -LL | m!(0, ..i128::MIN); - | ^^^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:43:14 - | -LL | m!(0f32, ..f32::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:46:14 - | -LL | m!(0f64, ..f64::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:50:13 - | -LL | m!('a', ..'\u{0}'); - | ^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:11:11 - | -LL | m!(0, ..u8::MIN); - | ^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11 - | -LL | m!(0, ..u16::MIN); - | ^^^^^^^^^^ - error[E0579]: lower range bound must be less than upper --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11 | -LL | m!(0, ..u32::MIN); - | ^^^^^^^^^^ - -error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:20:11 - | LL | m!(0, ..u64::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:19:11 | LL | m!(0, ..u128::MIN); | ^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:22:11 | LL | m!(0, ..i8::MIN); | ^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:24:11 | LL | m!(0, ..i16::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:26:11 | LL | m!(0, ..i32::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:36:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:28:11 | LL | m!(0, ..i64::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:39:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11 | LL | m!(0, ..i128::MIN); | ^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:43:14 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:14 | LL | m!(0f32, ..f32::NEG_INFINITY); | ^^^^^^^^^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:46:14 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:35:14 | LL | m!(0f64, ..f64::NEG_INFINITY); | ^^^^^^^^^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:50:13 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:38:13 | LL | m!('a', ..'\u{0}'); | ^^^^^^^^^ -error: aborting due to 26 previous errors +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0579`. diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr index fd0358421ebf..e6c750d0e427 100644 --- a/tests/ui/impl-trait/auto-trait-leak.stderr +++ b/tests/ui/impl-trait/auto-trait-leak.stderr @@ -29,6 +29,11 @@ note: ...which requires building MIR for `cycle1`... | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires match-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires building THIR for `cycle1`... --> $DIR/auto-trait-leak.rs:12:1 | @@ -70,6 +75,11 @@ note: ...which requires building MIR for `cycle2`... | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires match-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:19:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires building THIR for `cycle2`... --> $DIR/auto-trait-leak.rs:19:1 | diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs index 7c0d83516ea2..46e501abf6c2 100644 --- a/tests/ui/inline-const/const-match-pat-generic.rs +++ b/tests/ui/inline-const/const-match-pat-generic.rs @@ -7,7 +7,6 @@ fn foo() { match 0 { const { V } => {}, //~^ ERROR constant pattern depends on a generic parameter - //~| ERROR constant pattern depends on a generic parameter _ => {}, } } @@ -20,7 +19,6 @@ fn bar() { match 0 { const { f(V) } => {}, //~^ ERROR constant pattern depends on a generic parameter - //~| ERROR constant pattern depends on a generic parameter _ => {}, } } diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr index 77267f12fb11..4ffbde4101d7 100644 --- a/tests/ui/inline-const/const-match-pat-generic.stderr +++ b/tests/ui/inline-const/const-match-pat-generic.stderr @@ -5,22 +5,10 @@ LL | const { V } => {}, | ^^^^^^^^^^^ error: constant pattern depends on a generic parameter - --> $DIR/const-match-pat-generic.rs:21:9 + --> $DIR/const-match-pat-generic.rs:20:9 | LL | const { f(V) } => {}, | ^^^^^^^^^^^^^^ -error: constant pattern depends on a generic parameter - --> $DIR/const-match-pat-generic.rs:8:9 - | -LL | const { V } => {}, - | ^^^^^^^^^^^ - -error: constant pattern depends on a generic parameter - --> $DIR/const-match-pat-generic.rs:21:9 - | -LL | const { f(V) } => {}, - | ^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/match/match-range-fail-2.rs b/tests/ui/match/match-range-fail-2.rs index 792664e1db82..4489cf1ab1f2 100644 --- a/tests/ui/match/match-range-fail-2.rs +++ b/tests/ui/match/match-range-fail-2.rs @@ -3,22 +3,19 @@ fn main() { match 5 { 6 ..= 1 => { } + //~^ ERROR lower range bound must be less than or equal to upper _ => { } }; - //~^^^ ERROR lower range bound must be less than or equal to upper - //~| ERROR lower range bound must be less than or equal to upper match 5 { 0 .. 0 => { } + //~^ ERROR lower range bound must be less than upper _ => { } }; - //~^^^ ERROR lower range bound must be less than upper - //~| ERROR lower range bound must be less than upper match 5u64 { 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + //~^ ERROR lower range bound must be less than or equal to upper _ => { } }; - //~^^^ ERROR lower range bound must be less than or equal to upper - //~| ERROR lower range bound must be less than or equal to upper } diff --git a/tests/ui/match/match-range-fail-2.stderr b/tests/ui/match/match-range-fail-2.stderr index 7a0852d7e6ce..52a2bf2b34aa 100644 --- a/tests/ui/match/match-range-fail-2.stderr +++ b/tests/ui/match/match-range-fail-2.stderr @@ -5,36 +5,18 @@ LL | 6 ..= 1 => { } | ^ lower bound larger than upper bound error[E0579]: lower range bound must be less than upper - --> $DIR/match-range-fail-2.rs:12:9 + --> $DIR/match-range-fail-2.rs:11:9 | LL | 0 .. 0 => { } | ^ error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/match-range-fail-2.rs:19:9 + --> $DIR/match-range-fail-2.rs:17:9 | LL | 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } | ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound -error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/match-range-fail-2.rs:5:9 - | -LL | 6 ..= 1 => { } - | ^ lower bound larger than upper bound - -error[E0579]: lower range bound must be less than upper - --> $DIR/match-range-fail-2.rs:12:9 - | -LL | 0 .. 0 => { } - | ^ - -error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/match-range-fail-2.rs:19:9 - | -LL | 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } - | ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0030, E0579. For more information about an error, try `rustc --explain E0030`. diff --git a/tests/ui/never_type/exhaustive_patterns.stderr b/tests/ui/never_type/exhaustive_patterns.stderr index 40c7c1d1067f..5fed903eb70a 100644 --- a/tests/ui/never_type/exhaustive_patterns.stderr +++ b/tests/ui/never_type/exhaustive_patterns.stderr @@ -17,8 +17,8 @@ LL | B(inner::Wrapper), = note: the matched value is of type `Either<(), !>` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Either::A(()) = foo() { todo!() } - | ++ ~~~~~~~~~~~ +LL | if let Either::A(()) = foo() { todo!() }; + | ++ +++++++++++ error: aborting due to previous error diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr index 9aa808e6bc9a..9f691aea8a79 100644 --- a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr +++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr @@ -7,7 +7,7 @@ LL | match (0u8, 0u8) { = note: the matched value is of type `(u8, u8)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ (0 | 1, 2 | 3) => {} +LL ~ (0 | 1, 2 | 3) => {}, LL + (2_u8..=u8::MAX, _) => todo!() | @@ -20,7 +20,7 @@ LL | match ((0u8,),) { = note: the matched value is of type `((u8,),)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ ((0 | 1,) | (2 | 3,),) => {} +LL ~ ((0 | 1,) | (2 | 3,),) => {}, LL + ((4_u8..=u8::MAX)) => todo!() | @@ -33,7 +33,7 @@ LL | match (Some(0u8),) { = note: the matched value is of type `(Option,)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ (None | Some(0 | 1),) => {} +LL ~ (None | Some(0 | 1),) => {}, LL + (Some(2_u8..=u8::MAX)) => todo!() | diff --git a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr index 4adcf4feee90..fdb1a9bb4b78 100644 --- a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr +++ b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -9,8 +9,8 @@ LL | let (0 | (1 | 2)) = 0; = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let (0 | (1 | 2)) = 0 { todo!() } - | ++ ~~~~~~~~~~~ +LL | if let (0 | (1 | 2)) = 0 { todo!() }; + | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11 @@ -21,7 +21,7 @@ LL | match 0 { = note: the matched value is of type `i32` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ 0 | (1 | 2) => {} +LL ~ 0 | (1 | 2) => {}, LL + i32::MIN..=-1_i32 | 3_i32..=i32::MAX => todo!() | diff --git a/tests/ui/pattern/issue-106552.stderr b/tests/ui/pattern/issue-106552.stderr index ed5d40c09685..96f3d68458fa 100644 --- a/tests/ui/pattern/issue-106552.stderr +++ b/tests/ui/pattern/issue-106552.stderr @@ -9,8 +9,8 @@ LL | let 5 = 6; = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let 5 = 6 { todo!() } - | ++ ~~~~~~~~~~~ +LL | if let 5 = 6 { todo!() }; + | ++ +++++++++++ help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits | LL | let _5 = 6; @@ -20,7 +20,7 @@ error[E0005]: refutable pattern in local binding --> $DIR/issue-106552.rs:5:9 | LL | let x @ 5 = 6; - | ^^^^^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered + | ^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html diff --git a/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr index 54ecc24981f8..62c90b638d7c 100644 --- a/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr +++ b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr @@ -1,15 +1,15 @@ -error[E0158]: associated consts cannot be referenced in patterns - --> $DIR/issue-68393-let-pat-assoc-constant.rs:20:40 - | -LL | pub fn test(arg: EFoo, A::X: EFoo) { - | ^^^^ - error[E0158]: associated consts cannot be referenced in patterns --> $DIR/issue-68393-let-pat-assoc-constant.rs:22:9 | LL | let A::X = arg; | ^^^^ +error[E0158]: associated consts cannot be referenced in patterns + --> $DIR/issue-68393-let-pat-assoc-constant.rs:20:40 + | +LL | pub fn test(arg: EFoo, A::X: EFoo) { + | ^^^^ + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0158`. diff --git a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed index b28dce881059..b469fade3ea5 100644 --- a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed +++ b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed @@ -4,7 +4,7 @@ fn main() { match Some(1) { //~ ERROR non-exhaustive patterns: `None` not covered Some(1) => {} // hello - Some(_) => {} + Some(_) => {}, None => todo!() } } diff --git a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr index 2a016048f2f7..5f2c89246e39 100644 --- a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr +++ b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr @@ -12,7 +12,7 @@ note: `Option` defined here = note: the matched value is of type `Option` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Some(_) => {} +LL ~ Some(_) => {}, LL + None => todo!() | diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 08e3d76b538b..3f0b4a9f26a8 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -7,21 +7,6 @@ LL | FOO => {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: unreachable pattern - --> $DIR/consts-opaque.rs:32:9 - | -LL | FOO => {} - | --- matches any value -LL | -LL | _ => {} // should not be emitting unreachable warning - | ^ unreachable pattern - | -note: the lint level is defined here - --> $DIR/consts-opaque.rs:6:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` --> $DIR/consts-opaque.rs:37:9 | @@ -31,15 +16,6 @@ LL | FOO_REF => {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: unreachable pattern - --> $DIR/consts-opaque.rs:39:9 - | -LL | FOO_REF => {} - | ------- matches any value -LL | -LL | Foo(_) => {} // should not be emitting unreachable warning - | ^^^^^^ unreachable pattern - warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` --> $DIR/consts-opaque.rs:45:9 | @@ -61,23 +37,6 @@ LL | BAR => {} // should not be emitting unreachable warning = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: unreachable pattern - --> $DIR/consts-opaque.rs:53:9 - | -LL | Bar => {} - | --- matches any value -LL | BAR => {} // should not be emitting unreachable warning - | ^^^ unreachable pattern - -error: unreachable pattern - --> $DIR/consts-opaque.rs:56:9 - | -LL | Bar => {} - | --- matches any value -... -LL | _ => {} - | ^ unreachable pattern - error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` --> $DIR/consts-opaque.rs:61:9 | @@ -87,24 +46,6 @@ LL | BAR => {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: unreachable pattern - --> $DIR/consts-opaque.rs:63:9 - | -LL | BAR => {} - | --- matches any value -LL | -LL | Bar => {} // should not be emitting unreachable warning - | ^^^ unreachable pattern - -error: unreachable pattern - --> $DIR/consts-opaque.rs:65:9 - | -LL | BAR => {} - | --- matches any value -... -LL | _ => {} - | ^ unreachable pattern - error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` --> $DIR/consts-opaque.rs:70:9 | @@ -123,6 +64,92 @@ LL | BAR => {} // should not be emitting unreachable warning = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details +error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:80:9 + | +LL | BAZ => {} + | ^^^ + | + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details + +error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:90:9 + | +LL | BAZ => {} + | ^^^ + | + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details + +error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:97:9 + | +LL | BAZ => {} + | ^^^ + | + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details + +error: unreachable pattern + --> $DIR/consts-opaque.rs:32:9 + | +LL | FOO => {} + | --- matches any value +LL | +LL | _ => {} // should not be emitting unreachable warning + | ^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/consts-opaque.rs:6:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:39:9 + | +LL | FOO_REF => {} + | ------- matches any value +LL | +LL | Foo(_) => {} // should not be emitting unreachable warning + | ^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:53:9 + | +LL | Bar => {} + | --- matches any value +LL | BAR => {} // should not be emitting unreachable warning + | ^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:56:9 + | +LL | Bar => {} + | --- matches any value +... +LL | _ => {} + | ^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:63:9 + | +LL | BAR => {} + | --- matches any value +LL | +LL | Bar => {} // should not be emitting unreachable warning + | ^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:65:9 + | +LL | BAR => {} + | --- matches any value +... +LL | _ => {} + | ^ unreachable pattern + error: unreachable pattern --> $DIR/consts-opaque.rs:72:9 | @@ -141,15 +168,6 @@ LL | BAR => {} LL | _ => {} // should not be emitting unreachable warning | ^ unreachable pattern -error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:80:9 - | -LL | BAZ => {} - | ^^^ - | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details - error: unreachable pattern --> $DIR/consts-opaque.rs:82:9 | @@ -168,15 +186,6 @@ LL | BAZ => {} LL | _ => {} | ^ unreachable pattern -error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:90:9 - | -LL | BAZ => {} - | ^^^ - | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details - error: unreachable pattern --> $DIR/consts-opaque.rs:92:9 | @@ -186,15 +195,6 @@ LL | LL | _ => {} | ^ unreachable pattern -error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:97:9 - | -LL | BAZ => {} - | ^^^ - | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details - error: unreachable pattern --> $DIR/consts-opaque.rs:99:9 | diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr index 17e1a2304a13..ff29de03d6b3 100644 --- a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr +++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -12,7 +12,7 @@ LL | pub enum HiddenEnum { = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ HiddenEnum::B => {} +LL ~ HiddenEnum::B => {}, LL + _ => todo!() | @@ -33,7 +33,7 @@ LL | B, = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ HiddenEnum::C => {} +LL ~ HiddenEnum::C => {}, LL + HiddenEnum::B => todo!() | @@ -54,7 +54,7 @@ LL | B, = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ HiddenEnum::A => {} +LL ~ HiddenEnum::A => {}, LL + HiddenEnum::B | _ => todo!() | @@ -72,7 +72,7 @@ note: `Option` defined here = note: the matched value is of type `Option` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ Some(HiddenEnum::A) => {} +LL ~ Some(HiddenEnum::A) => {}, LL + Some(HiddenEnum::B) | Some(_) => todo!() | @@ -93,7 +93,7 @@ LL | C, = note: the matched value is of type `InCrate` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ InCrate::B => {} +LL ~ InCrate::B => {}, LL + InCrate::C => todo!() | diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index 5e12bc1d22f0..5a145efce948 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -162,7 +162,7 @@ LL | match_guarded_arm!(0u8); = note: the matched value is of type `u8` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + _ => todo!() | @@ -180,7 +180,7 @@ LL | struct NonEmptyStruct1; = note: the matched value is of type `NonEmptyStruct1` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyStruct1 => todo!() | @@ -198,7 +198,7 @@ LL | struct NonEmptyStruct2(bool); = note: the matched value is of type `NonEmptyStruct2` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyStruct2(_) => todo!() | @@ -216,7 +216,7 @@ LL | union NonEmptyUnion1 { = note: the matched value is of type `NonEmptyUnion1` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyUnion1 { .. } => todo!() | @@ -234,7 +234,7 @@ LL | union NonEmptyUnion2 { = note: the matched value is of type `NonEmptyUnion2` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyUnion2 { .. } => todo!() | @@ -254,7 +254,7 @@ LL | Foo(bool), = note: the matched value is of type `NonEmptyEnum1` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyEnum1::Foo(_) => todo!() | @@ -276,7 +276,7 @@ LL | Bar, = note: the matched value is of type `NonEmptyEnum2` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | @@ -294,7 +294,7 @@ LL | enum NonEmptyEnum5 { = note: the matched value is of type `NonEmptyEnum5` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + _ => todo!() | diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index 5e12bc1d22f0..5a145efce948 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -162,7 +162,7 @@ LL | match_guarded_arm!(0u8); = note: the matched value is of type `u8` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + _ => todo!() | @@ -180,7 +180,7 @@ LL | struct NonEmptyStruct1; = note: the matched value is of type `NonEmptyStruct1` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyStruct1 => todo!() | @@ -198,7 +198,7 @@ LL | struct NonEmptyStruct2(bool); = note: the matched value is of type `NonEmptyStruct2` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyStruct2(_) => todo!() | @@ -216,7 +216,7 @@ LL | union NonEmptyUnion1 { = note: the matched value is of type `NonEmptyUnion1` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyUnion1 { .. } => todo!() | @@ -234,7 +234,7 @@ LL | union NonEmptyUnion2 { = note: the matched value is of type `NonEmptyUnion2` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyUnion2 { .. } => todo!() | @@ -254,7 +254,7 @@ LL | Foo(bool), = note: the matched value is of type `NonEmptyEnum1` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyEnum1::Foo(_) => todo!() | @@ -276,7 +276,7 @@ LL | Bar, = note: the matched value is of type `NonEmptyEnum2` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | @@ -294,7 +294,7 @@ LL | enum NonEmptyEnum5 { = note: the matched value is of type `NonEmptyEnum5` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ _ if false => {} +LL ~ _ if false => {}, LL + _ => todo!() | diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr index c926e50b3580..d66d4ba298be 100644 --- a/tests/ui/pattern/usefulness/floats.stderr +++ b/tests/ui/pattern/usefulness/floats.stderr @@ -7,7 +7,7 @@ LL | match 0.0 { = note: the matched value is of type `f64` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ 0.0..=1.0 => {} +LL ~ 0.0..=1.0 => {}, LL + _ => todo!() | diff --git a/tests/ui/pattern/usefulness/guards.stderr b/tests/ui/pattern/usefulness/guards.stderr index 0c1563c160c1..fc6748958de5 100644 --- a/tests/ui/pattern/usefulness/guards.stderr +++ b/tests/ui/pattern/usefulness/guards.stderr @@ -7,7 +7,7 @@ LL | match 0u8 { = note: the matched value is of type `u8` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ 128 ..= 255 if true => {} +LL ~ 128 ..= 255 if true => {}, LL + 128_u8..=u8::MAX => todo!() | diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr index f30ba05dff9e..b585de206291 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr @@ -91,7 +91,7 @@ LL | match 0i8 { = note: the matched value is of type `i8` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ 1 ..= i8::MAX => {} +LL ~ 1 ..= i8::MAX => {}, LL + 0_i8 => todo!() | @@ -140,7 +140,7 @@ LL | match (0u8, true) { = note: the matched value is of type `(u8, bool)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ (0 ..= 255, true) => {} +LL ~ (0 ..= 255, true) => {}, LL + (126_u8..=127_u8, false) => todo!() | diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr index e3eb98ccdcda..0e0f0c3e11ee 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr @@ -9,7 +9,7 @@ LL | match 0usize { = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ 0 ..= usize::MAX => {} +LL ~ 0 ..= usize::MAX => {}, LL + _ => todo!() | @@ -24,7 +24,7 @@ LL | match 0isize { = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ isize::MIN ..= isize::MAX => {} +LL ~ isize::MIN ..= isize::MAX => {}, LL + _ => todo!() | @@ -147,7 +147,7 @@ LL | match 0isize { = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ 1 ..= isize::MAX => {} +LL ~ 1 ..= isize::MAX => {}, LL + _ => todo!() | diff --git a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr index 30492c98206c..b80411b26b04 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr @@ -9,7 +9,7 @@ LL | match 0usize { = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ 0..=usize::MAX => {} +LL ~ 0..=usize::MAX => {}, LL + _ => todo!() | @@ -24,7 +24,7 @@ LL | match 0isize { = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ isize::MIN..=isize::MAX => {} +LL ~ isize::MIN..=isize::MAX => {}, LL + _ => todo!() | diff --git a/tests/ui/pattern/usefulness/issue-2111.stderr b/tests/ui/pattern/usefulness/issue-2111.stderr index 01890b73cbdd..7f7c5a0f19de 100644 --- a/tests/ui/pattern/usefulness/issue-2111.stderr +++ b/tests/ui/pattern/usefulness/issue-2111.stderr @@ -7,7 +7,7 @@ LL | match (a, b) { = note: the matched value is of type `(Option, Option)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ (Some(_), None) | (None, Some(_)) => {} +LL ~ (Some(_), None) | (None, Some(_)) => {}, LL + (None, None) | (Some(_), Some(_)) => todo!() | diff --git a/tests/ui/pattern/usefulness/issue-30240.stderr b/tests/ui/pattern/usefulness/issue-30240.stderr index 759fdeafe4eb..ff755d681ac7 100644 --- a/tests/ui/pattern/usefulness/issue-30240.stderr +++ b/tests/ui/pattern/usefulness/issue-30240.stderr @@ -7,7 +7,7 @@ LL | match "world" { = note: the matched value is of type `&str` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ "hello" => {} +LL ~ "hello" => {}, LL + &_ => todo!() | @@ -20,7 +20,7 @@ LL | match "world" { = note: the matched value is of type `&str` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ "hello" => {} +LL ~ "hello" => {}, LL + &_ => todo!() | diff --git a/tests/ui/pattern/usefulness/issue-35609.stderr b/tests/ui/pattern/usefulness/issue-35609.stderr index 12113957d634..6d5e2f410bc9 100644 --- a/tests/ui/pattern/usefulness/issue-35609.stderr +++ b/tests/ui/pattern/usefulness/issue-35609.stderr @@ -7,7 +7,7 @@ LL | match (A, ()) { = note: the matched value is of type `(Enum, ())` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ (A, _) => {} +LL ~ (A, _) => {}, LL + _ => todo!() | @@ -20,7 +20,7 @@ LL | match (A, A) { = note: the matched value is of type `(Enum, Enum)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ (_, A) => {} +LL ~ (_, A) => {}, LL + _ => todo!() | @@ -33,7 +33,7 @@ LL | match ((A, ()), ()) { = note: the matched value is of type `((Enum, ()), ())` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ ((A, ()), _) => {} +LL ~ ((A, ()), _) => {}, LL + _ => todo!() | @@ -46,7 +46,7 @@ LL | match ((A, ()), A) { = note: the matched value is of type `((Enum, ()), Enum)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ ((A, ()), _) => {} +LL ~ ((A, ()), _) => {}, LL + _ => todo!() | @@ -59,7 +59,7 @@ LL | match ((A, ()), ()) { = note: the matched value is of type `((Enum, ()), ())` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ ((A, _), _) => {} +LL ~ ((A, _), _) => {}, LL + _ => todo!() | @@ -77,7 +77,7 @@ LL | struct S(Enum, ()); = note: the matched value is of type `S` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ S(A, _) => {} +LL ~ S(A, _) => {}, LL + _ => todo!() | @@ -95,7 +95,7 @@ LL | struct Sd { x: Enum, y: () } = note: the matched value is of type `Sd` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ Sd { x: A, y: _ } => {} +LL ~ Sd { x: A, y: _ } => {}, LL + _ => todo!() | diff --git a/tests/ui/pattern/usefulness/issue-3601.stderr b/tests/ui/pattern/usefulness/issue-3601.stderr index 59d7bcd4b5e7..2f6b167d4f8b 100644 --- a/tests/ui/pattern/usefulness/issue-3601.stderr +++ b/tests/ui/pattern/usefulness/issue-3601.stderr @@ -9,7 +9,7 @@ note: `Box` defined here = note: the matched value is of type `Box` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true } +LL ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }, LL + box _ => todo!() | diff --git a/tests/ui/pattern/usefulness/issue-50900.stderr b/tests/ui/pattern/usefulness/issue-50900.stderr index 348246d28aac..7880c8925671 100644 --- a/tests/ui/pattern/usefulness/issue-50900.stderr +++ b/tests/ui/pattern/usefulness/issue-50900.stderr @@ -12,7 +12,7 @@ LL | pub struct Tag(pub Context, pub u16); = note: the matched value is of type `Tag` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Tag::ExifIFDPointer => {} +LL ~ Tag::ExifIFDPointer => {}, LL + Tag(Context::Exif, _) => todo!() | diff --git a/tests/ui/pattern/usefulness/issue-56379.stderr b/tests/ui/pattern/usefulness/issue-56379.stderr index 6eed6bfae4c9..b3e40b992399 100644 --- a/tests/ui/pattern/usefulness/issue-56379.stderr +++ b/tests/ui/pattern/usefulness/issue-56379.stderr @@ -18,7 +18,7 @@ LL | C(bool), = note: the matched value is of type `Foo` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ Foo::C(true) => {} +LL ~ Foo::C(true) => {}, LL + Foo::A(false) | Foo::B(false) | Foo::C(false) => todo!() | diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr index a90f32f7aebf..3c482eef2105 100644 --- a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr @@ -7,7 +7,7 @@ LL | match buf { = note: the matched value is of type `&[u8; 4]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ b"AAAA" => {} +LL ~ b"AAAA" => {}, LL + &[0_u8..=64_u8, _, _, _] | &[66_u8..=u8::MAX, _, _, _] => todo!() | @@ -20,7 +20,7 @@ LL | match buf { = note: the matched value is of type `&[u8]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ b"AAAA" => {} +LL ~ b"AAAA" => {}, LL + _ => todo!() | diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.stderr index 86f75d15cfde..45352f09417f 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.stderr +++ b/tests/ui/pattern/usefulness/match-privately-empty.stderr @@ -12,7 +12,7 @@ note: `Option` defined here = note: the matched value is of type `Option` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ }) => {} +LL ~ }) => {}, LL + Some(Private { misc: true, .. }) => todo!() | diff --git a/tests/ui/pattern/usefulness/match-slice-patterns.stderr b/tests/ui/pattern/usefulness/match-slice-patterns.stderr index 961dd5901196..63d1f38e9db4 100644 --- a/tests/ui/pattern/usefulness/match-slice-patterns.stderr +++ b/tests/ui/pattern/usefulness/match-slice-patterns.stderr @@ -7,7 +7,7 @@ LL | match list { = note: the matched value is of type `&[Option<()>]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ &[.., Some(_), _] => {} +LL ~ &[.., Some(_), _] => {}, LL ~ &[_, Some(_), .., None, _] => todo!(), | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr index 769d4070fb58..8489e2f14b87 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -18,7 +18,7 @@ LL | C = note: the matched value is of type `E` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ E::A => {} +LL ~ E::A => {}, LL + E::B | E::C => todo!() | @@ -44,8 +44,8 @@ LL | C = note: the matched value is of type `E` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let E::A = e { todo!() } - | ++ ~~~~~~~~~~~ +LL | if let E::A = e { todo!() }; + | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered --> $DIR/non-exhaustive-defined-here.rs:50:11 @@ -67,7 +67,7 @@ LL | C = note: the matched value is of type `&E` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ E::A => {} +LL ~ E::A => {}, LL + &E::B | &E::C => todo!() | @@ -93,8 +93,8 @@ LL | C = note: the matched value is of type `&E` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let E::A = e { todo!() } - | ++ ~~~~~~~~~~~ +LL | if let E::A = e { todo!() }; + | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered --> $DIR/non-exhaustive-defined-here.rs:66:11 @@ -116,7 +116,7 @@ LL | C = note: the matched value is of type `&&mut &E` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ E::A => {} +LL ~ E::A => {}, LL + &&mut &E::B | &&mut &E::C => todo!() | @@ -142,8 +142,8 @@ LL | C = note: the matched value is of type `&&mut &E` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let E::A = e { todo!() } - | ++ ~~~~~~~~~~~ +LL | if let E::A = e { todo!() }; + | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `Opt::None` not covered --> $DIR/non-exhaustive-defined-here.rs:92:11 @@ -162,7 +162,7 @@ LL | None, = note: the matched value is of type `Opt` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Opt::Some(ref _x) => {} +LL ~ Opt::Some(ref _x) => {}, LL + Opt::None => todo!() | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr index 44f327421109..98e417a17f86 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr @@ -25,7 +25,7 @@ LL | enum T { A(U), B } = note: the matched value is of type `T` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ T::B => { panic!("goodbye"); } +LL ~ T::B => { panic!("goodbye"); }, LL + T::A(U::C) => todo!() | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr index e2260f50bfef..e59e8885e1a4 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -24,7 +24,7 @@ LL | match true { = note: the matched value is of type `bool` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ true => {} +LL ~ true => {}, LL + false => todo!() | @@ -42,7 +42,7 @@ note: `Option` defined here = note: the matched value is of type `Option` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ None => {} +LL ~ None => {}, LL + Some(_) => todo!() | @@ -55,7 +55,7 @@ LL | match (2, 3, 4) { = note: the matched value is of type `(i32, i32, i32)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ (_, _, 4) => {} +LL ~ (_, _, 4) => {}, LL + (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!() | @@ -68,7 +68,7 @@ LL | match (T::A, T::A) { = note: the matched value is of type `(T, T)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ (T::B, T::A) => {} +LL ~ (T::B, T::A) => {}, LL + (T::A, T::A) | (T::B, T::B) => todo!() | @@ -86,7 +86,7 @@ LL | enum T { A, B } = note: the matched value is of type `T` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ T::A => {} +LL ~ T::A => {}, LL + T::B => todo!() | @@ -99,7 +99,7 @@ LL | match *vec { = note: the matched value is of type `[Option]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [None] => {} +LL ~ [None] => {}, LL + [] => todo!() | diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr index c518de47740d..beb51a4d4504 100644 --- a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr +++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr @@ -17,8 +17,8 @@ LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); = note: the matched value is of type `(i32, (Option, i32))` help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() } - | ++ ~~~~~~~~~~~ +LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() }; + | ++ +++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr index 5d1e170ae6c2..fb6ecda3c4df 100644 --- a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr +++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr @@ -7,7 +7,7 @@ LL | match s2 { = note: the matched value is of type `&[bool; 2]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [true, .., true] => {} +LL ~ [true, .., true] => {}, LL + &[false, _] => todo!() | @@ -20,7 +20,7 @@ LL | match s3 { = note: the matched value is of type `&[bool; 3]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [true, .., true] => {} +LL ~ [true, .., true] => {}, LL + &[false, ..] => todo!() | @@ -33,7 +33,7 @@ LL | match s10 { = note: the matched value is of type `&[bool; 10]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [true, .., true] => {} +LL ~ [true, .., true] => {}, LL + &[false, ..] => todo!() | @@ -46,7 +46,7 @@ LL | match s2 { = note: the matched value is of type `&[bool; 2]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [.., false] => {} +LL ~ [.., false] => {}, LL + &[false, true] => todo!() | @@ -59,7 +59,7 @@ LL | match s3 { = note: the matched value is of type `&[bool; 3]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [.., false] => {} +LL ~ [.., false] => {}, LL + &[false, .., true] => todo!() | @@ -72,7 +72,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [.., false] => {} +LL ~ [.., false] => {}, LL + &[false, .., true] => todo!() | @@ -85,7 +85,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [] => {} +LL ~ [] => {}, LL + &[_, ..] => todo!() | @@ -98,7 +98,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [_] => {} +LL ~ [_] => {}, LL + &[_, _, ..] => todo!() | @@ -111,7 +111,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [true, ..] => {} +LL ~ [true, ..] => {}, LL + &[false, ..] => todo!() | @@ -124,7 +124,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [true, ..] => {} +LL ~ [true, ..] => {}, LL + &[false, _, ..] => todo!() | @@ -137,7 +137,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [.., true] => {} +LL ~ [.., true] => {}, LL + &[_, .., false] => todo!() | @@ -150,7 +150,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [.., false] => {} +LL ~ [.., false] => {}, LL + &[_, _, .., true] => todo!() | @@ -163,7 +163,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [false, .., false] => {} +LL ~ [false, .., false] => {}, LL + &[true, _, .., _] => todo!() | @@ -176,7 +176,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ &[true] => {} +LL ~ &[true] => {}, LL + &[] | &[_, _, ..] => todo!() | @@ -189,7 +189,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ CONST => {} +LL ~ CONST => {}, LL + &[] | &[_, _, ..] => todo!() | @@ -202,7 +202,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ &[false] => {} +LL ~ &[false] => {}, LL + &[] | &[_, _, ..] => todo!() | @@ -215,7 +215,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ CONST => {} +LL ~ CONST => {}, LL + &[] | &[_, _, ..] => todo!() | @@ -228,7 +228,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ CONST => {} +LL ~ CONST => {}, LL + &[_, _, ..] => todo!() | @@ -241,7 +241,7 @@ LL | match s { = note: the matched value is of type `&[bool]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ &[_, _, ..] => {} +LL ~ &[_, _, ..] => {}, LL + &[false] => todo!() | @@ -254,7 +254,7 @@ LL | match s1 { = note: the matched value is of type `&[bool; 1]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ CONST1 => {} +LL ~ CONST1 => {}, LL + &[false] => todo!() | diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr index 7b8588a3c735..f944c25a905c 100644 --- a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr +++ b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -15,7 +15,7 @@ LL | Stable2, = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ UnstableEnum::Stable => {} +LL ~ UnstableEnum::Stable => {}, LL + UnstableEnum::Stable2 | _ => todo!() | @@ -33,7 +33,7 @@ LL | pub enum UnstableEnum { = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ UnstableEnum::Stable2 => {} +LL ~ UnstableEnum::Stable2 => {}, LL + _ => todo!() | diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr index 85c97be29d6d..22425aa0dd4d 100644 --- a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr +++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr @@ -14,7 +14,7 @@ LL | B { x: Option }, = note: the matched value is of type `A` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ A::B { x: None } => {} +LL ~ A::B { x: None } => {}, LL + A::B { x: Some(_) } => todo!() | diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr index 6dc9a4058398..d776249b2318 100644 --- a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr +++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -15,7 +15,7 @@ LL | Unstable, = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ UnstableEnum::Stable2 => {} +LL ~ UnstableEnum::Stable2 => {}, LL + UnstableEnum::Unstable => todo!() | diff --git a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs index d02caff1febd..206f05d0d3ca 100644 --- a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs +++ b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs @@ -4,10 +4,8 @@ fn main() { match 0u8 { 251..257 => {} //~^ ERROR literal out of range - //~| ERROR literal out of range 251..=256 => {} //~^ ERROR literal out of range - //~| ERROR literal out of range _ => {} } } diff --git a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr index 7b8309b9bc2a..4f3f9d1eb3a7 100644 --- a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr +++ b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr @@ -5,22 +5,10 @@ LL | 251..257 => {} | ^^^ this value doesn't fit in `u8` whose maximum value is `255` error: literal out of range for `u8` - --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:8:15 + --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:7:15 | LL | 251..=256 => {} | ^^^ this value doesn't fit in `u8` whose maximum value is `255` -error: literal out of range for `u8` - --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:5:14 - | -LL | 251..257 => {} - | ^^^ this value doesn't fit in `u8` whose maximum value is `255` - -error: literal out of range for `u8` - --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:8:15 - | -LL | 251..=256 => {} - | ^^^ this value doesn't fit in `u8` whose maximum value is `255` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/rfc-2005-default-binding-mode/slice.stderr b/tests/ui/rfc-2005-default-binding-mode/slice.stderr index 60c1f5420f62..5b51dc5acc4e 100644 --- a/tests/ui/rfc-2005-default-binding-mode/slice.stderr +++ b/tests/ui/rfc-2005-default-binding-mode/slice.stderr @@ -7,7 +7,7 @@ LL | match sl { = note: the matched value is of type `&[u8]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ [first, remainder @ ..] => {} +LL ~ [first, remainder @ ..] => {}, LL ~ &[] => todo!(), | diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs index 15f08486f0f0..0b7eb3ee605b 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs @@ -2,10 +2,7 @@ fn main() { let A = 3; //~^ ERROR refutable pattern in local binding //~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered - //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable - //~| HELP introduce a variable instead - //~| SUGGESTION a_var + //~| HELP you might want to use `if let` to ignore the variants that aren't matched const A: i32 = 2; - //~^ constant defined here } diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr index 1c1cab25fbfa..b112e3a11757 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr @@ -2,16 +2,15 @@ error[E0005]: refutable pattern in local binding --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9 | LL | let A = 3; - | ^ - | | - | patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered - | missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `a_var` -... -LL | const A: i32 = 2; - | ------------ constant defined here + | ^ patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let A = 3 { todo!() }; + | ++ +++++++++++ error: aborting due to previous error From 4240a0bed0943cd3fa003e7951d91ab8a37ff8e3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 26 Feb 2023 20:42:46 +0000 Subject: [PATCH 057/267] Cleanup PatCtxt. --- .../src/thir/pattern/const_to_pat.rs | 33 ++++------ .../rustc_mir_build/src/thir/pattern/mod.rs | 63 ++++--------------- 2 files changed, 23 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 2dbef740d1a6..32d0404bd073 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -59,8 +59,6 @@ struct ConstToPat<'tcx> { // inference context used for checking `T: Structural` bounds. infcx: InferCtxt<'tcx>, - include_lint_checks: bool, - treat_byte_string_as_slice: bool, } @@ -93,7 +91,6 @@ impl<'tcx> ConstToPat<'tcx> { span, infcx, param_env: pat_ctxt.param_env, - include_lint_checks: pat_ctxt.include_lint_checks, saw_const_match_error: Cell::new(false), saw_const_match_lint: Cell::new(false), behind_reference: Cell::new(false), @@ -134,7 +131,7 @@ impl<'tcx> ConstToPat<'tcx> { }) }); - if self.include_lint_checks && !self.saw_const_match_error.get() { + if !self.saw_const_match_error.get() { // If we were able to successfully convert the const to some pat, // double-check that all types in the const implement `Structural`. @@ -239,21 +236,19 @@ impl<'tcx> ConstToPat<'tcx> { let kind = match cv.ty().kind() { ty::Float(_) => { - if self.include_lint_checks { tcx.emit_spanned_lint( lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, id, span, FloatPattern, ); - } PatKind::Constant { value: cv } } ty::Adt(adt_def, _) if adt_def.is_union() => { // Matching on union fields is unsafe, we can't hide it in constants self.saw_const_match_error.set(true); let err = UnionPattern { span }; - tcx.sess.create_err(err).emit_unless(!self.include_lint_checks); + tcx.sess.emit_err(err); PatKind::Wild } ty::Adt(..) @@ -267,7 +262,7 @@ impl<'tcx> ConstToPat<'tcx> { { self.saw_const_match_error.set(true); let err = TypeNotStructural { span, non_sm_ty }; - tcx.sess.create_err(err).emit_unless(!self.include_lint_checks); + tcx.sess.emit_err(err); PatKind::Wild } // If the type is not structurally comparable, just emit the constant directly, @@ -280,8 +275,7 @@ impl<'tcx> ConstToPat<'tcx> { // Backwards compatibility hack because we can't cause hard errors on these // types, so we compare them via `PartialEq::eq` at runtime. ty::Adt(..) if !self.type_marked_structural(cv.ty()) && self.behind_reference.get() => { - if self.include_lint_checks - && !self.saw_const_match_error.get() + if !self.saw_const_match_error.get() && !self.saw_const_match_lint.get() { self.saw_const_match_lint.set(true); @@ -305,7 +299,7 @@ impl<'tcx> ConstToPat<'tcx> { ); self.saw_const_match_error.set(true); let err = TypeNotStructural { span, non_sm_ty: cv.ty() }; - tcx.sess.create_err(err).emit_unless(!self.include_lint_checks); + tcx.sess.emit_err(err); PatKind::Wild } ty::Adt(adt_def, substs) if adt_def.is_enum() => { @@ -339,7 +333,7 @@ impl<'tcx> ConstToPat<'tcx> { ty::Dynamic(..) => { self.saw_const_match_error.set(true); let err = InvalidPattern { span, non_sm_ty: cv.ty() }; - tcx.sess.create_err(err).emit_unless(!self.include_lint_checks); + tcx.sess.emit_err(err); PatKind::Wild } // `&str` is represented as `ConstValue::Slice`, let's keep using this @@ -406,8 +400,7 @@ impl<'tcx> ConstToPat<'tcx> { // to figure out how to get a reference again. ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => { if self.behind_reference.get() { - if self.include_lint_checks - && !self.saw_const_match_error.get() + if !self.saw_const_match_error.get() && !self.saw_const_match_lint.get() { self.saw_const_match_lint.set(true); @@ -423,7 +416,7 @@ impl<'tcx> ConstToPat<'tcx> { if !self.saw_const_match_error.get() { self.saw_const_match_error.set(true); let err = TypeNotStructural { span, non_sm_ty: *pointee_ty }; - tcx.sess.create_err(err).emit_unless(!self.include_lint_checks); + tcx.sess.emit_err(err); } PatKind::Wild } @@ -437,7 +430,7 @@ impl<'tcx> ConstToPat<'tcx> { // (except slices, which are handled in a separate arm above). let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; - tcx.sess.create_err(err).emit_unless(!self.include_lint_checks); + tcx.sess.emit_err(err); PatKind::Wild } else { @@ -465,8 +458,7 @@ impl<'tcx> ConstToPat<'tcx> { // compilation choices change the runtime behaviour of the match. // See https://github.com/rust-lang/rust/issues/70861 for examples. ty::FnPtr(..) | ty::RawPtr(..) => { - if self.include_lint_checks - && !self.saw_const_match_error.get() + if !self.saw_const_match_error.get() && !self.saw_const_match_lint.get() { self.saw_const_match_lint.set(true); @@ -482,13 +474,12 @@ impl<'tcx> ConstToPat<'tcx> { _ => { self.saw_const_match_error.set(true); let err = InvalidPattern { span, non_sm_ty: cv.ty() }; - tcx.sess.create_err(err).emit_unless(!self.include_lint_checks); + tcx.sess.emit_err(err); PatKind::Wild } }; - if self.include_lint_checks - && !self.saw_const_match_error.get() + if !self.saw_const_match_error.get() && !self.saw_const_match_lint.get() && mir_structural_match_violation // FIXME(#73448): Find a way to bring const qualification into parity with diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 6e201b771ec6..70d015a39e4e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -31,20 +31,10 @@ use rustc_target::abi::FieldIdx; use std::cmp::Ordering; -#[derive(Clone, Debug)] -enum PatternError { - AssocConstInPattern(Span), - ConstParamInPattern(Span), - StaticInPattern(Span), - NonConstPath(Span), -} - struct PatCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, - errors: Vec, - include_lint_checks: bool, } pub(super) fn pat_from_hir<'a, 'tcx>( @@ -53,47 +43,13 @@ pub(super) fn pat_from_hir<'a, 'tcx>( typeck_results: &'a ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, ) -> Box> { - let mut pcx = PatCtxt::new(tcx, param_env, typeck_results); - pcx.include_lint_checks(); + let mut pcx = PatCtxt { tcx, param_env, typeck_results }; let result = pcx.lower_pattern(pat); - pcx.report_inlining_errors(); debug!("pat_from_hir({:?}) = {:?}", pat, result); result } impl<'a, 'tcx> PatCtxt<'a, 'tcx> { - fn new( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - typeck_results: &'a ty::TypeckResults<'tcx>, - ) -> Self { - PatCtxt { tcx, param_env, typeck_results, errors: vec![], include_lint_checks: false } - } - - fn include_lint_checks(&mut self) -> &mut Self { - self.include_lint_checks = true; - self - } - - fn report_inlining_errors(&self) { - for error in &self.errors { - match *error { - PatternError::StaticInPattern(span) => { - self.tcx.sess.emit_err(StaticInPattern { span }); - } - PatternError::AssocConstInPattern(span) => { - self.tcx.sess.emit_err(AssocConstInPattern { span }); - } - PatternError::ConstParamInPattern(span) => { - self.tcx.sess.emit_err(ConstParamInPattern { span }); - } - PatternError::NonConstPath(span) => { - self.tcx.sess.emit_err(NonConstPath { span }); - } - } - } - } - fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { // When implicit dereferences have been inserted in this pattern, the unadjusted lowered // pattern has the type that results *after* dereferencing. For example, in this code: @@ -490,12 +446,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { | Res::SelfTyAlias { .. } | Res::SelfCtor(..) => PatKind::Leaf { subpatterns }, _ => { - let pattern_error = match res { - Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span), - Res::Def(DefKind::Static(_), _) => PatternError::StaticInPattern(span), - _ => PatternError::NonConstPath(span), + match res { + Res::Def(DefKind::ConstParam, _) => { + self.tcx.sess.emit_err(ConstParamInPattern { span }) + } + Res::Def(DefKind::Static(_), _) => { + self.tcx.sess.emit_err(StaticInPattern { span }) + } + _ => self.tcx.sess.emit_err(NonConstPath { span }), }; - self.errors.push(pattern_error); PatKind::Wild } }; @@ -548,7 +507,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // It should be assoc consts if there's no error but we cannot resolve it. debug_assert!(is_associated_const); - self.errors.push(PatternError::AssocConstInPattern(span)); + self.tcx.sess.emit_err(AssocConstInPattern { span }); return pat_from_kind(PatKind::Wild); } @@ -626,7 +585,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { match value { mir::ConstantKind::Ty(c) => match c.kind() { ConstKind::Param(_) => { - self.errors.push(PatternError::ConstParamInPattern(span)); + self.tcx.sess.emit_err(ConstParamInPattern { span }); return PatKind::Wild; } ConstKind::Error(_) => { From 5d8161c570ac1d6298ee2d0a78c527d120ab9f02 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 27 Feb 2023 18:12:16 +0000 Subject: [PATCH 058/267] Hide warning. --- compiler/rustc_middle/src/dep_graph/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 84510fe218cf..0ddbe7d1c292 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -94,7 +94,7 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { } #[inline] - fn dep_kind_info(&self, dep_kind: DepKind) -> &DepKindStruct<'tcx> { - &self.query_kinds[dep_kind as usize] + fn dep_kind_info(&self, dk: DepKind) -> &DepKindStruct<'tcx> { + &self.query_kinds[dk as usize] } } From 4d8ed585f2ba5ce3f5a1208dc19c9b07ba0b0cee Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 27 Feb 2023 19:09:13 +0000 Subject: [PATCH 059/267] Bless mir-opt. --- ...ic.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir | 6 +++--- .../const_promotion_extern_static.FOO.PromoteTemps.diff | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 41657b53fc12..19daae86589c 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -7,10 +7,10 @@ promoted[0] in FOO: &[&i32; 1] = { let mut _3: *const i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 bb0: { - _3 = const {alloc3: *const i32}; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 + _3 = const {alloc2: *const i32}; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 // mir::Constant // + span: $DIR/const_promotion_extern_static.rs:13:42: 13:43 - // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) } + // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) } _2 = &(*_3); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:41: +0:43 _1 = [move _2]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 _0 = &_1; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 @@ -18,4 +18,4 @@ promoted[0] in FOO: &[&i32; 1] = { } } -alloc3 (extern static: X) +alloc2 (extern static: X) diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index 25ba0face6bd..5b13d60052fe 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -18,11 +18,11 @@ - StorageLive(_3); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 - StorageLive(_4); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:45 - StorageLive(_5); // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 -- _5 = const {alloc3: *const i32}; // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 +- _5 = const {alloc2: *const i32}; // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43 + _6 = const _; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 // mir::Constant - // + span: $DIR/const_promotion_extern_static.rs:13:42: 13:43 -- // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) } +- // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) } - _4 = &(*_5); // scope 1 at $DIR/const_promotion_extern_static.rs:+0:41: +0:43 - _3 = [move _4]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 - _2 = &_3; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 @@ -50,5 +50,5 @@ } } - -- alloc3 (extern static: X) +- alloc2 (extern static: X) From 4f97540432445c7e0dc4eb51e3ac5fd915d225ad Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 27 Feb 2023 20:50:01 +0000 Subject: [PATCH 060/267] Reinstate confusion note. --- compiler/rustc_mir_build/messages.ftl | 4 +- compiler/rustc_mir_build/src/errors.rs | 13 ------ .../src/thir/pattern/check_match.rs | 46 +++++++++++-------- tests/ui/consts/const-pattern-irrefutable.rs | 9 ++-- .../consts/const-pattern-irrefutable.stderr | 34 +++++++------- .../refutable-pattern-in-fn-arg.stderr | 4 ++ .../const-pat-non-exaustive-let-new-var.rs | 4 +- ...const-pat-non-exaustive-let-new-var.stderr | 10 ++-- 8 files changed, 63 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index c8172219267f..f346cd483470 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -347,15 +347,13 @@ mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -mir_build_res_defined_here = {$res} defined here - mir_build_adt_defined_here = `{$ty}` defined here mir_build_variant_defined_here = not covered mir_build_interpreted_as_const = introduce a variable instead -mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as {$article} {$res} pattern, not a new variable +mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count -> [one] variant that isn't diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index c67a002dce1d..6a05f35bdf33 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -6,7 +6,6 @@ use rustc_errors::{ error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, SubdiagnosticMessage, }; -use rustc_hir::def::Res; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::thir::Pat; use rustc_middle::ty::{self, Ty}; @@ -795,8 +794,6 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> { pub let_suggestion: Option, #[subdiagnostic] pub misc_suggestion: Option, - #[subdiagnostic] - pub res_defined_here: Option, } #[derive(Subdiagnostic)] @@ -830,14 +827,6 @@ impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> { } } -#[derive(Subdiagnostic)] -#[label(mir_build_res_defined_here)] -pub struct ResDefinedHere { - #[primary_span] - pub def_span: Span, - pub res: Res, -} - #[derive(Subdiagnostic)] #[suggestion( mir_build_interpreted_as_const, @@ -848,9 +837,7 @@ pub struct ResDefinedHere { pub struct InterpretedAsConst { #[primary_span] pub span: Span, - pub article: &'static str, pub variable: String, - pub res: Res, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index b1f85f039893..4fb8e915220a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -424,29 +424,38 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let inform = sp.is_some().then_some(Inform); let mut let_suggestion = None; let mut misc_suggestion = None; - if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) { - let mut bindings= vec![]; - pat.each_binding(|name, _, _, _| { - bindings.push(name); - }); + let mut interpreted_as_const = None; + if let PatKind::Constant { .. } = pat.kind + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) + { + // If the pattern to match is an integer literal: + if snippet.chars().all(|c| c.is_digit(10)) { + // Then give a suggestion, the user might've meant to create a binding instead. + misc_suggestion = Some(MiscPatternSuggestion::AttemptedIntegerLiteral { + start_span: pat.span.shrink_to_lo() + }); + } else if snippet.chars().all(|c| c.is_alphanumeric() || c == '_') { + interpreted_as_const = Some(InterpretedAsConst { + span: pat.span, + variable: snippet, + }); + } + } + + if let Some(span) = sp + && self.tcx.sess.source_map().is_span_accessible(span) + && interpreted_as_const.is_none() + { + let mut bindings = vec![]; + pat.each_binding(|name, _, _, _| bindings.push(name)); + let semi_span = span.shrink_to_hi(); let start_span = span.shrink_to_lo(); let end_span = semi_span.shrink_to_lo(); let count = witnesses.len(); - // If the pattern to match is an integer literal: - if bindings.is_empty() - && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) - && snippet.chars().all(|c| c.is_digit(10)) - { - // Then give a suggestion, the user might've meant to create a binding instead. - misc_suggestion = Some(MiscPatternSuggestion::AttemptedIntegerLiteral { - start_span: pat.span.shrink_to_lo() - }); - } - let_suggestion = Some(if bindings.is_empty() { - SuggestLet::If {start_span, semi_span, count } + SuggestLet::If { start_span, semi_span, count } } else { SuggestLet::Else { end_span, count } }); @@ -469,12 +478,11 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { origin, uncovered: Uncovered::new(pat.span, &cx, witnesses), inform, - interpreted_as_const: None, + interpreted_as_const, _p: (), pattern_ty, let_suggestion, misc_suggestion, - res_defined_here: None, adt_defined_here, }); } diff --git a/tests/ui/consts/const-pattern-irrefutable.rs b/tests/ui/consts/const-pattern-irrefutable.rs index d7d8e7328397..61bdf57ffdb9 100644 --- a/tests/ui/consts/const-pattern-irrefutable.rs +++ b/tests/ui/consts/const-pattern-irrefutable.rs @@ -12,14 +12,17 @@ fn main() { let a = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| HELP you might want to use `if let` to ignore the variants that aren't matched + //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead let c = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| HELP you might want to use `if let` to ignore the variants that aren't matched + //~| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead let d = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| HELP you might want to use `if let` to ignore the variants that aren't matched + //~| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115). } diff --git a/tests/ui/consts/const-pattern-irrefutable.stderr b/tests/ui/consts/const-pattern-irrefutable.stderr index 956a97a476c1..2aed68bdd643 100644 --- a/tests/ui/consts/const-pattern-irrefutable.stderr +++ b/tests/ui/consts/const-pattern-irrefutable.stderr @@ -2,43 +2,43 @@ error[E0005]: refutable pattern in local binding --> $DIR/const-pattern-irrefutable.rs:12:9 | LL | let a = 4; - | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | ^ + | | + | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `a_var` | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u8` -help: you might want to use `if let` to ignore the variants that aren't matched - | -LL | if let a = 4 { todo!() }; - | ++ +++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:16:9 + --> $DIR/const-pattern-irrefutable.rs:17:9 | LL | let c = 4; - | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | ^ + | | + | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `c_var` | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u8` -help: you might want to use `if let` to ignore the variants that aren't matched - | -LL | if let c = 4 { todo!() }; - | ++ +++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:20:9 + --> $DIR/const-pattern-irrefutable.rs:22:9 | LL | let d = 4; - | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | ^ + | | + | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `d_var` | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u8` -help: you might want to use `if let` to ignore the variants that aren't matched - | -LL | if let d = 4 { todo!() }; - | ++ +++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr index 55f0b2319fb7..ab3f6f69fb16 100644 --- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr +++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr @@ -5,6 +5,10 @@ LL | let f = |3: isize| println!("hello"); | ^ pattern `_` not covered | = note: the matched value is of type `isize` +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | let f = |_3: isize| println!("hello"); + | + error: aborting due to previous error diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs index 0b7eb3ee605b..af47ba8baa3f 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs @@ -2,7 +2,9 @@ fn main() { let A = 3; //~^ ERROR refutable pattern in local binding //~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered - //~| HELP you might want to use `if let` to ignore the variants that aren't matched + //~| missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead + //~| SUGGESTION A_var const A: i32 = 2; } diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr index b112e3a11757..9ee3e6eb2c82 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr @@ -2,15 +2,15 @@ error[E0005]: refutable pattern in local binding --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9 | LL | let A = 3; - | ^ patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered + | ^ + | | + | patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered + | missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `A_var` | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` -help: you might want to use `if let` to ignore the variants that aren't matched - | -LL | if let A = 3 { todo!() }; - | ++ +++++++++++ error: aborting due to previous error From e73aeeaeeee456b58f3d45041d4169318c2b7130 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 1 Mar 2023 21:40:56 +0000 Subject: [PATCH 061/267] Remove redundant field. --- compiler/rustc_mir_build/src/errors.rs | 1 - .../rustc_mir_build/src/thir/pattern/check_match.rs | 13 ++++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 6a05f35bdf33..431c3255ab2a 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -576,7 +576,6 @@ pub struct IrrefutableLetPatternsWhileLet { #[diag(mir_build_borrow_of_moved_value)] pub struct BorrowOfMovedValue<'tcx> { #[primary_span] - pub span: Span, #[label] #[label(mir_build_occurs_because_label)] pub binding_span: Span, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 4fb8e915220a..534d236030b5 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -900,7 +900,6 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) { // Extract `sub` in `binding @ sub`. let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { return }; - let binding_span = pat.span; //.with_hi(name.span.hi()); let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); @@ -917,15 +916,11 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, }); if !conflicts_ref.is_empty() { sess.emit_err(BorrowOfMovedValue { - span: pat.span, - binding_span, + binding_span: pat.span, conflicts_ref, name, ty, - suggest_borrowing: pat - .span - .contains(binding_span) - .then(|| binding_span.shrink_to_lo()), + suggest_borrowing: Some(pat.span.shrink_to_lo()), }); } return; @@ -967,8 +962,8 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, let report_move_conflict = !conflicts_move.is_empty(); let mut occurences = match mut_outer { - Mutability::Mut => vec![Conflict::Mut { span: binding_span, name }], - Mutability::Not => vec![Conflict::Ref { span: binding_span, name }], + Mutability::Mut => vec![Conflict::Mut { span: pat.span, name }], + Mutability::Not => vec![Conflict::Ref { span: pat.span, name }], }; occurences.extend(conflicts_mut_mut); occurences.extend(conflicts_mut_ref); From 03fbb3db1e3dd767caebe176a368e0e52aeb68cb Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 1 Mar 2023 21:43:39 +0000 Subject: [PATCH 062/267] Expand parameters. --- .../src/thir/pattern/check_match.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 534d236030b5..de63e07b7d57 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -144,8 +144,8 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { ExprKind::Let { box ref pat, expr } => { self.check_let(pat, expr, self.let_source, ex.span); } - ExprKind::LogicalOp { op: LogicalOp::And, .. } => { - self.check_let_chain(ex, self.let_source); + ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => { + self.check_let_chain(self.let_source, ex.span, lhs, rhs); } _ => {} }; @@ -296,13 +296,17 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } #[instrument(level = "trace", skip(self))] - fn check_let_chain(&mut self, top_expr: &Expr<'tcx>, let_source: LetSource) { + fn check_let_chain( + &mut self, + let_source: LetSource, + top_expr_span: Span, + mut lhs: ExprId, + rhs: ExprId, + ) { if let LetSource::None = let_source { return; } - let ExprKind::LogicalOp { op: LogicalOp::And, mut lhs, rhs } = top_expr.kind else { bug!() }; - // Lint level enclosing the next `lhs`. let mut cur_lint_level = self.lint_level; @@ -367,7 +371,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { self.lint_level, let_source, chain_refutabilities.len(), - top_expr.span, + top_expr_span, ); return; } From 03a6ef67fe72c58d976c3e83ffab2296179ae8a4 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 3 Apr 2023 16:13:06 +0000 Subject: [PATCH 063/267] Only emit lint on refutable patterns. --- .../rustc_mir_build/src/thir/pattern/check_match.rs | 11 ++++++----- .../rustc_mir_build/src/thir/pattern/usefulness.rs | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index de63e07b7d57..0882b473f108 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -199,12 +199,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern)) } - fn new_cx(&self, hir_id: HirId) -> MatchCheckCtxt<'p, 'tcx> { + fn new_cx(&self, hir_id: HirId, refutable: bool) -> MatchCheckCtxt<'p, 'tcx> { MatchCheckCtxt { tcx: self.tcx, param_env: self.param_env, module: self.tcx.parent_module(hir_id).to_def_id(), pattern_arena: &self.pattern_arena, + refutable, } } @@ -214,7 +215,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { return; } self.check_patterns(pat, Refutable); - let mut cx = self.new_cx(self.lint_level); + let mut cx = self.new_cx(self.lint_level, true); let tpat = self.lower_pattern(&mut cx, pat); self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span); } @@ -226,7 +227,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { source: hir::MatchSource, expr_span: Span, ) { - let mut cx = self.new_cx(self.lint_level); + let mut cx = self.new_cx(self.lint_level, true); for &arm in arms { // Check the arm for some things unrelated to exhaustiveness. @@ -328,7 +329,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { debug!(?expr, ?local_lint_level, "after scopes"); match expr.kind { ExprKind::Let { box ref pat, expr: _ } => { - let mut ncx = self.new_cx(local_lint_level); + let mut ncx = self.new_cx(local_lint_level, true); let tpat = self.lower_pattern(&mut ncx, pat); let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat); Some((expr.span, refutable)) @@ -409,7 +410,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { #[instrument(level = "trace", skip(self))] fn check_irrefutable(&self, pat: &Pat<'tcx>, origin: &str, sp: Option) { - let mut cx = self.new_cx(self.lint_level); + let mut cx = self.new_cx(self.lint_level, false); let pattern = self.lower_pattern(&mut cx, pat); let pattern_ty = pattern.ty(); diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 9edd7967e7a4..8c89bcb8cec8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -300,7 +300,6 @@ use rustc_arena::TypedArena; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_hir::HirId; -use rustc_hir::Node; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::{Span, DUMMY_SP}; @@ -319,6 +318,8 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> { pub(crate) module: DefId, pub(crate) param_env: ty::ParamEnv<'tcx>, pub(crate) pattern_arena: &'p TypedArena>, + /// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns. + pub(crate) refutable: bool, } impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { @@ -860,6 +861,8 @@ fn is_useful<'p, 'tcx>( // that has the potential to trigger the `non_exhaustive_omitted_patterns` lint. // To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors` if is_non_exhaustive_and_wild + // Only emit a lint on refutable patterns. + && cx.refutable // We check that the match has a wildcard pattern and that wildcard is useful, // meaning there are variants that are covered by the wildcard. Without the check // for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}` @@ -868,8 +871,6 @@ fn is_useful<'p, 'tcx>( &ctor, Constructor::Missing { nonexhaustive_enum_missing_real_variants: true } ) - // We don't want to lint patterns which are function arguments or locals - && !matches!(cx.tcx.hir().find_parent(hir_id), Some(Node::Param(_)|Node::Local(_))) { let patterns = { let mut split_wildcard = SplitWildcard::new(pcx); From a8187f8cb136eb5d27f00ec68ef3f7e213f8154d Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 3 Apr 2023 16:13:24 +0000 Subject: [PATCH 064/267] Rename hir_id to lint_root. --- .../src/thir/pattern/deconstruct_pat.rs | 4 ++-- .../src/thir/pattern/usefulness.rs | 24 ++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index e619e095496b..54bcb2d62c4b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -258,7 +258,7 @@ impl IntRange { pcx: &PatCtxt<'_, 'p, 'tcx>, pats: impl Iterator>, column_count: usize, - hir_id: HirId, + lint_root: HirId, ) { if self.is_singleton() { return; @@ -290,7 +290,7 @@ impl IntRange { if !overlap.is_empty() { pcx.cx.tcx.emit_spanned_lint( lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, - hir_id, + lint_root, pcx.span, OverlappingRangeEndpoints { overlap, range: pcx.span }, ); diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 8c89bcb8cec8..7b06498919d3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -766,13 +766,13 @@ impl<'p, 'tcx> Witness<'p, 'tcx> { /// `is_under_guard` is used to inform if the pattern has a guard. If it /// has one it must not be inserted into the matrix. This shouldn't be /// relied on for soundness. -#[instrument(level = "debug", skip(cx, matrix, hir_id), ret)] +#[instrument(level = "debug", skip(cx, matrix, lint_root), ret)] fn is_useful<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, matrix: &Matrix<'p, 'tcx>, v: &PatStack<'p, 'tcx>, witness_preference: ArmType, - hir_id: HirId, + lint_root: HirId, is_under_guard: bool, is_top_level: bool, ) -> Usefulness<'p, 'tcx> { @@ -805,7 +805,7 @@ fn is_useful<'p, 'tcx>( for v in v.expand_or_pat() { debug!(?v); let usefulness = ensure_sufficient_stack(|| { - is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false) + is_useful(cx, &matrix, &v, witness_preference, lint_root, is_under_guard, false) }); debug!(?usefulness); ret.extend(usefulness); @@ -838,7 +838,7 @@ fn is_useful<'p, 'tcx>( pcx, matrix.heads(), matrix.column_count().unwrap_or(0), - hir_id, + lint_root, ) } // We split the head constructor of `v`. @@ -853,7 +853,15 @@ fn is_useful<'p, 'tcx>( let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor); let v = v.pop_head_constructor(pcx, &ctor); let usefulness = ensure_sufficient_stack(|| { - is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false) + is_useful( + cx, + &spec_matrix, + &v, + witness_preference, + lint_root, + is_under_guard, + false, + ) }); let usefulness = usefulness.apply_constructor(pcx, start_matrix, &ctor); @@ -897,7 +905,7 @@ fn is_useful<'p, 'tcx>( // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`. cx.tcx.emit_spanned_lint( NON_EXHAUSTIVE_OMITTED_PATTERNS, - hir_id, + lint_root, pcx.span, NonExhaustiveOmittedPattern { scrut_ty: pcx.ty, @@ -955,7 +963,7 @@ pub(crate) struct UsefulnessReport<'p, 'tcx> { pub(crate) fn compute_match_usefulness<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, arms: &[MatchArm<'p, 'tcx>], - scrut_hir_id: HirId, + lint_root: HirId, scrut_ty: Ty<'tcx>, ) -> UsefulnessReport<'p, 'tcx> { let mut matrix = Matrix::empty(); @@ -980,7 +988,7 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>( let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty)); let v = PatStack::from_pattern(wild_pattern); - let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, scrut_hir_id, false, true); + let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, lint_root, false, true); let non_exhaustiveness_witnesses = match usefulness { WithWitnesses(pats) => pats.into_iter().map(|w| w.single_pattern()).collect(), NoWitnesses { .. } => bug!(), From 1dde34b831089a7acbb14e47810b356bbe951301 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 3 Apr 2023 16:14:27 +0000 Subject: [PATCH 065/267] Bless ui test. --- tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr index 617c629a4fe0..4cdda732a916 100644 --- a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr +++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr @@ -188,7 +188,7 @@ error[E0005]: refutable pattern in local binding --> $DIR/omitted-patterns.rs:194:9 | LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `_` not covered + | ^^^^^^^^^^^^^^^ pattern `_` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html From a84909c1e78aef244385b46db080bf78ce548881 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 14 Jan 2023 22:23:49 +0000 Subject: [PATCH 066/267] Enforce VarDebugInfo::Place in MIR validation. --- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 14 +++--- .../src/transform/validate.rs | 43 +++++++++++++++++-- compiler/rustc_middle/src/mir/mod.rs | 24 ++++++++--- 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index d15774696a52..8549abd6e390 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -165,11 +165,15 @@ fn calculate_debuginfo_offset< mir::ProjectionElem::Downcast(_, variant) => { place = place.downcast(bx, variant); } - _ => span_bug!( - var.source_info.span, - "unsupported var debuginfo place `{:?}`", - mir::Place { local, projection: var.projection }, - ), + _ => { + // Sanity check for `can_use_in_debuginfo`. + debug_assert!(!elem.can_use_in_debuginfo()); + span_bug!( + var.source_info.span, + "unsupported var debuginfo place `{:?}`", + mir::Place { local, projection: var.projection }, + ) + } } } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 2be385d551e8..5d7c0faf8517 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -5,13 +5,12 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_infer::traits::Reveal; use rustc_middle::mir::interpret::Scalar; -use rustc_middle::mir::visit::NonUseContext::VarDebugInfo; -use rustc_middle::mir::visit::{PlaceContext, Visitor}; +use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{ traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator, - TerminatorKind, UnOp, START_BLOCK, + TerminatorKind, UnOp, VarDebugInfo, VarDebugInfoContents, START_BLOCK, }; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_mir_dataflow::impls::MaybeStorageLive; @@ -419,13 +418,49 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.super_projection_elem(local, proj_base, elem, context, location); } + fn visit_var_debug_info(&mut self, debuginfo: &VarDebugInfo<'tcx>) { + let check_place = |place: Place<'_>| { + if place.projection.iter().any(|p| !p.can_use_in_debuginfo()) { + self.fail( + START_BLOCK.start_location(), + format!("illegal place {:?} in debuginfo for {:?}", place, debuginfo.name), + ); + } + }; + match debuginfo.value { + VarDebugInfoContents::Const(_) => {} + VarDebugInfoContents::Place(place) => check_place(place), + VarDebugInfoContents::Composite { ty, ref fragments } => { + for f in fragments { + check_place(f.contents); + if ty.is_union() || ty.is_enum() { + self.fail( + START_BLOCK.start_location(), + format!("invalid type {:?} for composite debuginfo", ty), + ); + } + if f.projection.iter().any(|p| !matches!(p, PlaceElem::Field(..))) { + self.fail( + START_BLOCK.start_location(), + format!( + "illegal projection {:?} in debuginfo for {:?}", + f.projection, debuginfo.name + ), + ); + } + } + } + } + self.super_var_debug_info(debuginfo); + } + fn visit_place(&mut self, place: &Place<'tcx>, cntxt: PlaceContext, location: Location) { // Set off any `bug!`s in the type computation code let _ = place.ty(&self.body.local_decls, self.tcx); if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) && place.projection.len() > 1 - && cntxt != PlaceContext::NonUse(VarDebugInfo) + && cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo) && place.projection[1..].contains(&ProjectionElem::Deref) { self.fail(location, format!("{:?}, has deref at the wrong place", place)); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9c575f6eb9fd..9604fb5743d3 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1029,8 +1029,7 @@ impl<'tcx> LocalDecl<'tcx> { #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum VarDebugInfoContents<'tcx> { - /// NOTE(eddyb) There's an unenforced invariant that this `Place` is - /// based on a `Local`, not a `Static`, and contains no indexing. + /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`. Place(Place<'tcx>), Const(Constant<'tcx>), /// The user variable's data is split across several fragments, @@ -1040,6 +1039,7 @@ pub enum VarDebugInfoContents<'tcx> { /// the underlying debuginfo feature this relies on. Composite { /// Type of the original user variable. + /// This cannot contain a union or an enum. ty: Ty<'tcx>, /// All the parts of the original user variable, which ended /// up in disjoint places, due to optimizations. @@ -1068,17 +1068,16 @@ pub struct VarDebugInfoFragment<'tcx> { /// Where in the composite user variable this fragment is, /// represented as a "projection" into the composite variable. /// At lower levels, this corresponds to a byte/bit range. - // NOTE(eddyb) there's an unenforced invariant that this contains - // only `Field`s, and not into `enum` variants or `union`s. - // FIXME(eddyb) support this for `enum`s by either using DWARF's + /// + /// This can only contain `PlaceElem::Field`. + // FIXME support this for `enum`s by either using DWARF's // more advanced control-flow features (unsupported by LLVM?) // to match on the discriminant, or by using custom type debuginfo // with non-overlapping variants for the composite variable. pub projection: Vec>, /// Where the data for this fragment can be found. - // NOTE(eddyb) There's an unenforced invariant that this `Place` is - // contains no indexing (with a non-constant index). + /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`. pub contents: Place<'tcx>, } @@ -1515,6 +1514,17 @@ impl ProjectionElem { pub fn is_field_to(&self, f: Field) -> bool { matches!(*self, Self::Field(x, _) if x == f) } + + /// Returns `true` if this is accepted inside `VarDebugInfoContents::Place`. + pub fn can_use_in_debuginfo(&self) -> bool { + match self { + Self::Deref | Self::Downcast(_, _) | Self::Field(_, _) => true, + Self::ConstantIndex { .. } + | Self::Index(_) + | Self::OpaqueCast(_) + | Self::Subslice { .. } => false, + } + } } /// Alias for projections as they appear in `UserTypeProjection`, where we From ab0b9356e6e018b2d2f76a26402a7c337c03bad3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 3 Apr 2023 21:20:48 +0000 Subject: [PATCH 067/267] Emit feature error for parenthesized generics in associated type bounds --- compiler/rustc_ast_passes/src/feature_gate.rs | 11 ++------ .../bad-inputs-and-output.rs | 2 ++ .../bad-inputs-and-output.stderr | 25 ++++++++++++++++--- .../unpretty-parenthesized.rs | 11 ++++++++ .../unpretty-parenthesized.stderr | 12 +++++++++ .../unpretty-parenthesized.stdout | 15 +++++++++++ 6 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.rs create mode 100644 tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stderr create mode 100644 tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stdout diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index de94c1bc4779..b3923b651eb3 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -485,17 +485,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if let Some(args) = constraint.gen_args.as_ref() && matches!( args, - ast::GenericArgs::ReturnTypeNotation(..) | ast::GenericArgs::Parenthesized(..) + ast::GenericArgs::ReturnTypeNotation(..) ) { - // RTN is gated elsewhere, and parenthesized args will turn into - // another error. - if matches!(args, ast::GenericArgs::Parenthesized(..)) { - self.sess.delay_span_bug( - constraint.span, - "should have emitted a parenthesized generics error", - ); - } + // RTN is gated below with a `gate_all`. } else { gate_feature_post!( &self, diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs index 75aa25906aa0..2f9a1d1c76e0 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs @@ -10,11 +10,13 @@ trait Trait { fn foo>() {} //~^ ERROR argument types not allowed with return type notation +//~| ERROR associated type bounds are unstable fn bar (): Send>>() {} //~^ ERROR return type not allowed with return type notation fn baz>() {} //~^ ERROR return type notation arguments must be elided with `..` +//~| ERROR associated type bounds are unstable fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr index 5b075a0fa292..b354a6805d6e 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr @@ -1,9 +1,27 @@ error: return type not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:14:28 + --> $DIR/bad-inputs-and-output.rs:15:28 | LL | fn bar (): Send>>() {} | ^^^^^ help: remove the return type +error[E0658]: associated type bounds are unstable + --> $DIR/bad-inputs-and-output.rs:11:17 + | +LL | fn foo>() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/bad-inputs-and-output.rs:18:17 + | +LL | fn baz>() {} + | ^^^^^^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bad-inputs-and-output.rs:3:12 | @@ -28,10 +46,11 @@ LL | fn foo>() {} | ^^^^^ help: remove the input types: `(..)` error: return type notation arguments must be elided with `..` - --> $DIR/bad-inputs-and-output.rs:17:23 + --> $DIR/bad-inputs-and-output.rs:18:23 | LL | fn baz>() {} | ^^ help: add `..`: `(..)` -error: aborting due to 3 previous errors; 2 warnings emitted +error: aborting due to 5 previous errors; 2 warnings emitted +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.rs b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.rs new file mode 100644 index 000000000000..9129f37e0c6b --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.rs @@ -0,0 +1,11 @@ +// edition: 2021 +// compile-flags: -Zunpretty=expanded + +trait Trait { + async fn method() {} +} + +fn foo>() {} +//~^ ERROR associated type bounds are unstable + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stderr b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stderr new file mode 100644 index 000000000000..77e015b4160b --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stderr @@ -0,0 +1,12 @@ +error[E0658]: associated type bounds are unstable + --> $DIR/unpretty-parenthesized.rs:8:17 + | +LL | fn foo>() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stdout b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stdout new file mode 100644 index 000000000000..b3dea8f6eca7 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stdout @@ -0,0 +1,15 @@ +#![feature(prelude_import)] +#[prelude_import] +use std::prelude::rust_2021::*; +#[macro_use] +extern crate std; +// edition: 2021 +// compile-flags: -Zunpretty=expanded + +trait Trait { + async fn method() {} +} + +fn foo>() {} + +fn main() {} From 5c3e5af2ed3776755e584530fd8915544292b821 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 3 Apr 2023 14:22:09 -0700 Subject: [PATCH 068/267] Doc-comment `IndexVec::from_elem` and use it in a few more places --- .../src/type_check/liveness/local_use_map.rs | 4 ++-- compiler/rustc_index/src/vec.rs | 11 +++++++++++ .../src/infer/lexical_region_resolve/mod.rs | 2 +- compiler/rustc_mir_transform/src/coverage/graph.rs | 5 ++--- compiler/rustc_ty_utils/src/layout.rs | 2 +- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index 8023ef60d205..2c387edfef07 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -63,7 +63,7 @@ impl LocalUseMap { elements: &RegionValueElements, body: &Body<'_>, ) -> Self { - let nones = IndexVec::from_elem_n(None, body.local_decls.len()); + let nones = IndexVec::from_elem(None, &body.local_decls); let mut local_use_map = LocalUseMap { first_def_at: nones.clone(), first_use_at: nones.clone(), @@ -76,7 +76,7 @@ impl LocalUseMap { } let mut locals_with_use_data: IndexVec = - IndexVec::from_elem_n(false, body.local_decls.len()); + IndexVec::from_elem(false, &body.local_decls); live_locals.iter().for_each(|&local| locals_with_use_data[local] = true); LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data } diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 5945de2302a5..16cf9ae5cfc2 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -129,6 +129,17 @@ impl IndexVec { IndexVec { raw: Vec::with_capacity(capacity), _marker: PhantomData } } + /// Creates a new vector with a copy of `elem` for each index in `universe`. + /// + /// Thus `IndexVec::from_elem(elem, &universe)` is equivalent to + /// `IndexVec::::from_elem_n(elem, universe.len())`. That can help + /// type inference as it ensures that the resulting vector uses the same + /// index type as `universe`, rather than something potentially surprising. + /// + /// For example, if you want to store data for each local in a MIR body, + /// using `let mut uses = IndexVec::from_elem(vec![], &body.local_decls);` + /// ensures that `uses` is an `IndexVec`, and thus can give + /// better error messages later if one accidentally mismatches indices. #[inline] pub fn from_elem(elem: T, universe: &IndexSlice) -> Self where diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 9e2bdb7f510b..f298b95ca35b 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -203,7 +203,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // Tracks the `VarSubVar` constraints generated for each region vid. We // later use this to expand across vids. - let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len()); + let mut constraints = IndexVec::from_elem(Vec::new(), &var_values.values); // Tracks the changed region vids. let mut changes = Vec::new(); for constraint in self.data.constraints.keys() { diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 689d6c71361d..6a73f2a65781 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -37,8 +37,7 @@ impl CoverageGraph { // `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so // de-duplication is required. This is done without reordering the successors. - let bcbs_len = bcbs.len(); - let mut seen = IndexVec::from_elem_n(false, bcbs_len); + let mut seen = IndexVec::from_elem(false, &bcbs); let successors = IndexVec::from_fn_n( |bcb| { for b in seen.iter_mut() { @@ -60,7 +59,7 @@ impl CoverageGraph { bcbs.len(), ); - let mut predecessors = IndexVec::from_elem_n(Vec::new(), bcbs.len()); + let mut predecessors = IndexVec::from_elem(Vec::new(), &bcbs); for (bcb, bcb_successors) in successors.iter_enumerated() { for &successor in bcb_successors { predecessors[successor].push(bcb); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 73f86f74d14f..e8155520c9b7 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -522,7 +522,7 @@ fn generator_saved_local_eligibility( use SavedLocalEligibility::*; let mut assignments: IndexVec = - IndexVec::from_elem_n(Unassigned, info.field_tys.len()); + IndexVec::from_elem(Unassigned, &info.field_tys); // The saved locals not eligible for overlap. These will get // "promoted" to the prefix of our generator. From fc5de13d315c1b857ff53054fd68c4a928122330 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 3 Apr 2023 15:30:28 -0700 Subject: [PATCH 069/267] rustdoc: convert `print_tuple_struct_fields` to return a Display --- src/librustdoc/html/render/print_item.rs | 34 +++++++++++++----------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 674cd0d62d49..7837368f3405 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1174,17 +1174,23 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: document_type_layout(w, cx, def_id); } -fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) { - for (i, ty) in s.iter().enumerate() { - if i > 0 { - w.write_str(", "); +fn print_tuple_struct_fields<'a, 'cx: 'a>( + cx: &'a Context<'cx>, + s: &'a [clean::Item], +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(|f| { + for (i, ty) in s.iter().enumerate() { + if i > 0 { + f.write_str(", ")?; + } + match *ty.kind { + clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_")?, + clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx))?, + _ => unreachable!(), + } } - match *ty.kind { - clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"), - clean::StructFieldItem(ref ty) => write!(w, "{}", ty.print(cx)), - _ => unreachable!(), - } - } + Ok(()) + }) } fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) { @@ -1221,9 +1227,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: clean::VariantItem(ref var) => match var.kind { clean::VariantKind::CLike => write!(w, "{}", name), clean::VariantKind::Tuple(ref s) => { - write!(w, "{}(", name); - print_tuple_struct_fields(w, cx, s); - w.write_str(")"); + write!(w, "{name}({})", print_tuple_struct_fields(cx, s),); } clean::VariantKind::Struct(ref s) => { render_struct(w, v, None, None, &s.fields, " ", false, cx); @@ -1276,9 +1280,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; if let clean::VariantKind::Tuple(ref s) = variant_data.kind { - w.write_str("("); - print_tuple_struct_fields(w, cx, s); - w.write_str(")"); + write!(w, "({})", print_tuple_struct_fields(cx, s),); } w.write_str(""); From 94faa5c7399202d9b3277e1851f34b3248675ec8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 3 Apr 2023 15:35:27 -0700 Subject: [PATCH 070/267] rustdoc: convert render_attributes_in_pre to return a Display --- src/librustdoc/html/render/mod.rs | 17 ++++++++++---- src/librustdoc/html/render/print_item.rs | 30 ++++++++++++------------ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index d75d03071f89..920fbdcf0d61 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -50,6 +50,7 @@ use std::string::ToString; use askama::Template; use rustc_ast_pretty::pprust; use rustc_attr::{ConstStability, Deprecation, StabilityLevel}; +use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::Mutability; @@ -842,7 +843,7 @@ fn assoc_method( let (indent, indent_str, end_newline) = if parent == ItemType::Trait { header_len += 4; let indent_str = " "; - render_attributes_in_pre(w, meth, indent_str); + write!(w, "{}", render_attributes_in_pre(meth, indent_str)); (4, indent_str, Ending::NoNewline) } else { render_attributes_in_code(w, meth); @@ -1038,10 +1039,16 @@ fn attributes(it: &clean::Item) -> Vec { // When an attribute is rendered inside a `
` tag, it is formatted using
 // a whitespace prefix and newline.
-fn render_attributes_in_pre(w: &mut Buffer, it: &clean::Item, prefix: &str) {
-    for a in attributes(it) {
-        writeln!(w, "{}{}", prefix, a);
-    }
+fn render_attributes_in_pre<'a>(
+    it: &'a clean::Item,
+    prefix: &'a str,
+) -> impl fmt::Display + Captures<'a> {
+    crate::html::format::display_fn(move |f| {
+        for a in attributes(it) {
+            writeln!(f, "{}{}", prefix, a)?;
+        }
+        Ok(())
+    })
 }
 
 // When an attribute is rendered inside a  tag, it is formatted using
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 7837368f3405..b223c49a8999 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -544,12 +544,12 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
         f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
 
     wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
         w.reserve(header_len);
         write!(
             w,
-            "{vis}{constness}{asyncness}{unsafety}{abi}fn \
+            "{attrs}{vis}{constness}{asyncness}{unsafety}{abi}fn \
                 {name}{generics}{decl}{notable_traits}{where_clause}",
+            attrs = render_attributes_in_pre(it, ""),
             vis = visibility,
             constness = constness,
             asyncness = asyncness,
@@ -581,16 +581,16 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
 
     // Output the trait definition
     wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
         write!(
             w,
-            "{}{}{}trait {}{}{}",
+            "{attrs}{}{}{}trait {}{}{}",
             visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
             t.unsafety(tcx).print_with_space(),
             if t.is_auto(tcx) { "auto " } else { "" },
             it.name.unwrap(),
             t.generics.print(cx),
-            bounds
+            bounds,
+            attrs = render_attributes_in_pre(it, ""),
         );
 
         if !t.generics.where_predicates.is_empty() {
@@ -1057,14 +1057,14 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
 
 fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
     wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
         write!(
             w,
-            "trait {}{}{} = {};",
+            "{attrs}trait {}{}{} = {};",
             it.name.unwrap(),
             t.generics.print(cx),
             print_where_clause(&t.generics, cx, 0, Ending::Newline),
-            bounds(&t.bounds, true, cx)
+            bounds(&t.bounds, true, cx),
+            attrs = render_attributes_in_pre(it, ""),
         );
     });
 
@@ -1079,14 +1079,14 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &
 
 fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
     wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
         write!(
             w,
-            "type {}{}{where_clause} = impl {bounds};",
+            "{attrs}type {}{}{where_clause} = impl {bounds};",
             it.name.unwrap(),
             t.generics.print(cx),
             where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
             bounds = bounds(&t.bounds, false, cx),
+            attrs = render_attributes_in_pre(it, ""),
         );
     });
 
@@ -1102,15 +1102,15 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl
 fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) {
     fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
         wrap_item(w, |w| {
-            render_attributes_in_pre(w, it, "");
             write!(
                 w,
-                "{}type {}{}{where_clause} = {type_};",
+                "{attrs}{}type {}{}{where_clause} = {type_};",
                 visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
                 it.name.unwrap(),
                 t.generics.print(cx),
                 where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
                 type_ = t.type_.print(cx),
+                attrs = render_attributes_in_pre(it, ""),
             );
         });
     }
@@ -1130,7 +1130,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
 
 fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
     wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
+        write!(w, "{}", render_attributes_in_pre(it, ""));
         render_union(w, it, Some(&s.generics), &s.fields, cx);
     });
 
@@ -1197,13 +1197,13 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
     let tcx = cx.tcx();
     let count_variants = e.variants().count();
     wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
         write!(
             w,
-            "{}enum {}{}",
+            "{attrs}{}enum {}{}",
             visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
             it.name.unwrap(),
             e.generics.print(cx),
+            attrs = render_attributes_in_pre(it, ""),
         );
         if !print_where_clause_and_check(w, &e.generics, cx) {
             // If there wasn't a `where` clause, we add a whitespace.

From a368316905a6c8d4b7a0100c92f6f0186c7c2db8 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Tue, 4 Apr 2023 00:08:32 +0000
Subject: [PATCH 071/267] Remove intercrate and mark_ambiguous from Relation

---
 .../rustc_hir_analysis/src/check/dropck.rs    |  8 -----
 compiler/rustc_infer/src/infer/combine.rs     | 24 +++++++-------
 compiler/rustc_infer/src/infer/equate.rs      |  8 -----
 .../src/infer/error_reporting/mod.rs          |  9 ------
 compiler/rustc_infer/src/infer/glb.rs         |  9 ------
 compiler/rustc_infer/src/infer/lub.rs         |  9 ------
 .../rustc_infer/src/infer/nll_relate/mod.rs   | 24 --------------
 .../src/infer/outlives/test_type_match.rs     |  8 -----
 compiler/rustc_infer/src/infer/sub.rs         |  8 -----
 compiler/rustc_middle/src/ty/_match.rs        |  8 -----
 compiler/rustc_middle/src/ty/relate.rs        | 32 ++++++-------------
 .../traits/error_reporting/method_chain.rs    |  8 -----
 12 files changed, 22 insertions(+), 133 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 2bb724138f58..111bf5e54555 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -253,10 +253,6 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
         self.tcx
     }
 
-    fn intercrate(&self) -> bool {
-        false
-    }
-
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
@@ -269,10 +265,6 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
         true
     }
 
-    fn mark_ambiguous(&mut self) {
-        bug!()
-    }
-
     fn relate_with_variance>(
         &mut self,
         _: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 88a28e26005d..fe45b5ebe61b 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -137,6 +137,18 @@ impl<'tcx> InferCtxt<'tcx> {
                 Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
             }
 
+            // During coherence, opaque types should be treated as *possibly*
+            // equal to each other, even if their generic params differ, as
+            // they could resolve to the same hidden type, even for different
+            // generic params.
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if self.intercrate && a_def_id == b_def_id => {
+                relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
+                Ok(a)
+            }
+
             _ => ty::relate::super_relate_tys(relation, a, b),
         }
     }
@@ -505,10 +517,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
             Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, to_pred)
         }))
     }
-
-    pub fn mark_ambiguous(&mut self) {
-        self.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
-    }
 }
 
 struct Generalizer<'cx, 'tcx> {
@@ -581,10 +589,6 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
         self.infcx.tcx
     }
 
-    fn intercrate(&self) -> bool {
-        self.infcx.intercrate
-    }
-
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
@@ -597,10 +601,6 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
         true
     }
 
-    fn mark_ambiguous(&mut self) {
-        span_bug!(self.cause.span, "opaque types are handled in `tys`");
-    }
-
     fn binders(
         &mut self,
         a: ty::Binder<'tcx, T>,
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 38002357cde3..fe4a2dd38007 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -35,10 +35,6 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
         self.fields.tcx()
     }
 
-    fn intercrate(&self) -> bool {
-        self.fields.infcx.intercrate
-    }
-
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.fields.param_env
     }
@@ -47,10 +43,6 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
         self.a_is_expected
     }
 
-    fn mark_ambiguous(&mut self) {
-        self.fields.mark_ambiguous();
-    }
-
     fn relate_item_substs(
         &mut self,
         _item_def_id: DefId,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index d53e64830ff3..c9956b60a56d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2697,11 +2697,6 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
         self.0.tcx
     }
 
-    fn intercrate(&self) -> bool {
-        assert!(!self.0.intercrate);
-        false
-    }
-
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         // Unused, only for consts which we treat as always equal
         ty::ParamEnv::empty()
@@ -2715,10 +2710,6 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
         true
     }
 
-    fn mark_ambiguous(&mut self) {
-        bug!()
-    }
-
     fn relate_with_variance>(
         &mut self,
         _variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs
index 6395c4d4b207..2f659d9a6652 100644
--- a/compiler/rustc_infer/src/infer/glb.rs
+++ b/compiler/rustc_infer/src/infer/glb.rs
@@ -29,11 +29,6 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
         "Glb"
     }
 
-    fn intercrate(&self) -> bool {
-        assert!(!self.fields.infcx.intercrate);
-        false
-    }
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.fields.tcx()
     }
@@ -46,10 +41,6 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
         self.a_is_expected
     }
 
-    fn mark_ambiguous(&mut self) {
-        bug!("mark_ambiguous used outside of coherence");
-    }
-
     fn relate_with_variance>(
         &mut self,
         variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs
index 98cbd4c561c5..e41ec7e6c010 100644
--- a/compiler/rustc_infer/src/infer/lub.rs
+++ b/compiler/rustc_infer/src/infer/lub.rs
@@ -29,11 +29,6 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
         "Lub"
     }
 
-    fn intercrate(&self) -> bool {
-        assert!(!self.fields.infcx.intercrate);
-        false
-    }
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.fields.tcx()
     }
@@ -46,10 +41,6 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
         self.a_is_expected
     }
 
-    fn mark_ambiguous(&mut self) {
-        bug!("mark_ambiguous used outside of coherence");
-    }
-
     fn relate_with_variance>(
         &mut self,
         variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index f5d20cb7ebfe..7616a996da10 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -443,10 +443,6 @@ where
         self.infcx.tcx
     }
 
-    fn intercrate(&self) -> bool {
-        self.infcx.intercrate
-    }
-
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.delegate.param_env()
     }
@@ -459,17 +455,6 @@ where
         true
     }
 
-    fn mark_ambiguous(&mut self) {
-        let cause = ObligationCause::dummy_with_span(self.delegate.span());
-        let param_env = self.delegate.param_env();
-        self.delegate.register_obligations(vec![Obligation::new(
-            self.tcx(),
-            cause,
-            param_env,
-            ty::Binder::dummy(ty::PredicateKind::Ambiguous),
-        )]);
-    }
-
     #[instrument(skip(self, info), level = "trace", ret)]
     fn relate_with_variance>(
         &mut self,
@@ -834,11 +819,6 @@ where
         self.infcx.tcx
     }
 
-    fn intercrate(&self) -> bool {
-        assert!(!self.infcx.intercrate);
-        false
-    }
-
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.delegate.param_env()
     }
@@ -851,10 +831,6 @@ where
         true
     }
 
-    fn mark_ambiguous(&mut self) {
-        bug!()
-    }
-
     fn relate_with_variance>(
         &mut self,
         variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 3c6cc2b90010..01f900f050ee 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -137,10 +137,6 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         "Match"
     }
 
-    fn intercrate(&self) -> bool {
-        false
-    }
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -151,10 +147,6 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         true
     } // irrelevant
 
-    fn mark_ambiguous(&mut self) {
-        bug!()
-    }
-
     #[instrument(level = "trace", skip(self))]
     fn relate_with_variance>(
         &mut self,
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index fc73ca7606d2..0dd73a6e999e 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -35,10 +35,6 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
         "Sub"
     }
 
-    fn intercrate(&self) -> bool {
-        self.fields.infcx.intercrate
-    }
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.fields.infcx.tcx
     }
@@ -51,10 +47,6 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
         self.a_is_expected
     }
 
-    fn mark_ambiguous(&mut self) {
-        self.fields.mark_ambiguous()
-    }
-
     fn with_cause(&mut self, cause: Cause, f: F) -> R
     where
         F: FnOnce(&mut Self) -> R,
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index df9aa765dc15..468c2c818b24 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -37,10 +37,6 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         self.tcx
     }
 
-    fn intercrate(&self) -> bool {
-        false
-    }
-
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
@@ -48,10 +44,6 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         true
     } // irrelevant
 
-    fn mark_ambiguous(&mut self) {
-        bug!()
-    }
-
     fn relate_with_variance>(
         &mut self,
         _: ty::Variance,
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 3fc5f5bed8fc..46c931d61dc9 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -22,8 +22,6 @@ pub enum Cause {
 pub trait TypeRelation<'tcx>: Sized {
     fn tcx(&self) -> TyCtxt<'tcx>;
 
-    fn intercrate(&self) -> bool;
-
     fn param_env(&self) -> ty::ParamEnv<'tcx>;
 
     /// Returns a static string we can use for printouts.
@@ -33,9 +31,6 @@ pub trait TypeRelation<'tcx>: Sized {
     /// relation. Just affects error messages.
     fn a_is_expected(&self) -> bool;
 
-    /// Used during coherence. If called, must emit an always-ambiguous obligation.
-    fn mark_ambiguous(&mut self);
-
     fn with_cause(&mut self, _cause: Cause, f: F) -> R
     where
         F: FnOnce(&mut Self) -> R,
@@ -559,23 +554,16 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
             &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
             &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
         ) if a_def_id == b_def_id => {
-            if relation.intercrate() {
-                // During coherence, opaque types should be treated as equal to each other, even if their generic params
-                // differ, as they could resolve to the same hidden type, even for different generic params.
-                relation.mark_ambiguous();
-                Ok(a)
-            } else {
-                let opt_variances = tcx.variances_of(a_def_id);
-                let substs = relate_substs_with_variances(
-                    relation,
-                    a_def_id,
-                    opt_variances,
-                    a_substs,
-                    b_substs,
-                    false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
-                )?;
-                Ok(tcx.mk_opaque(a_def_id, substs))
-            }
+            let opt_variances = tcx.variances_of(a_def_id);
+            let substs = relate_substs_with_variances(
+                relation,
+                a_def_id,
+                opt_variances,
+                a_substs,
+                b_substs,
+                false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
+            )?;
+            Ok(tcx.mk_opaque(a_def_id, substs))
         }
 
         _ => Err(TypeError::Sorts(expected_found(relation, a, b))),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
index 13607b9079a7..7e1dba4ed262 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
@@ -21,10 +21,6 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
         self.infcx.tcx
     }
 
-    fn intercrate(&self) -> bool {
-        false
-    }
-
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
@@ -33,10 +29,6 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
         true
     }
 
-    fn mark_ambiguous(&mut self) {
-        bug!()
-    }
-
     fn relate_with_variance>(
         &mut self,
         _: ty::Variance,

From 6567bc9a4778d44cb46b7732aec6452358c62312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= 
Date: Tue, 4 Apr 2023 02:09:23 +0200
Subject: [PATCH 072/267] rustdoc: escape GAT args in more cases

---
 src/librustdoc/html/format.rs                 | 31 +++++++++----------
 .../generic-associated-types/issue-109488.rs  | 18 +++++++++++
 2 files changed, 33 insertions(+), 16 deletions(-)
 create mode 100644 tests/rustdoc/generic-associated-types/issue-109488.rs

diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 0895bb510d48..02b358e863b6 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1142,22 +1142,21 @@ fn fmt_type<'cx>(
             //        the ugliness comes from inlining across crates where
             //        everything comes in as a fully resolved QPath (hard to
             //        look at).
-            match href(trait_.def_id(), cx) {
-                Ok((ref url, _, ref path)) if !f.alternate() => {
-                    write!(
-                        f,
-                        "{name}{args}",
-                        url = url,
-                        shortty = ItemType::AssocType,
-                        name = assoc.name,
-                        path = join_with_double_colon(path),
-                        args = assoc.args.print(cx),
-                    )?;
-                }
-                _ => write!(f, "{}{:#}", assoc.name, assoc.args.print(cx))?,
-            }
-            Ok(())
+            if !f.alternate() && let Ok((url, _, path)) = href(trait_.def_id(), cx) {
+                write!(
+                    f,
+                    "{name}",
+                    shortty = ItemType::AssocType,
+                    name = assoc.name,
+                    path = join_with_double_colon(&path),
+                )
+            } else {
+                write!(f, "{}", assoc.name)
+            }?;
+
+            // Carry `f.alternate()` into this display w/o branching manually.
+            fmt::Display::fmt(&assoc.args.print(cx), f)
         }
     }
 }
diff --git a/tests/rustdoc/generic-associated-types/issue-109488.rs b/tests/rustdoc/generic-associated-types/issue-109488.rs
new file mode 100644
index 000000000000..99ae8a6c36c5
--- /dev/null
+++ b/tests/rustdoc/generic-associated-types/issue-109488.rs
@@ -0,0 +1,18 @@
+// Make sure that we escape the arguments of the GAT projection even if we fail to compute
+// the href of the corresponding trait (in this case it is private).
+// Further, test that we also linkify the GAT arguments.
+
+// @has 'issue_109488/type.A.html'
+// @has - '//pre[@class="rust item-decl"]' '::P>'
+// @has - '//pre[@class="rust item-decl"]//a[@class="enum"]/@href' '{{channel}}/core/option/enum.Option.html'
+pub type A = ::P>;
+
+/*private*/ trait Tr {
+    type P;
+}
+
+pub struct S;
+
+impl Tr for S {
+    type P = ();
+}

From 19f9f658d64c4cb3eae674db677aabbe9b41cb0f Mon Sep 17 00:00:00 2001
From: Michael Howell 
Date: Mon, 3 Apr 2023 17:12:19 -0700
Subject: [PATCH 073/267] rustdoc: migrate document functions to return a
 Display

---
 src/librustdoc/html/render/mod.rs        | 282 ++++++++++++-----------
 src/librustdoc/html/render/print_item.rs |  49 ++--
 src/librustdoc/html/sources.rs           |   6 +-
 3 files changed, 178 insertions(+), 159 deletions(-)

diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 920fbdcf0d61..49986433dfbb 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -70,7 +70,7 @@ use crate::formats::item_type::ItemType;
 use crate::formats::{AssocItemRender, Impl, RenderMode};
 use crate::html::escape::Escape;
 use crate::html::format::{
-    href, join_with_double_colon, print_abi_with_space, print_constness_with_space,
+    display_fn, href, join_with_double_colon, print_abi_with_space, print_constness_with_space,
     print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space,
     Buffer, Ending, HrefError, PrintWithSpace,
 };
@@ -409,128 +409,134 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
     )
 }
 
-fn document(
-    w: &mut Buffer,
-    cx: &mut Context<'_>,
-    item: &clean::Item,
-    parent: Option<&clean::Item>,
+fn document<'a, 'cx: 'a>(
+    cx: &'a mut Context<'cx>,
+    item: &'a clean::Item,
+    parent: Option<&'a clean::Item>,
     heading_offset: HeadingOffset,
-) {
+) -> impl fmt::Display + 'a + Captures<'cx> {
     if let Some(ref name) = item.name {
         info!("Documenting {}", name);
     }
-    document_item_info(cx, item, parent).render_into(w).unwrap();
-    if parent.is_none() {
-        document_full_collapsible(w, item, cx, heading_offset);
-    } else {
-        document_full(w, item, cx, heading_offset);
-    }
+
+    display_fn(move |f| {
+        document_item_info(cx, item, parent).render_into(f).unwrap();
+        if parent.is_none() {
+            write!(f, "{}", document_full_collapsible(item, cx, heading_offset))?;
+        } else {
+            write!(f, "{}", document_full(item, cx, heading_offset))?;
+        }
+        Ok(())
+    })
 }
 
 /// Render md_text as markdown.
-fn render_markdown(
-    w: &mut Buffer,
-    cx: &mut Context<'_>,
-    md_text: &str,
+fn render_markdown<'a, 'cx: 'a>(
+    cx: &'a mut Context<'cx>,
+    md_text: &'a str,
     links: Vec,
     heading_offset: HeadingOffset,
-) {
-    write!(
-        w,
-        "
{}
", - Markdown { - content: md_text, - links: &links, - ids: &mut cx.id_map, - error_codes: cx.shared.codes, - edition: cx.shared.edition(), - playground: &cx.shared.playground, - heading_offset, - } - .into_string() - ) +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(move |f| { + write!( + f, + "
{}
", + Markdown { + content: md_text, + links: &links, + ids: &mut cx.id_map, + error_codes: cx.shared.codes, + edition: cx.shared.edition(), + playground: &cx.shared.playground, + heading_offset, + } + .into_string() + ) + }) } /// Writes a documentation block containing only the first paragraph of the documentation. If the /// docs are longer, a "Read more" link is appended to the end. -fn document_short( - w: &mut Buffer, - item: &clean::Item, - cx: &mut Context<'_>, - link: AssocItemLink<'_>, - parent: &clean::Item, +fn document_short<'a, 'cx: 'a>( + item: &'a clean::Item, + cx: &'a mut Context<'cx>, + link: AssocItemLink<'a>, + parent: &'a clean::Item, show_def_docs: bool, -) { - document_item_info(cx, item, Some(parent)).render_into(w).unwrap(); - if !show_def_docs { - return; - } - if let Some(s) = item.doc_value() { - let (mut summary_html, has_more_content) = - MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content(); +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(move |f| { + document_item_info(cx, item, Some(parent)).render_into(f).unwrap(); + if !show_def_docs { + return Ok(()); + } + if let Some(s) = item.doc_value() { + let (mut summary_html, has_more_content) = + MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content(); - if has_more_content { - let link = format!(r#" Read more"#, assoc_href_attr(item, link, cx)); + if has_more_content { + let link = format!(r#" Read more"#, assoc_href_attr(item, link, cx)); - if let Some(idx) = summary_html.rfind("

") { - summary_html.insert_str(idx, &link); + if let Some(idx) = summary_html.rfind("

") { + summary_html.insert_str(idx, &link); + } else { + summary_html.push_str(&link); + } + } + + write!(f, "
{}
", summary_html)?; + } + Ok(()) + }) +} + +fn document_full_collapsible<'a, 'cx: 'a>( + item: &'a clean::Item, + cx: &'a mut Context<'cx>, + heading_offset: HeadingOffset, +) -> impl fmt::Display + 'a + Captures<'cx> { + document_full_inner(item, cx, true, heading_offset) +} + +fn document_full<'a, 'cx: 'a>( + item: &'a clean::Item, + cx: &'a mut Context<'cx>, + heading_offset: HeadingOffset, +) -> impl fmt::Display + 'a + Captures<'cx> { + document_full_inner(item, cx, false, heading_offset) +} + +fn document_full_inner<'a, 'cx: 'a>( + item: &'a clean::Item, + cx: &'a mut Context<'cx>, + is_collapsible: bool, + heading_offset: HeadingOffset, +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(move |f| { + if let Some(s) = item.collapsed_doc_value() { + debug!("Doc block: =====\n{}\n=====", s); + if is_collapsible { + write!( + f, + "
\ + \ + Expand description\ + {}
", + render_markdown(cx, &s, item.links(cx), heading_offset) + )?; } else { - summary_html.push_str(&link); + write!(f, "{}", render_markdown(cx, &s, item.links(cx), heading_offset))?; } } - write!(w, "
{}
", summary_html,); - } -} + let kind = match &*item.kind { + clean::ItemKind::StrippedItem(box kind) | kind => kind, + }; -fn document_full_collapsible( - w: &mut Buffer, - item: &clean::Item, - cx: &mut Context<'_>, - heading_offset: HeadingOffset, -) { - document_full_inner(w, item, cx, true, heading_offset); -} - -fn document_full( - w: &mut Buffer, - item: &clean::Item, - cx: &mut Context<'_>, - heading_offset: HeadingOffset, -) { - document_full_inner(w, item, cx, false, heading_offset); -} - -fn document_full_inner( - w: &mut Buffer, - item: &clean::Item, - cx: &mut Context<'_>, - is_collapsible: bool, - heading_offset: HeadingOffset, -) { - if let Some(s) = item.collapsed_doc_value() { - debug!("Doc block: =====\n{}\n=====", s); - if is_collapsible { - w.write_str( - "
\ - \ - Expand description\ - ", - ); - render_markdown(w, cx, &s, item.links(cx), heading_offset); - w.write_str("
"); - } else { - render_markdown(w, cx, &s, item.links(cx), heading_offset); + if let clean::ItemKind::FunctionItem(..) | clean::ItemKind::MethodItem(..) = kind { + render_call_locations(f, cx, item); } - } - - let kind = match &*item.kind { - clean::ItemKind::StrippedItem(box kind) | kind => kind, - }; - - if let clean::ItemKind::FunctionItem(..) | clean::ItemKind::MethodItem(..) = kind { - render_call_locations(w, cx, item); - } + Ok(()) + }) } #[derive(Template)] @@ -1485,18 +1491,25 @@ fn render_impl( document_item_info(cx, it, Some(parent)) .render_into(&mut info_buffer) .unwrap(); - document_full(&mut doc_buffer, item, cx, HeadingOffset::H5); + write!( + &mut doc_buffer, + "{}", + document_full(item, cx, HeadingOffset::H5) + ); short_documented = false; } else { // In case the item isn't documented, // provide short documentation from the trait. - document_short( + write!( &mut doc_buffer, - it, - cx, - link, - parent, - rendering_params.show_def_docs, + "{}", + document_short( + it, + cx, + link, + parent, + rendering_params.show_def_docs, + ) ); } } @@ -1505,18 +1518,15 @@ fn render_impl( .render_into(&mut info_buffer) .unwrap(); if rendering_params.show_def_docs { - document_full(&mut doc_buffer, item, cx, HeadingOffset::H5); + write!(&mut doc_buffer, "{}", document_full(item, cx, HeadingOffset::H5)); short_documented = false; } } } else { - document_short( + write!( &mut doc_buffer, - item, - cx, - link, - parent, - rendering_params.show_def_docs, + "{}", + document_short(item, cx, link, parent, rendering_params.show_def_docs,) ); } } @@ -2213,7 +2223,7 @@ const MAX_FULL_EXAMPLES: usize = 5; const NUM_VISIBLE_LINES: usize = 10; /// Generates the HTML for example call locations generated via the --scrape-examples flag. -fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item) { +fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &clean::Item) { let tcx = cx.tcx(); let def_id = item.item_id.expect_def_id(); let key = tcx.def_path_hash(def_id); @@ -2222,7 +2232,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite // Generate a unique ID so users can link to this section for a given method let id = cx.id_map.derive("scraped-examples"); write!( - w, + &mut w, "
\ \
\ @@ -2231,7 +2241,8 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
", root_path = cx.root_path(), id = id - ); + ) + .unwrap(); // Create a URL to a particular location in a reverse-dependency's source file let link_to_loc = |call_data: &CallData, loc: &CallLocation| -> (String, String) { @@ -2249,7 +2260,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite }; // Generate the HTML for a single example, being the title and code block - let write_example = |w: &mut Buffer, (path, call_data): (&PathBuf, &CallData)| -> bool { + let write_example = |mut w: &mut W, (path, call_data): (&PathBuf, &CallData)| -> bool { let contents = match fs::read_to_string(&path) { Ok(contents) => contents, Err(err) => { @@ -2297,7 +2308,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite let locations_encoded = serde_json::to_string(&line_ranges).unwrap(); write!( - w, + &mut w, "
\
\ {name} ({title})\ @@ -2310,10 +2321,12 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite // The locations are encoded as a data attribute, so they can be read // later by the JS for interactions. locations = Escape(&locations_encoded) - ); + ) + .unwrap(); if line_ranges.len() > 1 { - write!(w, r#" "#); + write!(w, r#" "#) + .unwrap(); } // Look for the example file in the source map if it exists, otherwise return a dummy span @@ -2340,7 +2353,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite decoration_info.insert("highlight", byte_ranges); sources::print_src( - w, + &mut w, contents_subset, file_span, cx, @@ -2348,7 +2361,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite highlight::DecorationInfo(decoration_info), sources::SourceContext::Embedded { offset: line_min, needs_expansion }, ); - write!(w, "
"); + write!(w, "
").unwrap(); true }; @@ -2382,7 +2395,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite // An example may fail to write if its source can't be read for some reason, so this method // continues iterating until a write succeeds - let write_and_skip_failure = |w: &mut Buffer, it: &mut Peekable<_>| { + let write_and_skip_failure = |w: &mut W, it: &mut Peekable<_>| { while let Some(example) = it.next() { if write_example(&mut *w, example) { break; @@ -2391,7 +2404,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite }; // Write just one example that's visible by default in the method's description. - write_and_skip_failure(w, &mut it); + write_and_skip_failure(&mut w, &mut it); // Then add the remaining examples in a hidden section. if it.peek().is_some() { @@ -2404,17 +2417,19 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
Hide additional examples
\
\
" - ); + ) + .unwrap(); // Only generate inline code for MAX_FULL_EXAMPLES number of examples. Otherwise we could // make the page arbitrarily huge! for _ in 0..MAX_FULL_EXAMPLES { - write_and_skip_failure(w, &mut it); + write_and_skip_failure(&mut w, &mut it); } // For the remaining examples, generate a
    containing links to the source files. if it.peek().is_some() { - write!(w, r#"").unwrap(); } - write!(w, "
"); + write!(w, "").unwrap(); } - write!(w, ""); + write!(w, "").unwrap(); } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index b223c49a8999..ea53f8d107dc 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -218,7 +218,7 @@ fn toggle_close(w: &mut Buffer) { } fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) { - document(w, cx, item, None, HeadingOffset::H2); + write!(w, "{}", document(cx, item, None, HeadingOffset::H2)); let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::>(); @@ -562,7 +562,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle notable_traits = notable_traits.unwrap_or_default(), ); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); } fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) { @@ -717,7 +717,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: }); // Trait documentation - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) { write!( @@ -735,7 +735,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let item_type = m.type_(); let id = cx.derive_id(format!("{}.{}", item_type, name)); let mut content = Buffer::empty_from(w); - document(&mut content, cx, m, Some(t), HeadingOffset::H5); + write!(&mut content, "{}", document(cx, m, Some(t), HeadingOffset::H5)); let toggled = !content.is_empty(); if toggled { let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; @@ -1068,7 +1068,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: & ); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show @@ -1090,7 +1090,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl ); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show @@ -1117,7 +1117,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea write_content(w, cx, it, t); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); let def_id = it.item_id.expect_def_id(); // Render any items associated directly to this alias, as otherwise they @@ -1134,7 +1134,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: render_union(w, it, Some(&s.generics), &s.fields, cx); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); let mut fields = s .fields @@ -1166,7 +1166,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: if let Some(stability_class) = field.stability_class(cx.tcx()) { write!(w, ""); } - document(w, cx, field, Some(it), HeadingOffset::H3); + write!(w, "{}", document(cx, field, Some(it), HeadingOffset::H3)); } } let def_id = it.item_id.expect_def_id(); @@ -1248,7 +1248,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: } }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); if count_variants != 0 { write!( @@ -1324,10 +1324,13 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: {f}: {t}\ ", f = field.name.unwrap(), - t = ty.print(cx) + t = ty.print(cx), + ); + write!( + w, + "{}", + document(cx, field, Some(variant), HeadingOffset::H5) ); - document(w, cx, field, Some(variant), HeadingOffset::H5); - write!(w, ""); } _ => unreachable!(), } @@ -1335,7 +1338,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str(""); } - document(w, cx, variant, Some(it), HeadingOffset::H4); + write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4)); } write!(w, ""); } @@ -1346,7 +1349,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) { highlight::render_item_decl_with_highlighting(&t.source, w); - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) { @@ -1372,12 +1375,12 @@ fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &c } } }); - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { let def_id = it.item_id.expect_def_id(); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { render_assoc_items(w, cx, it, def_id, AssocItemRender::All); } else { @@ -1435,7 +1438,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle } }); - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { @@ -1444,7 +1447,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); let mut fields = s .fields @@ -1478,7 +1481,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean item_type = ItemType::StructField, ty = ty.print(cx) ); - document(w, cx, field, Some(it), HeadingOffset::H3); + write!(w, "{}", document(cx, field, Some(it), HeadingOffset::H3)); } } } @@ -1499,7 +1502,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean typ = s.type_.print(cx) ); }); - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { @@ -1514,13 +1517,13 @@ fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { ); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) } fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } /// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order). diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 1d298f52f758..c8397967c879 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -2,7 +2,6 @@ use crate::clean; use crate::docfs::PathError; use crate::error::Error; use crate::html::format; -use crate::html::format::Buffer; use crate::html::highlight; use crate::html::layout; use crate::html::render::Context; @@ -17,6 +16,7 @@ use rustc_span::source_map::FileName; use std::cell::RefCell; use std::ffi::OsStr; +use std::fmt; use std::fs; use std::ops::RangeInclusive; use std::path::{Component, Path, PathBuf}; @@ -294,7 +294,7 @@ pub(crate) enum SourceContext { /// Wrapper struct to render the source code of a file. This will do things like /// adding line numbers to the left-hand side. pub(crate) fn print_src( - buf: &mut Buffer, + mut writer: impl fmt::Write, s: &str, file_span: rustc_span::Span, context: &Context<'_>, @@ -329,5 +329,5 @@ pub(crate) fn print_src( ); Ok(()) }); - Source { embedded, needs_expansion, lines, code_html: code }.render_into(buf).unwrap(); + Source { embedded, needs_expansion, lines, code_html: code }.render_into(&mut writer).unwrap(); } From 1b5ac399082253288772dc1dabaa9d5458c927a9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 4 Apr 2023 00:28:05 +0000 Subject: [PATCH 074/267] dyn* is a valid const --- .../src/transform/check_consts/check.rs | 2 +- tests/ui/dyn-star/const-and-static.rs | 10 ++++++++++ tests/ui/dyn-star/const-and-static.stderr | 11 +++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/ui/dyn-star/const-and-static.rs create mode 100644 tests/ui/dyn-star/const-and-static.stderr diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index d6110a050f2d..20c0852fe33a 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -553,7 +553,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } Rvalue::Cast(CastKind::DynStar, _, _) => { - unimplemented!() + // `dyn*` coercion is implemented for CTFE. } Rvalue::Cast(_, _, _) => {} diff --git a/tests/ui/dyn-star/const-and-static.rs b/tests/ui/dyn-star/const-and-static.rs new file mode 100644 index 000000000000..551b072abfab --- /dev/null +++ b/tests/ui/dyn-star/const-and-static.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(dyn_star)] +//~^ WARN the feature `dyn_star` is incomplete + +const C: dyn* Send + Sync = &(); + +static S: dyn* Send + Sync = &(); + +fn main() {} diff --git a/tests/ui/dyn-star/const-and-static.stderr b/tests/ui/dyn-star/const-and-static.stderr new file mode 100644 index 000000000000..df8f42fb0f57 --- /dev/null +++ b/tests/ui/dyn-star/const-and-static.stderr @@ -0,0 +1,11 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-and-static.rs:3:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + From 69e3f7a30dc4858d951473d8e4c2540a063e5350 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 4 Apr 2023 02:40:31 +0100 Subject: [PATCH 075/267] Disable `has_thread_local` on OpenHarmony OpenHarmony uses emulated TLS, which doesn't link properly when using thread-local variables across crate boundaries with `-C prefer-dynamic`. This PR makes thread_local! use pthreads directly instead. --- compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs | 1 + compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs index 0a5e654cf0d0..bf1b089f657b 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs @@ -18,6 +18,7 @@ pub fn target() -> Target { features: "+reserve-x18".into(), mcount: "\u{1}_mcount".into(), force_emulated_tls: true, + has_thread_local: false, supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs index a64f3a4f0493..16da24533677 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs @@ -21,6 +21,7 @@ pub fn target() -> Target { crt_static_default: false, mcount: "\u{1}mcount".into(), force_emulated_tls: true, + has_thread_local: false, ..super::linux_musl_base::opts() }, } From 8b21f9ee22fa96a656bfcbf6f0a57120304d56a8 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Tue, 4 Apr 2023 15:31:37 +0800 Subject: [PATCH 076/267] write threads info into log only when debugging --- compiler/rustc_log/src/lib.rs | 2 +- src/librustdoc/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 22924efa9484..21f6a404a015 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -83,7 +83,7 @@ pub fn init_env_logger(env: &str) -> Result<(), Error> { .with_verbose_exit(verbose_entry_exit) .with_verbose_entry(verbose_entry_exit) .with_indent_amount(2); - #[cfg(parallel_compiler)] + #[cfg(all(parallel_compiler, debug_assertions))] let layer = layer.with_thread_ids(true).with_thread_names(true); let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4c4dbc9864fd..79f53ee57cc9 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -203,7 +203,7 @@ fn init_logging() { .with_verbose_exit(true) .with_verbose_entry(true) .with_indent_amount(2); - #[cfg(parallel_compiler)] + #[cfg(all(parallel_compiler, debug_assertions))] let layer = layer.with_thread_ids(true).with_thread_names(true); use tracing_subscriber::layer::SubscriberExt; From 648a35e3279f98783aaa0f78b71f5aee2f247225 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 29 Dec 2022 09:45:19 +0000 Subject: [PATCH 077/267] Add ability to transmute with generic consts Previously if the expression contained generic consts and did not have a directly equivalent type, transmuting the type in this way was forbidden, despite the two sizes being identical. Instead, we should be able to lazily tell if the two consts are identical, and if so allow them to be transmuted. --- compiler/rustc_hir_typeck/src/intrinsicck.rs | 7 ++ compiler/rustc_middle/src/ty/layout.rs | 93 +++++++++++++++++++ tests/ui/const-generics/transmute-fail.rs | 34 +++++++ tests/ui/const-generics/transmute-fail.stderr | 52 +++++++++++ tests/ui/const-generics/transmute.rs | 82 ++++++++++++++++ 5 files changed, 268 insertions(+) create mode 100644 tests/ui/const-generics/transmute-fail.rs create mode 100644 tests/ui/const-generics/transmute-fail.stderr create mode 100644 tests/ui/const-generics/transmute.rs diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 19d2befc4387..eedab9fa1b0a 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -84,6 +84,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let skeleton_string = |ty: Ty<'tcx>, sk| match sk { Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()), Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"), + Ok(SizeSkeleton::Generic(size)) => { + if let Some(size) = size.try_eval_target_usize(tcx, self.param_env) { + format!("{size} bytes") + } else { + format!("generic size") + } + } Err(LayoutError::Unknown(bad)) => { if bad == ty { "this type does not have a fixed size".to_owned() diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 42fb5d031bbc..2a057e71eac4 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -281,6 +281,12 @@ pub enum SizeSkeleton<'tcx> { /// Any statically computable Layout. Known(Size), + /// This is a generic const expression (i.e. N * 2), which may contain some parameters. + /// It must be of type usize, and represents the size of a type in bytes. + /// It is not required to be evaluatable to a concrete value, but can be used to check + /// that another SizeSkeleton is of equal size. + Generic(ty::Const<'tcx>), + /// A potentially-fat pointer. Pointer { /// If true, this pointer is never null. @@ -326,6 +332,35 @@ impl<'tcx> SizeSkeleton<'tcx> { ), } } + ty::Array(inner, len) if len.ty() == tcx.types.usize => { + match SizeSkeleton::compute(inner, tcx, param_env)? { + // This may succeed because the multiplication of two types may overflow + // but a single size of a nested array will not. + SizeSkeleton::Known(s) => { + if let Some(c) = len.try_eval_target_usize(tcx, param_env) { + let size = s + .bytes() + .checked_mul(c) + .ok_or_else(|| LayoutError::SizeOverflow(ty))?; + return Ok(SizeSkeleton::Known(Size::from_bytes(size))); + } + let len = tcx.expand_abstract_consts(len); + let prev = ty::Const::from_target_usize(tcx, s.bytes()); + let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else { + return Err(LayoutError::SizeOverflow(ty)); + }; + Ok(SizeSkeleton::Generic(gen_size)) + } + SizeSkeleton::Pointer { .. } => Err(err), + SizeSkeleton::Generic(g) => { + let len = tcx.expand_abstract_consts(len); + let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else { + return Err(LayoutError::SizeOverflow(ty)); + }; + Ok(SizeSkeleton::Generic(gen_size)) + } + } + } ty::Adt(def, substs) => { // Only newtypes and enums w/ nullable pointer optimization. @@ -355,6 +390,9 @@ impl<'tcx> SizeSkeleton<'tcx> { } ptr = Some(field); } + SizeSkeleton::Generic(_) => { + return Err(err); + } } } Ok(ptr) @@ -410,11 +448,66 @@ impl<'tcx> SizeSkeleton<'tcx> { (SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => { a == b } + // constants are always pre-normalized into a canonical form so this + // only needs to check if their pointers are identical. + (SizeSkeleton::Generic(a), SizeSkeleton::Generic(b)) => a == b, _ => false, } } } +/// When creating the layout for types with abstract conts in their size (i.e. [usize; 4 * N]), +/// to ensure that they have a canonical order and can be compared directly we combine all +/// constants, and sort the other terms. This allows comparison of expressions of sizes, +/// allowing for things like transmutating between types that depend on generic consts. +/// This returns `None` if multiplication of constants overflows. +fn mul_sorted_consts<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, +) -> Option> { + use crate::mir::BinOp::Mul; + use ty::ConstKind::Expr; + use ty::Expr::Binop; + + let mut work = vec![a, b]; + let mut done = vec![]; + while let Some(n) = work.pop() { + if let Expr(Binop(Mul, l, r)) = n.kind() { + work.push(l); + work.push(r) + } else { + done.push(n); + } + } + let mut k = 1; + let mut overflow = false; + for _ in done.drain_filter(|c| { + let Some(c) = c.try_eval_target_usize(tcx, param_env) else { + return false; + }; + let Some(next) = c.checked_mul(k) else { + overflow = true; + return true; + }; + k *= next; + true + }) {} + if overflow { + return None; + } + if k != 1 { + done.push(ty::Const::from_target_usize(tcx, k)); + } else if k == 0 { + return Some(ty::Const::from_target_usize(tcx, 0)); + } + done.sort_unstable(); + + // create a single tree from the buffer + done.into_iter().reduce(|acc, n| tcx.mk_const(Expr(Binop(Mul, n, acc)), n.ty())) +} + pub trait HasTyCtxt<'tcx>: HasDataLayout { fn tcx(&self) -> TyCtxt<'tcx>; } diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs new file mode 100644 index 000000000000..490e4de9aac7 --- /dev/null +++ b/tests/ui/const-generics/transmute-fail.rs @@ -0,0 +1,34 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo(v: [[u32;H+1]; W]) -> [[u32; W+1]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + //~^ ERROR mismatched types + //~| ERROR mismatched types + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute between types + } +} + +fn baz(v: [[u32; H]; W]) -> [u32; W * H * H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 8888888] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn main() {} diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr new file mode 100644 index 000000000000..bf6a3b61dbb2 --- /dev/null +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -0,0 +1,52 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fail.rs:6:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; H+1]; W]` (generic size) + = note: target type: `[[u32; W+1]; H]` (generic size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fail.rs:15:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; H]; W]` (this type does not have a fixed size) + = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) + +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:11:53 + | +LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:11:67 + | +LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fail.rs:22:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; H]; W]` (generic size) + = note: target type: `[u32; W * H * H]` (generic size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fail.rs:29:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture) + = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[[u32; 9999999]; 777777777]; 8888888]` are too big for the current architecture) + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0512. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/transmute.rs b/tests/ui/const-generics/transmute.rs new file mode 100644 index 000000000000..9571b9157049 --- /dev/null +++ b/tests/ui/const-generics/transmute.rs @@ -0,0 +1,82 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn transpose(v: [[u32;H]; W]) -> [[u32; W]; H] { + unsafe { + std::mem::transmute(v) + } +} + +fn ident(v: [[u32; H]; W]) -> [[u32; H]; W] { + unsafe { + std::mem::transmute(v) + } +} + +fn flatten(v: [[u32; H]; W]) -> [u32; W * H] { + unsafe { + std::mem::transmute(v) + } +} + +fn coagulate(v: [u32; H*W]) -> [[u32; W];H] { + unsafe { + std::mem::transmute(v) + } +} + +fn flatten_3d( + v: [[[u32; D]; H]; W] +) -> [u32; D * W * H] { + unsafe { + std::mem::transmute(v) + } +} + +fn flatten_somewhat( + v: [[[u32; D]; H]; W] +) -> [[u32; D * W]; H] { + unsafe { + std::mem::transmute(v) + } +} + +fn known_size(v: [u16; L]) -> [u8; L * 2] { + unsafe { + std::mem::transmute(v) + } +} + +fn condense_bytes(v: [u8; L * 2]) -> [u16; L] { + unsafe { + std::mem::transmute(v) + } +} + +fn singleton_each(v: [u8; L]) -> [[u8;1]; L] { + unsafe { + std::mem::transmute(v) + } +} + +fn transpose_with_const( + v: [[u32; 2 * H]; W + W] +) -> [[u32; W + W]; 2 * H] { + unsafe { + std::mem::transmute(v) + } +} + +fn main() { + let _ = transpose([[0; 8]; 16]); + let _ = transpose_with_const::<8,4>([[0; 8]; 16]); + let _ = ident([[0; 8]; 16]); + let _ = flatten([[0; 13]; 5]); + let _: [[_; 5]; 13] = coagulate([0; 65]); + let _ = flatten_3d([[[0; 3]; 13]; 5]); + let _ = flatten_somewhat([[[0; 3]; 13]; 5]); + let _ = known_size([16; 13]); + let _: [u16; 5] = condense_bytes([16u8; 10]); + let _ = singleton_each([16; 10]); +} From aad33198ff9096a3671cc4938f4b7dba983617be Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 14 Mar 2023 11:30:23 +0000 Subject: [PATCH 078/267] Remove a fishy Clone impl --- compiler/rustc_data_structures/src/sync.rs | 8 -------- .../rustc_middle/src/mir/interpret/mod.rs | 3 ++- compiler/rustc_query_system/src/cache.rs | 7 ++++++- compiler/rustc_span/src/lib.rs | 20 ++++++++++++++++++- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 4e2126fff7be..9e9c3c6b9d70 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -481,14 +481,6 @@ impl Default for Lock { } } -// FIXME: Probably a bad idea -impl Clone for Lock { - #[inline] - fn clone(&self) -> Self { - Lock::new(self.borrow().clone()) - } -} - #[derive(Debug, Default)] pub struct RwLock(InnerRwLock); diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 1766d7a66980..1f8b650e34cf 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -263,7 +263,8 @@ impl AllocDecodingState { } pub fn new(data_offsets: Vec) -> Self { - let decoding_state = vec![Lock::new(State::Empty); data_offsets.len()]; + let decoding_state = + std::iter::repeat_with(|| Lock::new(State::Empty)).take(data_offsets.len()).collect(); Self { decoding_state, data_offsets } } diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_query_system/src/cache.rs index 7cc885be2ba6..6e862db0b254 100644 --- a/compiler/rustc_query_system/src/cache.rs +++ b/compiler/rustc_query_system/src/cache.rs @@ -7,11 +7,16 @@ use rustc_data_structures::sync::Lock; use std::hash::Hash; -#[derive(Clone)] pub struct Cache { hashmap: Lock>>, } +impl Clone for Cache { + fn clone(&self) -> Self { + Self { hashmap: Lock::new(self.hashmap.borrow().clone()) } + } +} + impl Default for Cache { fn default() -> Self { Self { hashmap: Default::default() } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index e14760aa0188..11cd5811be8b 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1318,7 +1318,6 @@ pub struct SourceFileDiffs { } /// A single source in the [`SourceMap`]. -#[derive(Clone)] pub struct SourceFile { /// The name of the file that the source came from. Source that doesn't /// originate from files has names between angle brackets by convention @@ -1349,6 +1348,25 @@ pub struct SourceFile { pub cnum: CrateNum, } +impl Clone for SourceFile { + fn clone(&self) -> Self { + Self { + name: self.name.clone(), + src: self.src.clone(), + src_hash: self.src_hash.clone(), + external_src: Lock::new(self.external_src.borrow().clone()), + start_pos: self.start_pos.clone(), + end_pos: self.end_pos.clone(), + lines: Lock::new(self.lines.borrow().clone()), + multibyte_chars: self.multibyte_chars.clone(), + non_narrow_chars: self.non_narrow_chars.clone(), + normalized_pos: self.normalized_pos.clone(), + name_hash: self.name_hash.clone(), + cnum: self.cnum.clone(), + } + } +} + impl Encodable for SourceFile { fn encode(&self, s: &mut S) { self.name.encode(s); From c7a3a943f2a1dd974f8887fe79ab3ff43f7005ac Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 14 Mar 2023 11:46:48 +0000 Subject: [PATCH 079/267] Replace a lock with an atomic --- compiler/rustc_parse/src/parser/mod.rs | 9 +++++++-- compiler/rustc_passes/src/entry.rs | 2 +- compiler/rustc_session/src/parse.rs | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 53c25a80c4bf..cc7270e7c2a3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -29,6 +29,7 @@ use rustc_ast::{Async, AttrArgs, AttrArgsEq, Expr, ExprKind, MacDelimiter, Mutab use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::Ordering; use rustc_errors::PResult; use rustc_errors::{ Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, @@ -1540,8 +1541,12 @@ pub(crate) fn make_unclosed_delims_error( } pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, sess: &ParseSess) { - *sess.reached_eof.borrow_mut() |= - unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none()); + let _ = sess.reached_eof.compare_exchange( + false, + unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none()), + Ordering::Relaxed, + Ordering::Relaxed, + ); for unmatched in unclosed_delims.drain(..) { if let Some(mut e) = make_unclosed_delims_error(unmatched, sess) { e.emit(); diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 8c3dff23b272..e3e4b73efa32 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -187,7 +187,7 @@ fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 { fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) { let sp = tcx.def_span(CRATE_DEF_ID); - if *tcx.sess.parse_sess.reached_eof.borrow() { + if tcx.sess.parse_sess.reached_eof.load(rustc_data_structures::sync::Ordering::Relaxed) { // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about // the missing `fn main()` then as it might have been hidden inside an unclosed block. tcx.sess.delay_span_bug(sp, "`main` not found, but expected unclosed brace error"); diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 4e8c3f73e29c..e451668e5885 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -8,7 +8,7 @@ use crate::lint::{ }; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_data_structures::sync::{Lock, Lrc}; +use rustc_data_structures::sync::{AtomicBool, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, @@ -208,7 +208,7 @@ pub struct ParseSess { pub gated_spans: GatedSpans, pub symbol_gallery: SymbolGallery, /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. - pub reached_eof: Lock, + pub reached_eof: AtomicBool, /// Environment variables accessed during the build and their values when they exist. pub env_depinfo: Lock)>>, /// File paths accessed during the build. @@ -254,7 +254,7 @@ impl ParseSess { ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), gated_spans: GatedSpans::default(), symbol_gallery: SymbolGallery::default(), - reached_eof: Lock::new(false), + reached_eof: AtomicBool::new(false), env_depinfo: Default::default(), file_depinfo: Default::default(), type_ascription_path_suggestions: Default::default(), From daee746771f12f58f707787e8075d9f89ec0511d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 14 Mar 2023 11:51:00 +0000 Subject: [PATCH 080/267] Add a usize-indexed append-only-vec --- compiler/rustc_data_structures/src/sync.rs | 2 +- .../rustc_data_structures/src/sync/vec.rs | 36 +++++++++++++++++-- compiler/rustc_interface/src/queries.rs | 4 +-- compiler/rustc_session/src/cstore.rs | 4 +-- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 9e9c3c6b9d70..80a9ccd6daa6 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -51,7 +51,7 @@ use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; pub use std::sync::atomic::Ordering; pub use std::sync::atomic::Ordering::SeqCst; -pub use vec::AppendOnlyVec; +pub use vec::{AppendOnlyIndexVec, AppendOnlyVec}; mod vec; diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs index cbea4f059992..6ffd2a75e810 100644 --- a/compiler/rustc_data_structures/src/sync/vec.rs +++ b/compiler/rustc_data_structures/src/sync/vec.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use rustc_index::vec::Idx; -pub struct AppendOnlyVec { +pub struct AppendOnlyIndexVec { #[cfg(not(parallel_compiler))] vec: elsa::vec::FrozenVec, #[cfg(parallel_compiler)] @@ -10,7 +10,7 @@ pub struct AppendOnlyVec { _marker: PhantomData, } -impl AppendOnlyVec { +impl AppendOnlyIndexVec { pub fn new() -> Self { Self { #[cfg(not(parallel_compiler))] @@ -39,3 +39,35 @@ impl AppendOnlyVec { return self.vec.get(i); } } + +pub struct AppendOnlyVec { + #[cfg(not(parallel_compiler))] + vec: elsa::vec::FrozenVec, + #[cfg(parallel_compiler)] + vec: elsa::sync::LockFreeFrozenVec, +} + +impl AppendOnlyVec { + pub fn new() -> Self { + Self { + #[cfg(not(parallel_compiler))] + vec: elsa::vec::FrozenVec::new(), + #[cfg(parallel_compiler)] + vec: elsa::sync::LockFreeFrozenVec::new(), + } + } + + pub fn push(&self, val: T) { + #[cfg(not(parallel_compiler))] + self.vec.push(val); + #[cfg(parallel_compiler)] + self.vec.push(val) + } + + pub fn get(&self, i: usize) -> Option { + #[cfg(not(parallel_compiler))] + return self.vec.get_copy(i); + #[cfg(parallel_compiler)] + return self.vec.get(i); + } +} diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index d2293780836d..818f450a58c1 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -7,7 +7,7 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{AppendOnlyVec, Lrc, OnceCell, RwLock, WorkerLocal}; +use rustc_data_structures::sync::{AppendOnlyIndexVec, Lrc, OnceCell, RwLock, WorkerLocal}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_incremental::DepGraphFuture; @@ -215,7 +215,7 @@ impl<'tcx> Queries<'tcx> { let cstore = RwLock::new(Box::new(CStore::new(sess)) as _); let definitions = RwLock::new(Definitions::new(sess.local_stable_crate_id())); - let source_span = AppendOnlyVec::new(); + let source_span = AppendOnlyIndexVec::new(); let _id = source_span.push(krate.spans.inner_span); debug_assert_eq!(_id, CRATE_DEF_ID); let untracked = Untracked { cstore, source_span, definitions }; diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index a262c06d91f0..dd1721801f37 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -6,7 +6,7 @@ use crate::search_paths::PathKind; use crate::utils::NativeLibKind; use crate::Session; use rustc_ast as ast; -use rustc_data_structures::sync::{self, AppendOnlyVec, MetadataRef, RwLock}; +use rustc_data_structures::sync::{self, AppendOnlyIndexVec, MetadataRef, RwLock}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions}; use rustc_span::hygiene::{ExpnHash, ExpnId}; @@ -257,6 +257,6 @@ pub type CrateStoreDyn = dyn CrateStore + sync::Sync + sync::Send; pub struct Untracked { pub cstore: RwLock>, /// Reference span for definitions. - pub source_span: AppendOnlyVec, + pub source_span: AppendOnlyIndexVec, pub definitions: RwLock, } From 46996326377b100fa461b49b5be0c91a075f55e5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 14 Mar 2023 12:11:56 +0000 Subject: [PATCH 081/267] Remove a lock in favor of an AppendOnlyVec --- compiler/rustc_data_structures/src/sync/vec.rs | 9 +++++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 3 +-- compiler/rustc_session/src/parse.rs | 17 ++++++++++------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs index 6ffd2a75e810..99de33685f6e 100644 --- a/compiler/rustc_data_structures/src/sync/vec.rs +++ b/compiler/rustc_data_structures/src/sync/vec.rs @@ -2,6 +2,7 @@ use std::marker::PhantomData; use rustc_index::vec::Idx; +#[derive(Default)] pub struct AppendOnlyIndexVec { #[cfg(not(parallel_compiler))] vec: elsa::vec::FrozenVec, @@ -40,6 +41,7 @@ impl AppendOnlyIndexVec { } } +#[derive(Default)] pub struct AppendOnlyVec { #[cfg(not(parallel_compiler))] vec: elsa::vec::FrozenVec, @@ -57,11 +59,14 @@ impl AppendOnlyVec { } } - pub fn push(&self, val: T) { + pub fn push(&self, val: T) -> usize { + #[cfg(not(parallel_compiler))] + let i = self.vec.len(); #[cfg(not(parallel_compiler))] self.vec.push(val); #[cfg(parallel_compiler)] - self.vec.push(val) + let i = self.vec.push(val); + i } pub fn get(&self, i: usize) -> Option { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2652a4280d37..0e8155afcb4d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1712,8 +1712,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let stability = tcx.lookup_stability(CRATE_DEF_ID); let macros = self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)); - let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans(); - for (i, span) in spans.into_iter().enumerate() { + for (i, span) in self.tcx.sess.parse_sess.proc_macro_quoted_spans() { let span = self.lazy(span); self.tables.proc_macro_quoted_spans.set_some(i, span); } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index e451668e5885..d80911747f3a 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -8,7 +8,7 @@ use crate::lint::{ }; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_data_structures::sync::{AtomicBool, Lock, Lrc}; +use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, @@ -219,7 +219,7 @@ pub struct ParseSess { pub assume_incomplete_release: bool, /// Spans passed to `proc_macro::quote_span`. Each span has a numerical /// identifier represented by its position in the vector. - pub proc_macro_quoted_spans: Lock>, + pub proc_macro_quoted_spans: AppendOnlyVec, /// Used to generate new `AttrId`s. Every `AttrId` is unique. pub attr_id_generator: AttrIdGenerator, } @@ -324,13 +324,16 @@ impl ParseSess { } pub fn save_proc_macro_span(&self, span: Span) -> usize { - let mut spans = self.proc_macro_quoted_spans.lock(); - spans.push(span); - return spans.len() - 1; + self.proc_macro_quoted_spans.push(span) } - pub fn proc_macro_quoted_spans(&self) -> Vec { - self.proc_macro_quoted_spans.lock().clone() + pub fn proc_macro_quoted_spans(&self) -> impl Iterator + '_ { + // This is equivalent to `.iter().copied().enumerate()`, but that isn't possible for + // AppendOnlyVec, so we resort to this scheme. + (0..) + .map(|i| (i, self.proc_macro_quoted_spans.get(i))) + .take_while(|(_, o)| o.is_some()) + .filter_map(|(i, o)| Some((i, o?))) } #[track_caller] From 7edd1d8799aff9d4dfea72e37c500ec8fdb0afb8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 14 Mar 2023 12:16:19 +0000 Subject: [PATCH 082/267] Replace another lock with an append-only vec --- compiler/rustc_data_structures/src/sync/vec.rs | 16 ++++++++++++++++ compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_parse/src/lexer/mod.rs | 2 +- compiler/rustc_session/src/parse.rs | 4 ++-- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs index 99de33685f6e..64b0aff6ca2d 100644 --- a/compiler/rustc_data_structures/src/sync/vec.rs +++ b/compiler/rustc_data_structures/src/sync/vec.rs @@ -76,3 +76,19 @@ impl AppendOnlyVec { return self.vec.get(i); } } + +impl AppendOnlyVec { + pub fn contains(&self, val: T) -> bool { + for i in 0.. { + match self.get(i) { + None => return false, + Some(v) => { + if val == v { + return true; + } + } + } + } + false + } +} diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c1b247e3d615..6b387df785e7 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1947,7 +1947,7 @@ impl KeywordIdents { }; // Don't lint `r#foo`. - if cx.sess().parse_sess.raw_identifier_spans.borrow().contains(&ident.span) { + if cx.sess().parse_sess.raw_identifier_spans.contains(ident.span) { return; } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 9dbddee5a56f..4a7da11a0978 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -175,7 +175,7 @@ impl<'a> StringReader<'a> { if !sym.can_be_raw() { self.sess.emit_err(errors::CannotBeRawIdent { span, ident: sym }); } - self.sess.raw_identifier_spans.borrow_mut().push(span); + self.sess.raw_identifier_spans.push(span); token::Ident(sym, true) } rustc_lexer::TokenKind::UnknownPrefix => { diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index d80911747f3a..61ce9291040c 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -194,7 +194,7 @@ pub struct ParseSess { pub edition: Edition, /// Places where raw identifiers were used. This is used to avoid complaining about idents /// clashing with keywords in new editions. - pub raw_identifier_spans: Lock>, + pub raw_identifier_spans: AppendOnlyVec, /// Places where identifiers that contain invalid Unicode codepoints but that look like they /// should be. Useful to avoid bad tokenization when encountering emoji. We group them to /// provide a single error per unique incorrect identifier. @@ -247,7 +247,7 @@ impl ParseSess { config: FxIndexSet::default(), check_config: CrateCheckConfig::default(), edition: ExpnId::root().expn_data().edition, - raw_identifier_spans: Lock::new(Vec::new()), + raw_identifier_spans: Default::default(), bad_unicode_identifiers: Lock::new(Default::default()), source_map, buffered_lints: Lock::new(vec![]), From a1d20cf7a20eb69b7a48c9897dfd8e9a3e4b6360 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 14 Mar 2023 12:30:16 +0000 Subject: [PATCH 083/267] Another AppendOnlyVec --- .../rustc_data_structures/src/sync/vec.rs | 33 ++++++++++++------- compiler/rustc_metadata/src/creader.rs | 4 +-- compiler/rustc_metadata/src/rmeta/decoder.rs | 12 +++---- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs index 64b0aff6ca2d..aefaa8519d53 100644 --- a/compiler/rustc_data_structures/src/sync/vec.rs +++ b/compiler/rustc_data_structures/src/sync/vec.rs @@ -75,20 +75,31 @@ impl AppendOnlyVec { #[cfg(parallel_compiler)] return self.vec.get(i); } + + pub fn iter_enumerated(&self) -> impl Iterator + '_ { + (0..) + .map(|i| (i, self.get(i))) + .take_while(|(_, o)| o.is_some()) + .filter_map(|(i, o)| Some((i, o?))) + } + + pub fn iter(&self) -> impl Iterator + '_ { + (0..).map(|i| self.get(i)).take_while(|o| o.is_some()).filter_map(|o| o) + } } impl AppendOnlyVec { pub fn contains(&self, val: T) -> bool { - for i in 0.. { - match self.get(i) { - None => return false, - Some(v) => { - if val == v { - return true; - } - } - } - } - false + self.iter_enumerated().any(|(_, v)| v == val) + } +} + +impl FromIterator for AppendOnlyVec { + fn from_iter>(iter: T) -> Self { + let this = Self::new(); + for val in iter { + this.push(val); + } + this } } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 23c1aebb8ae3..23aceca06223 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -185,7 +185,7 @@ impl CStore { fn push_dependencies_in_postorder(&self, deps: &mut Vec, cnum: CrateNum) { if !deps.contains(&cnum) { let data = self.get_crate_data(cnum); - for &dep in data.dependencies().iter() { + for dep in data.dependencies() { if dep != cnum { self.push_dependencies_in_postorder(deps, dep); } @@ -605,7 +605,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { if cmeta.update_extern_crate(extern_crate) { // Propagate the extern crate info to dependencies if it was updated. let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; - for &dep_cnum in cmeta.dependencies().iter() { + for dep_cnum in cmeta.dependencies() { self.update_extern_crate(dep_cnum, extern_crate); } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 43e5946f3135..21ac7e201f9a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -7,7 +7,7 @@ use rustc_ast as ast; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell}; +use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell}; use rustc_data_structures::unhash::UnhashMap; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro}; @@ -109,7 +109,7 @@ pub(crate) struct CrateMetadata { /// IDs as they are seen from the current compilation session. cnum_map: CrateNumMap, /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime. - dependencies: Lock>, + dependencies: AppendOnlyVec, /// How to link (or not link) this crate to the currently compiled crate. dep_kind: Lock, /// Filesystem location of this crate. @@ -1594,7 +1594,7 @@ impl CrateMetadata { .collect(); let alloc_decoding_state = AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); - let dependencies = Lock::new(cnum_map.iter().cloned().collect()); + let dependencies = cnum_map.iter().copied().collect(); // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation // that does not copy any data. It just does some data verification. @@ -1634,12 +1634,12 @@ impl CrateMetadata { cdata } - pub(crate) fn dependencies(&self) -> LockGuard<'_, Vec> { - self.dependencies.borrow() + pub(crate) fn dependencies(&self) -> impl Iterator + '_ { + self.dependencies.iter() } pub(crate) fn add_dependency(&self, cnum: CrateNum) { - self.dependencies.borrow_mut().push(cnum); + self.dependencies.push(cnum); } pub(crate) fn update_extern_crate(&self, new_extern_crate: ExternCrate) -> bool { From 300901b70509a0af2d971aa6f6104300da24212c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 15 Mar 2023 15:44:23 +0000 Subject: [PATCH 084/267] Use new iteration helpers instead of manually rolling them --- compiler/rustc_session/src/parse.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 61ce9291040c..002ae1e3165a 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -330,10 +330,7 @@ impl ParseSess { pub fn proc_macro_quoted_spans(&self) -> impl Iterator + '_ { // This is equivalent to `.iter().copied().enumerate()`, but that isn't possible for // AppendOnlyVec, so we resort to this scheme. - (0..) - .map(|i| (i, self.proc_macro_quoted_spans.get(i))) - .take_while(|(_, o)| o.is_some()) - .filter_map(|(i, o)| Some((i, o?))) + self.proc_macro_quoted_spans.iter_enumerated() } #[track_caller] From 54214c8d8d50c76fa66e1411fbbbd17bf314bcb5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 15 Mar 2023 16:25:28 +0000 Subject: [PATCH 085/267] Use a simpler atomic operation than the `compare_exchange` hammer --- compiler/rustc_data_structures/src/sync.rs | 8 ++++++++ compiler/rustc_parse/src/parser/mod.rs | 4 +--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 80a9ccd6daa6..e8ee4fb76cc5 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -107,6 +107,14 @@ cfg_if! { } } + impl Atomic { + pub fn fetch_or(&self, val: bool, _: Ordering) -> bool { + let result = self.0.get() | val; + self.0.set(val); + result + } + } + impl Atomic { #[inline] pub fn compare_exchange(&self, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index cc7270e7c2a3..aa57b804779b 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1541,11 +1541,9 @@ pub(crate) fn make_unclosed_delims_error( } pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, sess: &ParseSess) { - let _ = sess.reached_eof.compare_exchange( - false, + let _ = sess.reached_eof.fetch_or( unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none()), Ordering::Relaxed, - Ordering::Relaxed, ); for unmatched in unclosed_delims.drain(..) { if let Some(mut e) = make_unclosed_delims_error(unmatched, sess) { From b08a557f80865433d39d47934904a81b8ab3d720 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 08:37:47 +0000 Subject: [PATCH 086/267] rust-analyzer guided enum variant structification --- compiler/rustc_ast/src/ast.rs | 11 +++++++---- compiler/rustc_ast/src/mut_visit.rs | 4 ++-- compiler/rustc_ast/src/visit.rs | 4 ++-- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_passes/src/ast_validation.rs | 4 ++-- compiler/rustc_ast_pretty/src/pprust/state/item.rs | 3 ++- compiler/rustc_builtin_macros/src/global_allocator.rs | 4 ++-- compiler/rustc_expand/src/build.rs | 7 ++++++- compiler/rustc_lint/src/builtin.rs | 3 ++- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 5 +++-- compiler/rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- .../clippy_lints/src/redundant_static_lifetimes.rs | 4 ++-- src/tools/clippy/clippy_utils/src/ast_utils.rs | 2 +- src/tools/rustfmt/src/items.rs | 2 +- 16 files changed, 36 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 9b6bfaadef05..6c18e15ceb86 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2890,6 +2890,9 @@ pub struct Fn { pub body: Option>, } +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct Static(pub P, pub Mutability, pub Option>); + #[derive(Clone, Encodable, Decodable, Debug)] pub enum ItemKind { /// An `extern crate` item, with the optional *original* crate name if the crate was renamed. @@ -2903,7 +2906,7 @@ pub enum ItemKind { /// A static item (`static`). /// /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. - Static(P, Mutability, Option>), + Static(Static), /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. @@ -2975,7 +2978,7 @@ impl ItemKind { match self { ItemKind::ExternCrate(..) => "extern crate", ItemKind::Use(..) => "`use` import", - ItemKind::Static(..) => "static item", + ItemKind::Static(Static(..)) => "static item", ItemKind::Const(..) => "constant item", ItemKind::Fn(..) => "function", ItemKind::Mod(..) => "module", @@ -3084,7 +3087,7 @@ pub enum ForeignItemKind { impl From for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { - ForeignItemKind::Static(a, b, c) => ItemKind::Static(a, b, c), + ForeignItemKind::Static(a, b, c) => ItemKind::Static(Static(a, b, c)), ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), ForeignItemKind::MacCall(a) => ItemKind::MacCall(a), @@ -3097,7 +3100,7 @@ impl TryFrom for ForeignItemKind { fn try_from(item_kind: ItemKind) -> Result { Ok(match item_kind { - ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c), + ItemKind::Static(Static(a, b, c)) => ForeignItemKind::Static(a, b, c), ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind), ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind), ItemKind::MacCall(a) => ForeignItemKind::MacCall(a), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 514978f5569a..d5b5faf5cd77 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -7,10 +7,10 @@ //! a `MutVisitor` renaming item names in a module will miss all of those //! that are created by the expansion of a macro. -use crate::ast::*; use crate::ptr::P; use crate::token::{self, Token}; use crate::tokenstream::*; +use crate::{ast::*, Static}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::sync::Lrc; @@ -1030,7 +1030,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { match kind { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(ty, _, expr) => { + ItemKind::Static(Static(ty, _, expr)) => { vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e5a0ad1f1e48..bfd047c67c46 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -13,7 +13,7 @@ //! instance, a walker looking for item names in a module will miss all of //! those that are created by the expansion of a macro. -use crate::ast::*; +use crate::{ast::*, Static}; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -305,7 +305,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { match &item.kind { ItemKind::ExternCrate(_) => {} ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false), - ItemKind::Static(typ, _, expr) | ItemKind::Const(_, typ, expr) => { + ItemKind::Static(Static(typ, _, expr)) | ItemKind::Const(_, typ, expr) => { visitor.visit_ty(typ); walk_list!(visitor, visit_expr, expr); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 2efffbb6dc5e..cfcb55275c10 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -229,7 +229,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) } - ItemKind::Static(t, m, e) => { + ItemKind::Static(ast::Static(t, m, e)) => { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); hir::ItemKind::Static(ty, *m, body_id) } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 44b6c77fc419..777a1763e261 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -9,8 +9,8 @@ use itertools::{Either, Itertools}; use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; -use rustc_ast::walk_list; use rustc_ast::*; +use rustc_ast::{walk_list, Static}; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; use rustc_macros::Subdiagnostic; @@ -990,7 +990,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { replace_span: self.ending_semi_or_hi(item.span), }); } - ItemKind::Static(.., None) => { + ItemKind::Static(Static(.., None)) => { self.session.emit_err(errors::StaticWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index bf2c73a66a2c..b62e006fbb74 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -2,6 +2,7 @@ use crate::pp::Breaks::Inconsistent; use crate::pprust::state::delimited::IterDelimited; use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; +use ast::Static; use rustc_ast as ast; use rustc_ast::GenericBound; use rustc_ast::ModKind; @@ -156,7 +157,7 @@ impl<'a> State<'a> { self.print_use_tree(tree); self.word(";"); } - ast::ItemKind::Static(ty, mutbl, body) => { + ast::ItemKind::Static(Static(ty, mutbl, body)) => { let def = ast::Defaultness::Final; self.print_item_const( item.ident, diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 41b51bae7364..f817b20daf40 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -25,12 +25,12 @@ pub fn expand( // FIXME - if we get deref patterns, use them to reduce duplication here let (item, is_stmt, ty_span) = if let Annotatable::Item(item) = &item - && let ItemKind::Static(ty, ..) = &item.kind + && let ItemKind::Static(ast::Static(ty, ..)) = &item.kind { (item, false, ecx.with_def_site_ctxt(ty.span)) } else if let Annotatable::Stmt(stmt) = &item && let StmtKind::Item(item) = &stmt.kind - && let ItemKind::Static(ty, ..) = &item.kind + && let ItemKind::Static(ast::Static(ty, ..)) = &item.kind { (item, true, ecx.with_def_site_ctxt(ty.span)) } else { diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 8a16143311b8..82d1ff46ba9a 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -623,7 +623,12 @@ impl<'a> ExtCtxt<'a> { mutbl: ast::Mutability, expr: P, ) -> P { - self.item(span, name, AttrVec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr))) + self.item( + span, + name, + AttrVec::new(), + ast::ItemKind::Static(ast::Static(ty, mutbl, Some(expr))), + ) } pub fn item_const( diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c1b247e3d615..fbcc40f6657b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -43,6 +43,7 @@ use crate::{ types::{transparent_newtype_field, CItemKind}, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, }; +use ast::Static; use hir::IsAsync; use rustc_ast::attr; use rustc_ast::tokenstream::{TokenStream, TokenTree}; @@ -370,7 +371,7 @@ impl EarlyLintPass for UnsafeCode { } } - ast::ItemKind::Static(..) => { + ast::ItemKind::Static(Static(..)) => { if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleStatic); } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 42e59f92840e..b620e4592f5d 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -805,7 +805,7 @@ trait UnusedDelimLint { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind { + if let Const(.., Some(expr)) | Static(ast::Static(.., Some(expr))) = &item.kind { self.check_unused_delims_expr( cx, expr, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index ae8fe90e9d61..f2d37d810cfc 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -3,6 +3,7 @@ use crate::errors; use super::diagnostics::{dummy_arg, ConsumeClosingDelim}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; +use ast::Static; use rustc_ast::ast::*; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, TokenKind}; @@ -227,7 +228,7 @@ impl<'a> Parser<'a> { self.bump(); // `static` let m = self.parse_mutability(); let (ident, ty, expr) = self.parse_item_global(Some(m))?; - (ident, ItemKind::Static(ty, m, expr)) + (ident, ItemKind::Static(Static(ty, m, expr))) } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { @@ -862,7 +863,7 @@ impl<'a> Parser<'a> { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Static(a, _, b) => { + ItemKind::Static(Static(a, _, b)) => { self.sess.emit_err(errors::AssociatedStaticItemNotAllowed { span }); AssocItemKind::Const(Defaultness::Final, a, b) } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 19ccb3a6484a..b66df4752704 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -688,7 +688,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // These items live in the value namespace. - ItemKind::Static(_, mt, _) => { + ItemKind::Static(ast::Static(_, mt, _)) => { let res = Res::Def(DefKind::Static(mt), def_id); self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index b82b07bcf0cc..7e3c43e38076 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2346,7 +2346,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }); } - ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => { + ItemKind::Static(ast::Static(ref ty, _, ref expr)) | ItemKind::Const(_, ref ty, ref expr) => { self.with_static_rib(|this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { this.visit_ty(ty); diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index 44bf824aa0e2..d2f03f2a97fb 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; -use rustc_ast::ast::{Item, ItemKind, Ty, TyKind}; +use rustc_ast::ast::{Item, ItemKind, Ty, TyKind, Static}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -106,7 +106,7 @@ impl EarlyLintPass for RedundantStaticLifetimes { // #2438) } - if let ItemKind::Static(ref var_type, _, _) = item.kind { + if let ItemKind::Static(Static(ref var_type, _, _)) = item.kind { Self::visit_type(var_type, cx, "statics have by default a `'static` lifetime"); } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index d2dedc204395..30be129ad75a 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -286,7 +286,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { match (l, r) { (ExternCrate(l), ExternCrate(r)) => l == r, (Use(l), Use(r)) => eq_use_tree(l, r), - (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Static(ast::Static(lt, lm, le)), Static(ast::Static(rt, rm, re))) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 25e8a024857c..520bb5278001 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1805,7 +1805,7 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { let (defaultness, prefix, ty, mutability, expr) = match item.kind { - ast::ItemKind::Static(ref ty, mutability, ref expr) => { + ast::ItemKind::Static(ast::Static(ref ty, mutability, ref expr)) => { (None, "static", ty, mutability, expr) } ast::ItemKind::Const(defaultness, ref ty, ref expr) => { From e3828777a6b669c33fc59f2bddde44e888d304af Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 08:50:04 +0000 Subject: [PATCH 087/267] rust-analyzer guided tuple field to named field --- compiler/rustc_ast/src/ast.rs | 16 ++++++++++++---- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 3 ++- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_passes/src/ast_validation.rs | 2 +- .../rustc_ast_pretty/src/pprust/state/item.rs | 2 +- .../rustc_builtin_macros/src/global_allocator.rs | 4 ++-- compiler/rustc_expand/src/build.rs | 4 ++-- compiler/rustc_lint/src/builtin.rs | 3 +-- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 4 ++-- .../rustc_resolve/src/build_reduced_graph.rs | 4 ++-- compiler/rustc_resolve/src/late.rs | 3 ++- .../src/redundant_static_lifetimes.rs | 2 +- src/tools/clippy/clippy_utils/src/ast_utils.rs | 2 +- src/tools/rustfmt/src/items.rs | 2 +- 16 files changed, 33 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 6c18e15ceb86..898e2fc8b372 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2891,7 +2891,11 @@ pub struct Fn { } #[derive(Clone, Encodable, Decodable, Debug)] -pub struct Static(pub P, pub Mutability, pub Option>); +pub struct Static { + pub ty: P, + pub mutability: Mutability, + pub expr: Option>, +} #[derive(Clone, Encodable, Decodable, Debug)] pub enum ItemKind { @@ -2978,7 +2982,7 @@ impl ItemKind { match self { ItemKind::ExternCrate(..) => "extern crate", ItemKind::Use(..) => "`use` import", - ItemKind::Static(Static(..)) => "static item", + ItemKind::Static(..) => "static item", ItemKind::Const(..) => "constant item", ItemKind::Fn(..) => "function", ItemKind::Mod(..) => "module", @@ -3087,7 +3091,9 @@ pub enum ForeignItemKind { impl From for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { - ForeignItemKind::Static(a, b, c) => ItemKind::Static(Static(a, b, c)), + ForeignItemKind::Static(a, b, c) => { + ItemKind::Static(Static { ty: a, mutability: b, expr: c }) + } ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), ForeignItemKind::MacCall(a) => ItemKind::MacCall(a), @@ -3100,7 +3106,9 @@ impl TryFrom for ForeignItemKind { fn try_from(item_kind: ItemKind) -> Result { Ok(match item_kind { - ItemKind::Static(Static(a, b, c)) => ForeignItemKind::Static(a, b, c), + ItemKind::Static(Static { ty: a, mutability: b, expr: c }) => { + ForeignItemKind::Static(a, b, c) + } ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind), ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind), ItemKind::MacCall(a) => ForeignItemKind::MacCall(a), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index d5b5faf5cd77..b7372af1e0d3 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1030,7 +1030,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { match kind { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(Static(ty, _, expr)) => { + ItemKind::Static(Static { ty, mutability: _, expr }) => { vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index bfd047c67c46..e1d3c9d2cb74 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -305,7 +305,8 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { match &item.kind { ItemKind::ExternCrate(_) => {} ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false), - ItemKind::Static(Static(typ, _, expr)) | ItemKind::Const(_, typ, expr) => { + ItemKind::Static(Static { ty: typ, mutability: _, expr }) + | ItemKind::Const(_, typ, expr) => { visitor.visit_ty(typ); walk_list!(visitor, visit_expr, expr); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index cfcb55275c10..769b20a57981 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -229,7 +229,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) } - ItemKind::Static(ast::Static(t, m, e)) => { + ItemKind::Static(ast::Static { ty: t, mutability: m, expr: e }) => { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); hir::ItemKind::Static(ty, *m, body_id) } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 777a1763e261..8f77a372638e 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -990,7 +990,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { replace_span: self.ending_semi_or_hi(item.span), }); } - ItemKind::Static(Static(.., None)) => { + ItemKind::Static(Static { expr: None, .. }) => { self.session.emit_err(errors::StaticWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index b62e006fbb74..d545fc87674a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -157,7 +157,7 @@ impl<'a> State<'a> { self.print_use_tree(tree); self.word(";"); } - ast::ItemKind::Static(Static(ty, mutbl, body)) => { + ast::ItemKind::Static(Static { ty, mutability: mutbl, expr: body }) => { let def = ast::Defaultness::Final; self.print_item_const( item.ident, diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index f817b20daf40..f26e2572088b 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -25,12 +25,12 @@ pub fn expand( // FIXME - if we get deref patterns, use them to reduce duplication here let (item, is_stmt, ty_span) = if let Annotatable::Item(item) = &item - && let ItemKind::Static(ast::Static(ty, ..)) = &item.kind + && let ItemKind::Static(ast::Static { ty, ..}) = &item.kind { (item, false, ecx.with_def_site_ctxt(ty.span)) } else if let Annotatable::Stmt(stmt) = &item && let StmtKind::Item(item) = &stmt.kind - && let ItemKind::Static(ast::Static(ty, ..)) = &item.kind + && let ItemKind::Static(ast::Static { ty, ..}) = &item.kind { (item, true, ecx.with_def_site_ctxt(ty.span)) } else { diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 82d1ff46ba9a..e184f7320908 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -620,14 +620,14 @@ impl<'a> ExtCtxt<'a> { span: Span, name: Ident, ty: P, - mutbl: ast::Mutability, + mutability: ast::Mutability, expr: P, ) -> P { self.item( span, name, AttrVec::new(), - ast::ItemKind::Static(ast::Static(ty, mutbl, Some(expr))), + ast::ItemKind::Static(ast::Static { ty, mutability, expr: Some(expr) }), ) } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index fbcc40f6657b..c1b247e3d615 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -43,7 +43,6 @@ use crate::{ types::{transparent_newtype_field, CItemKind}, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, }; -use ast::Static; use hir::IsAsync; use rustc_ast::attr; use rustc_ast::tokenstream::{TokenStream, TokenTree}; @@ -371,7 +370,7 @@ impl EarlyLintPass for UnsafeCode { } } - ast::ItemKind::Static(Static(..)) => { + ast::ItemKind::Static(..) => { if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleStatic); } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index b620e4592f5d..8f652511459c 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -805,7 +805,7 @@ trait UnusedDelimLint { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - if let Const(.., Some(expr)) | Static(ast::Static(.., Some(expr))) = &item.kind { + if let Const(.., Some(expr)) | Static(ast::Static { expr: Some(expr), .. }) = &item.kind { self.check_unused_delims_expr( cx, expr, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index f2d37d810cfc..60ecaf5cb22a 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -228,7 +228,7 @@ impl<'a> Parser<'a> { self.bump(); // `static` let m = self.parse_mutability(); let (ident, ty, expr) = self.parse_item_global(Some(m))?; - (ident, ItemKind::Static(Static(ty, m, expr))) + (ident, ItemKind::Static(Static { ty, mutability: m, expr })) } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { @@ -863,7 +863,7 @@ impl<'a> Parser<'a> { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Static(Static(a, _, b)) => { + ItemKind::Static(Static { ty: a, mutability: _, expr: b }) => { self.sess.emit_err(errors::AssociatedStaticItemNotAllowed { span }); AssocItemKind::Const(Defaultness::Final, a, b) } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index b66df4752704..3a79ddca2eb4 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -688,8 +688,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // These items live in the value namespace. - ItemKind::Static(ast::Static(_, mt, _)) => { - let res = Res::Def(DefKind::Static(mt), def_id); + ItemKind::Static(ast::Static { mutability, .. }) => { + let res = Res::Def(DefKind::Static(mutability), def_id); self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } ItemKind::Const(..) => { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 7e3c43e38076..35b4d9dad83b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2346,7 +2346,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }); } - ItemKind::Static(ast::Static(ref ty, _, ref expr)) | ItemKind::Const(_, ref ty, ref expr) => { + ItemKind::Static(ast::Static { ref ty, ref expr, .. }) + | ItemKind::Const(_, ref ty, ref expr) => { self.with_static_rib(|this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { this.visit_ty(ty); diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index d2f03f2a97fb..434f00113319 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -106,7 +106,7 @@ impl EarlyLintPass for RedundantStaticLifetimes { // #2438) } - if let ItemKind::Static(Static(ref var_type, _, _)) = item.kind { + if let ItemKind::Static(Static{ ty: ref var_type,.. }) = item.kind { Self::visit_type(var_type, cx, "statics have by default a `'static` lifetime"); } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 30be129ad75a..258207639a17 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -286,7 +286,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { match (l, r) { (ExternCrate(l), ExternCrate(r)) => l == r, (Use(l), Use(r)) => eq_use_tree(l, r), - (Static(ast::Static(lt, lm, le)), Static(ast::Static(rt, rm, re))) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Static(ast::Static{ ty: lt, mutability: lm, expr: le}), Static(ast::Static { ty: rt, mutability: rm, expr: re})) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 520bb5278001..6cbe68ae3984 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1805,7 +1805,7 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { let (defaultness, prefix, ty, mutability, expr) = match item.kind { - ast::ItemKind::Static(ast::Static(ref ty, mutability, ref expr)) => { + ast::ItemKind::Static(ast::Static { ref ty, mutability, ref expr}) => { (None, "static", ty, mutability, expr) } ast::ItemKind::Const(defaultness, ref ty, ref expr) => { From ec74653652e59fc209506c084357ccee922a2d73 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 09:20:45 +0000 Subject: [PATCH 088/267] Split out ast::ItemKind::Const into its own struct --- compiler/rustc_ast/src/ast.rs | 17 ++++++++++----- compiler/rustc_ast/src/mut_visit.rs | 21 ++++++++++++------- compiler/rustc_ast/src/visit.rs | 8 +++---- compiler/rustc_ast_lowering/src/item.rs | 10 ++++----- .../rustc_ast_passes/src/ast_validation.rs | 16 +++++++------- .../rustc_ast_pretty/src/pprust/state/item.rs | 15 +++++++++---- compiler/rustc_builtin_macros/src/test.rs | 10 ++++----- compiler/rustc_expand/src/build.rs | 9 ++++++-- compiler/rustc_lint/src/unused.rs | 4 +++- compiler/rustc_parse/src/parser/item.rs | 14 ++++++++----- compiler/rustc_resolve/src/late.rs | 10 ++++----- .../src/redundant_static_lifetimes.rs | 4 ++-- .../clippy/clippy_utils/src/ast_utils.rs | 4 ++-- src/tools/rustfmt/src/items.rs | 8 +++---- 14 files changed, 89 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 898e2fc8b372..985b66e6bea6 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2897,6 +2897,13 @@ pub struct Static { pub expr: Option>, } +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct ConstItem { + pub defaultness: Defaultness, + pub ty: P, + pub expr: Option>, +} + #[derive(Clone, Encodable, Decodable, Debug)] pub enum ItemKind { /// An `extern crate` item, with the optional *original* crate name if the crate was renamed. @@ -2914,7 +2921,7 @@ pub enum ItemKind { /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. - Const(Defaultness, P, Option>), + Const(ConstItem), /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. @@ -3030,7 +3037,7 @@ pub type AssocItem = Item; pub enum AssocItemKind { /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. /// If `def` is parsed, then the constant is provided, and otherwise required. - Const(Defaultness, P, Option>), + Const(ConstItem), /// An associated function. Fn(Box), /// An associated type. @@ -3042,7 +3049,7 @@ pub enum AssocItemKind { impl AssocItemKind { pub fn defaultness(&self) -> Defaultness { match *self { - Self::Const(defaultness, ..) + Self::Const(ConstItem { defaultness, .. }) | Self::Fn(box Fn { defaultness, .. }) | Self::Type(box TyAlias { defaultness, .. }) => defaultness, Self::MacCall(..) => Defaultness::Final, @@ -3053,7 +3060,7 @@ impl AssocItemKind { impl From for ItemKind { fn from(assoc_item_kind: AssocItemKind) -> ItemKind { match assoc_item_kind { - AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c), + AssocItemKind::Const(item) => ItemKind::Const(item), AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), AssocItemKind::MacCall(a) => ItemKind::MacCall(a), @@ -3066,7 +3073,7 @@ impl TryFrom for AssocItemKind { fn try_from(item_kind: ItemKind) -> Result { Ok(match item_kind { - ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c), + ItemKind::Const(item) => AssocItemKind::Const(item), ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind), ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind), ItemKind::MacCall(a) => AssocItemKind::MacCall(a), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index b7372af1e0d3..e99a2fee67c8 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1034,10 +1034,8 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); } - ItemKind::Const(defaultness, ty, expr) => { - visit_defaultness(defaultness, vis); - vis.visit_ty(ty); - visit_opt(expr, |expr| vis.visit_expr(expr)); + ItemKind::Const(item) => { + visit_const_item(item, vis); } ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { visit_defaultness(defaultness, vis); @@ -1120,10 +1118,8 @@ pub fn noop_flat_map_assoc_item( visitor.visit_vis(vis); visit_attrs(attrs, visitor); match kind { - AssocItemKind::Const(defaultness, ty, expr) => { - visit_defaultness(defaultness, visitor); - visitor.visit_ty(ty); - visit_opt(expr, |expr| visitor.visit_expr(expr)); + AssocItemKind::Const(item) => { + visit_const_item(item, visitor); } AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { visit_defaultness(defaultness, visitor); @@ -1153,6 +1149,15 @@ pub fn noop_flat_map_assoc_item( smallvec![item] } +fn visit_const_item( + ConstItem { defaultness, ty, expr }: &mut ConstItem, + visitor: &mut T, +) { + visit_defaultness(defaultness, visitor); + visitor.visit_ty(ty); + visit_opt(expr, |expr| visitor.visit_expr(expr)); +} + pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { let FnHeader { unsafety, asyncness, constness, ext: _ } = header; visit_constness(constness, vis); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e1d3c9d2cb74..55a17efe4160 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -305,9 +305,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { match &item.kind { ItemKind::ExternCrate(_) => {} ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false), - ItemKind::Static(Static { ty: typ, mutability: _, expr }) - | ItemKind::Const(_, typ, expr) => { - visitor.visit_ty(typ); + ItemKind::Static(Static { ty, mutability: _, expr }) + | ItemKind::Const(ConstItem { ty, expr, .. }) => { + visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { @@ -675,7 +675,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, visitor.visit_ident(ident); walk_list!(visitor, visit_attribute, attrs); match kind { - AssocItemKind::Const(_, ty, expr) => { + AssocItemKind::Const(ConstItem { ty, expr, .. }) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 769b20a57981..b41bb5017e51 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -233,8 +233,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); hir::ItemKind::Static(ty, *m, body_id) } - ItemKind::Const(_, t, e) => { - let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); + ItemKind::Const(ast::ConstItem { ty, expr, .. }) => { + let (ty, body_id) = self.lower_const_item(ty, span, expr.as_deref()); hir::ItemKind::Const(ty, body_id) } ItemKind::Fn(box Fn { @@ -708,10 +708,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let trait_item_def_id = hir_id.expect_owner(); let (generics, kind, has_default) = match &i.kind { - AssocItemKind::Const(_, ty, default) => { + AssocItemKind::Const(ConstItem { ty, expr, .. }) => { let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); - let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); + let body = expr.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => { @@ -809,7 +809,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_attrs(hir_id, &i.attrs); let (generics, kind) = match &i.kind { - AssocItemKind::Const(_, ty, expr) => { + AssocItemKind::Const(ConstItem { ty, expr, .. }) => { let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); ( diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 8f77a372638e..43d086ec52d8 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -983,8 +983,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.err_handler().emit_err(errors::FieldlessUnion { span: item.span }); } } - ItemKind::Const(def, .., None) => { - self.check_defaultness(item.span, *def); + ItemKind::Const(ConstItem { defaultness, expr: None, .. }) => { + self.check_defaultness(item.span, *defaultness); self.session.emit_err(errors::ConstWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), @@ -1259,13 +1259,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if ctxt == AssocCtxt::Impl { match &item.kind { - AssocItemKind::Const(_, _, body) => { - if body.is_none() { - self.session.emit_err(errors::AssocConstWithoutBody { - span: item.span, - replace_span: self.ending_semi_or_hi(item.span), - }); - } + AssocItemKind::Const(ConstItem { expr: None, .. }) => { + self.session.emit_err(errors::AssocConstWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); } AssocItemKind::Fn(box Fn { body, .. }) => { if body.is_none() { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index d545fc87674a..92b9c8fd766a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -168,8 +168,15 @@ impl<'a> State<'a> { def, ); } - ast::ItemKind::Const(def, ty, body) => { - self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, *def); + ast::ItemKind::Const(ast::ConstItem { defaultness, ty, expr }) => { + self.print_item_const( + item.ident, + None, + ty, + expr.as_deref(), + &item.vis, + *defaultness, + ); } ast::ItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { self.print_fn_full( @@ -508,8 +515,8 @@ impl<'a> State<'a> { ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs); } - ast::AssocItemKind::Const(def, ty, body) => { - self.print_item_const(ident, None, ty, body.as_deref(), vis, *def); + ast::AssocItemKind::Const(ast::ConstItem { defaultness, ty, expr }) => { + self.print_item_const(ident, None, ty, expr.as_deref(), vis, *defaultness); } ast::AssocItemKind::Type(box ast::TyAlias { defaultness, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 44b9c4718a75..ced341e54130 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -264,11 +264,11 @@ pub fn expand_test_or_bench( cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp), ], // const $ident: test::TestDescAndFn = - ast::ItemKind::Const( - ast::Defaultness::Final, - cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), + ast::ItemKind::Const(ast::ConstItem { + defaultness: ast::Defaultness::Final, + ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), // test::TestDescAndFn { - Some( + expr: Some( cx.expr_struct( sp, test_path("TestDescAndFn"), @@ -361,7 +361,7 @@ pub fn expand_test_or_bench( ], ), // } ), - ), + }), ); test_const = test_const.map(|mut tc| { tc.vis.kind = ast::VisibilityKind::Public; diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index e184f7320908..39fed9fdd0d4 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -638,8 +638,13 @@ impl<'a> ExtCtxt<'a> { ty: P, expr: P, ) -> P { - let def = ast::Defaultness::Final; - self.item(span, name, AttrVec::new(), ast::ItemKind::Const(def, ty, Some(expr))) + let defaultness = ast::Defaultness::Final; + self.item( + span, + name, + AttrVec::new(), + ast::ItemKind::Const(ast::ConstItem { defaultness, ty, expr: Some(expr) }), + ) } // Builds `#[name]`. diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 8f652511459c..d920e237508c 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -805,7 +805,9 @@ trait UnusedDelimLint { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - if let Const(.., Some(expr)) | Static(ast::Static { expr: Some(expr), .. }) = &item.kind { + if let Const(ast::ConstItem { expr: Some(expr), .. }) + | Static(ast::Static { expr: Some(expr), .. }) = &item.kind + { self.check_unused_delims_expr( cx, expr, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 60ecaf5cb22a..f6422d30ba50 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -237,7 +237,7 @@ impl<'a> Parser<'a> { } else { self.recover_const_mut(const_span); let (ident, ty, expr) = self.parse_item_global(None)?; - (ident, ItemKind::Const(def_(), ty, expr)) + (ident, ItemKind::Const(ConstItem { defaultness: def_(), ty, expr })) } } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() { // TRAIT ITEM @@ -863,9 +863,13 @@ impl<'a> Parser<'a> { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Static(Static { ty: a, mutability: _, expr: b }) => { + ItemKind::Static(Static { ty, mutability: _, expr }) => { self.sess.emit_err(errors::AssociatedStaticItemNotAllowed { span }); - AssocItemKind::Const(Defaultness::Final, a, b) + AssocItemKind::Const(ConstItem { + defaultness: Defaultness::Final, + ty, + expr, + }) } _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), }, @@ -1115,12 +1119,12 @@ impl<'a> Parser<'a> { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Const(_, a, b) => { + ItemKind::Const(ConstItem { ty, expr, .. }) => { self.sess.emit_err(errors::ExternItemCannotBeConst { ident_span: ident.span, const_span: span.with_hi(ident.span.lo()), }); - ForeignItemKind::Static(a, Mutability::Not, b) + ForeignItemKind::Static(ty, Mutability::Not, expr) } _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), }, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 35b4d9dad83b..735644ec8d51 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2347,7 +2347,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } ItemKind::Static(ast::Static { ref ty, ref expr, .. }) - | ItemKind::Const(_, ref ty, ref expr) => { + | ItemKind::Const(ast::ConstItem { ref ty, ref expr, .. }) => { self.with_static_rib(|this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { this.visit_ty(ty); @@ -2625,11 +2625,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { for item in trait_items { self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); match &item.kind { - AssocItemKind::Const(_, ty, default) => { + AssocItemKind::Const(ast::ConstItem { ty, expr, .. }) => { self.visit_ty(ty); // Only impose the restrictions of `ConstRibKind` for an // actual constant expression in a provided default. - if let Some(expr) = default { + if let Some(expr) = expr { // We allow arbitrary const expressions inside of associated consts, // even if they are potentially not const evaluatable. // @@ -2800,7 +2800,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { use crate::ResolutionError::*; self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis))); match &item.kind { - AssocItemKind::Const(_, ty, default) => { + AssocItemKind::Const(ast::ConstItem { ty, expr, .. }) => { debug!("resolve_implementation AssocItemKind::Const"); // If this is a trait impl, ensure the const // exists in trait @@ -2815,7 +2815,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); self.visit_ty(ty); - if let Some(expr) = default { + if let Some(expr) = expr { // We allow arbitrary const expressions inside of associated consts, // even if they are potentially not const evaluatable. // diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index 434f00113319..d41f79f81315 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; -use rustc_ast::ast::{Item, ItemKind, Ty, TyKind, Static}; +use rustc_ast::ast::{Item, ItemKind, Ty, TyKind, Static, ConstItem}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -100,7 +100,7 @@ impl EarlyLintPass for RedundantStaticLifetimes { } if !item.span.from_expansion() { - if let ItemKind::Const(_, ref var_type, _) = item.kind { + if let ItemKind::Const(ConstItem { ty: ref var_type, .. }) = item.kind { Self::visit_type(var_type, cx, "constants have by default a `'static` lifetime"); // Don't check associated consts because `'static` cannot be elided on those (issue // #2438) diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 258207639a17..be841098dba3 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -287,7 +287,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (ExternCrate(l), ExternCrate(r)) => l == r, (Use(l), Use(r)) => eq_use_tree(l, r), (Static(ast::Static{ ty: lt, mutability: lm, expr: le}), Static(ast::Static { ty: rt, mutability: rm, expr: re})) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), - (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Const(ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(ast::ConstItem { defaultness: rd, ty: rt, expr: re} )) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { defaultness: ld, @@ -451,7 +451,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { use AssocItemKind::*; match (l, r) { - (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Const(ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(ast::ConstItem { defaultness: rd, ty: rt, expr: re})) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { defaultness: ld, diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 6cbe68ae3984..0dc8a4e937f2 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1808,7 +1808,7 @@ impl<'a> StaticParts<'a> { ast::ItemKind::Static(ast::Static { ref ty, mutability, ref expr}) => { (None, "static", ty, mutability, expr) } - ast::ItemKind::Const(defaultness, ref ty, ref expr) => { + ast::ItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => { (Some(defaultness), "const", ty, ast::Mutability::Not, expr) } _ => unreachable!(), @@ -1827,8 +1827,8 @@ impl<'a> StaticParts<'a> { pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { let (defaultness, ty, expr_opt) = match ti.kind { - ast::AssocItemKind::Const(defaultness, ref ty, ref expr_opt) => { - (defaultness, ty, expr_opt) + ast::AssocItemKind::Const(ast::ConstItem {defaultness, ref ty, ref expr}) => { + (defaultness, ty, expr) } _ => unreachable!(), }; @@ -1846,7 +1846,7 @@ impl<'a> StaticParts<'a> { pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { let (defaultness, ty, expr) = match ii.kind { - ast::AssocItemKind::Const(defaultness, ref ty, ref expr) => (defaultness, ty, expr), + ast::AssocItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => (defaultness, ty, expr), _ => unreachable!(), }; StaticParts { From b5d96d5ec5388b89c700b4b9e6f7f73afa9cbcb1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 4 Apr 2023 10:39:26 +0000 Subject: [PATCH 089/267] Move a const-prop-lint specific hack from mir interpret to const-prop-lint and make it fallible --- .../rustc_const_eval/src/interpret/operand.rs | 9 +--- .../src/ty/normalize_erasing_regions.rs | 6 +-- .../src/const_prop_lint.rs | 10 +++- tests/ui/mir/issue-109743.rs | 51 +++++++++++++++++++ 4 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 tests/ui/mir/issue-109743.rs diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 8d5192bca67e..5310ef0bb3ed 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -612,14 +612,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { span: Option, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - // FIXME(const_prop): normalization needed b/c const prop lint in - // `mir_drops_elaborated_and_const_checked`, which happens before - // optimized MIR. Only after optimizing the MIR can we guarantee - // that the `RevealAll` pass has happened and that the body's consts - // are normalized, so any call to resolve before that needs to be - // manually normalized. - let val = self.tcx.normalize_erasing_regions(self.param_env, *val); - match val { + match *val { mir::ConstantKind::Ty(ct) => { let ty = ct.ty(); let valtree = self.eval_ty_constant(ct, span)?; diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 578cd82aa4c2..7c59879a187f 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -193,9 +193,9 @@ impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { let arg = self.param_env.and(arg); self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!( - "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead", - arg.value - )) + "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead", + arg.value + )) } } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index d7696a570006..176027b3b93e 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -284,7 +284,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } - self.use_ecx(source_info, |this| this.ecx.eval_mir_constant(&c.literal, Some(c.span), None)) + // Normalization needed b/c const prop lint runs in + // `mir_drops_elaborated_and_const_checked`, which happens before + // optimized MIR. Only after optimizing the MIR can we guarantee + // that the `RevealAll` pass has happened and that the body's consts + // are normalized, so any call to resolve before that needs to be + // manually normalized. + let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.literal).ok()?; + + self.use_ecx(source_info, |this| this.ecx.eval_mir_constant(&val, Some(c.span), None)) } /// Returns the value, if any, of evaluating `place`. diff --git a/tests/ui/mir/issue-109743.rs b/tests/ui/mir/issue-109743.rs new file mode 100644 index 000000000000..73f3405e3ad7 --- /dev/null +++ b/tests/ui/mir/issue-109743.rs @@ -0,0 +1,51 @@ +// build-pass +// compile-flags: --crate-type=lib + +use std::marker::PhantomData; + +pub trait StreamOnce { + type Token; +} + +impl StreamOnce for &str { + type Token = (); +} + +pub trait Parser { + type PartialState: Default; + fn parse_mode(&self, _state: &Self::PartialState) {} + fn parse_mode_impl() {} +} + +pub fn parse_bool<'a>() -> impl Parser<&'a str> { + pub struct TokensCmp + where + Input: StreamOnce, + { + _cmp: C, + _marker: PhantomData, + } + + impl Parser for TokensCmp + where + C: FnMut(Input::Token), + Input: StreamOnce, + { + type PartialState = (); + } + + TokensCmp { _cmp: |_| (), _marker: PhantomData } +} + +pub struct ParseBool; + +impl<'a> Parser<&'a str> for ParseBool +where + &'a str: StreamOnce, +{ + type PartialState = (); + + fn parse_mode_impl() { + parse_bool().parse_mode(&Default::default()) + } +} From 92b759137178c732ea541134cede507b606e0a0d Mon Sep 17 00:00:00 2001 From: jyn Date: Tue, 4 Apr 2023 07:37:33 -0400 Subject: [PATCH 090/267] Add a best guess at what `line-directives-only` means --- src/doc/rustc/src/codegen-options/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 4d418f9c9b74..62347f169a5e 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -72,9 +72,9 @@ This flag controls the generation of debug information. It takes one of the following values: * `0` or `none`: no debug info at all (the default). -* `line-directives-only`: line info directives only, (For the nvptx* targets this enables [profiling](https://reviews.llvm.org/D46061), but on other targets the behavior is unspecified). -* `line-tables-only`: line tables only, (Generates the minimal amount of debug info for backtraces with filename/line number info, but not anything else, i.e. variable or function parameter info). -* `1` or `limited`: debug info without type information. +* `line-directives-only`: line info directives only. For the nvptx* targets this enables [profiling](https://reviews.llvm.org/D46061). For other use cases, `line-tables-only` is the better, more compatible choice. +* `line-tables-only`: line tables only. Generates the minimal amount of debug info for backtraces with filename/line number info, but not anything else, i.e. no variable or function parameter info. +* `1` or `limited`: debug info without type or variable-level information. * `2` or `full`: full debug info. Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`. From 0b5f9ac73e087b3728f0fcf53d541d4e80773732 Mon Sep 17 00:00:00 2001 From: klensy Date: Sun, 2 Apr 2023 15:20:00 +0300 Subject: [PATCH 091/267] replace deprecated LLVMSetCurrentDebugLocation with LLVMSetCurrentDebugLocation2 --- compiler/rustc_codegen_llvm/src/debuginfo/mod.rs | 3 +-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 5392534cfcb7..980eb54d1239 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -209,8 +209,7 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) { unsafe { - let dbg_loc_as_llval = llvm::LLVMRustMetadataAsValue(self.cx().llcx, dbg_loc); - llvm::LLVMSetCurrentDebugLocation(self.llbuilder, dbg_loc_as_llval); + llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, dbg_loc); } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 0d63e634ad88..a91edd805585 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1250,7 +1250,7 @@ extern "C" { pub fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>); // Metadata - pub fn LLVMSetCurrentDebugLocation<'a>(Builder: &Builder<'a>, L: &'a Value); + pub fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: &'a Metadata); // Terminators pub fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value; From 7d6181e4d8e25d83d2fe6b868a313ff9942466cc Mon Sep 17 00:00:00 2001 From: klensy Date: Sun, 2 Apr 2023 17:11:41 +0300 Subject: [PATCH 092/267] add bunch of fixmes: currently there exist some functions that accept LLVMValueRef, some that accept LLVMMetadataRef, and replacing one with another not always possible without explicit convertion --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 8 ++++++++ compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index a91edd805585..0ec209c8d437 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1072,7 +1072,13 @@ extern "C" { pub fn LLVMGetPoison(Ty: &Type) -> &Value; // Operations on metadata + // FIXME: deprecated, replace with LLVMMDStringInContext2 pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value; + + // LLVMMDStringInContext but don't own string + pub fn LLVMMDStringInContext2(C: &Context, Str: *const c_char, SLen: size_t) -> &Metadata; + + // FIXME: deprecated, replace with LLVMMDNodeInContext2 pub fn LLVMMDNodeInContext<'a>( C: &'a Context, Vals: *const &'a Value, @@ -1111,6 +1117,8 @@ extern "C" { Packed: Bool, ) -> &'a Value; + // FIXME: replace with LLVMConstArray2 + // https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc pub fn LLVMConstArray<'a>( ElementTy: &'a Type, ConstantVals: *const &'a Value, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index e3493caaaf74..be8c960b864d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1150,6 +1150,8 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, } // LLVMArrayType function does not support 64-bit ElementCount +// FIXME: replace with LLVMArrayType2 +// https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, uint64_t ElementCount) { return wrap(ArrayType::get(unwrap(ElementTy), ElementCount)); From c53a9faa6fdcdf8776646e837272ea0a85bf8179 Mon Sep 17 00:00:00 2001 From: klensy Date: Sun, 2 Apr 2023 17:52:38 +0300 Subject: [PATCH 093/267] replace LLVMRustMetadataAsValue with LLVMMetadataAsValue --- compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index e2a592d851a8..78197ca8529a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -882,7 +882,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( if tcx.sess.opts.unstable_opts.profile { let cu_desc_metadata = - llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata); + llvm::LLVMMetadataAsValue(debug_context.llcontext, unit_metadata); let default_gcda_path = &output_filenames.with_extension("gcda"); let gcda_path = tcx.sess.opts.unstable_opts.profile_emit.as_ref().unwrap_or(default_gcda_path); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 0ec209c8d437..9b69af4fa037 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1916,7 +1916,7 @@ extern "C" { ); pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool; - pub fn LLVMRustMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; + pub fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index be8c960b864d..b921573d1d2e 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -750,10 +750,6 @@ extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name, return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr; } -extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) { - return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD))); -} - extern "C" void LLVMRustGlobalAddMetadata( LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) { unwrap(Global)->addMetadata(Kind, *unwrap(MD)); From 076116bb4ca84801e5f513fc7cf280c55f32e8c4 Mon Sep 17 00:00:00 2001 From: klensy Date: Sun, 2 Apr 2023 18:26:48 +0300 Subject: [PATCH 094/267] replace LLVMRustAppendModuleInlineAsm with LLVMAppendModuleInlineAsm, LLVMRustMetadataTypeInContext with LLVMMetadataTypeInContext --- compiler/rustc_codegen_llvm/src/asm.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 4 ++-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 4 ++-- compiler/rustc_codegen_llvm/src/type_.rs | 2 +- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 9 --------- 5 files changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index d9f8170a3cff..e7668341eb6e 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -381,7 +381,7 @@ impl<'tcx> AsmMethods<'tcx> for CodegenCx<'_, 'tcx> { } unsafe { - llvm::LLVMRustAppendModuleInlineAsm( + llvm::LLVMAppendModuleInlineAsm( self.llmod, template_str.as_ptr().cast(), template_str.len(), diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index fb563f70ed09..7136f750f39d 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -904,9 +904,9 @@ unsafe fn embed_bitcode( // We need custom section flags, so emit module-level inline assembly. let section_flags = if cgcx.is_pe_coff { "n" } else { "e" }; let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode); - llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); + llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes()); - llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); + llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 9b69af4fa037..5e1798a48665 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1006,7 +1006,7 @@ extern "C" { pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char); /// See Module::setModuleInlineAsm. - pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char, AsmLen: size_t); + pub fn LLVMAppendModuleInlineAsm(M: &Module, Asm: *const c_char, Len: size_t); /// See llvm::LLVMTypeKind::getTypeID. pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind; @@ -1053,7 +1053,7 @@ extern "C" { // Operations on other types pub fn LLVMVoidTypeInContext(C: &Context) -> &Type; - pub fn LLVMRustMetadataTypeInContext(C: &Context) -> &Type; + pub fn LLVMMetadataTypeInContext(C: &Context) -> &Type; // Operations on all values pub fn LLVMTypeOf(Val: &Value) -> &Type; diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index ff111d96f840..bef4647f2078 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -53,7 +53,7 @@ impl<'ll> CodegenCx<'ll, '_> { } pub(crate) fn type_metadata(&self) -> &'ll Type { - unsafe { llvm::LLVMRustMetadataTypeInContext(self.llcx) } + unsafe { llvm::LLVMMetadataTypeInContext(self.llcx) } } ///x Creates an integer type with the given number of bits, e.g., i24 diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index b921573d1d2e..27f8c7a4a6d3 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -152,10 +152,6 @@ LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) { nullptr)); } -extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) { - return wrap(Type::getMetadataTy(*unwrap(C))); -} - static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { switch (Kind) { case AlwaysInline: @@ -480,11 +476,6 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, #endif } -extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, - size_t AsmLen) { - unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen)); -} - typedef DIBuilder *LLVMRustDIBuilderRef; template DIT *unwrapDIPtr(LLVMMetadataRef Ref) { From cc77ae07a9ee7c3a56e73e801d1db68fc6ed49dc Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 3 Apr 2023 15:12:21 +0300 Subject: [PATCH 095/267] Use existing llvm methods, instead of rust wrappers for: LLVMRustBuildCleanupPad -> LLVMBuildCleanupPad LLVMRustBuildCleanupRet -> LLVMBuildCleanupRet LLVMRustBuildCatchPad -> LLVMBuildCatchPad LLVMRustBuildCatchRet -> LLVMBuildCatchRet LLVMRustBuildCatchSwitch -> LLVMBuildCatchSwitch --- compiler/rustc_codegen_llvm/src/builder.rs | 15 +++--- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 20 ++++---- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 49 ------------------- 3 files changed, 17 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 63e8a67db53e..6290452315b4 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1001,11 +1001,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> { let name = cstr!("cleanuppad"); let ret = unsafe { - llvm::LLVMRustBuildCleanupPad( + llvm::LLVMBuildCleanupPad( self.llbuilder, parent, - args.len() as c_uint, args.as_ptr(), + args.len() as c_uint, name.as_ptr(), ) }; @@ -1014,7 +1014,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn cleanup_ret(&mut self, funclet: &Funclet<'ll>, unwind: Option<&'ll BasicBlock>) { unsafe { - llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) + llvm::LLVMBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) .expect("LLVM does not have support for cleanupret"); } } @@ -1022,11 +1022,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> { let name = cstr!("catchpad"); let ret = unsafe { - llvm::LLVMRustBuildCatchPad( + llvm::LLVMBuildCatchPad( self.llbuilder, parent, - args.len() as c_uint, args.as_ptr(), + args.len() as c_uint, name.as_ptr(), ) }; @@ -1041,7 +1041,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) -> &'ll Value { let name = cstr!("catchswitch"); let ret = unsafe { - llvm::LLVMRustBuildCatchSwitch( + llvm::LLVMBuildCatchSwitch( self.llbuilder, parent, unwind, @@ -1376,8 +1376,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value { - let ret = - unsafe { llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) }; + let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) }; ret.expect("LLVM does not have support for catchret") } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 5e1798a48665..727a3f90efaa 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1298,34 +1298,34 @@ extern "C" { pub fn LLVMBuildResume<'a>(B: &Builder<'a>, Exn: &'a Value) -> &'a Value; pub fn LLVMBuildUnreachable<'a>(B: &Builder<'a>) -> &'a Value; - pub fn LLVMRustBuildCleanupPad<'a>( + pub fn LLVMBuildCleanupPad<'a>( B: &Builder<'a>, ParentPad: Option<&'a Value>, - ArgCnt: c_uint, Args: *const &'a Value, + NumArgs: c_uint, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCleanupRet<'a>( + pub fn LLVMBuildCleanupRet<'a>( B: &Builder<'a>, CleanupPad: &'a Value, - UnwindBB: Option<&'a BasicBlock>, + BB: Option<&'a BasicBlock>, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchPad<'a>( + pub fn LLVMBuildCatchPad<'a>( B: &Builder<'a>, ParentPad: &'a Value, - ArgCnt: c_uint, Args: *const &'a Value, + NumArgs: c_uint, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchRet<'a>( + pub fn LLVMBuildCatchRet<'a>( B: &Builder<'a>, - Pad: &'a Value, + CatchPad: &'a Value, BB: &'a BasicBlock, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchSwitch<'a>( + pub fn LLVMBuildCatchSwitch<'a>( Builder: &Builder<'a>, ParentPad: Option<&'a Value>, - BB: Option<&'a BasicBlock>, + UnwindBB: Option<&'a BasicBlock>, NumHandlers: c_uint, Name: *const c_char, ) -> Option<&'a Value>; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 27f8c7a4a6d3..ea45b30351b2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1394,55 +1394,6 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, return true; } -extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B, - LLVMValueRef ParentPad, - unsigned ArgCount, - LLVMValueRef *LLArgs, - const char *Name) { - Value **Args = unwrap(LLArgs); - if (ParentPad == nullptr) { - Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); - ParentPad = wrap(Constant::getNullValue(Ty)); - } - return wrap(unwrap(B)->CreateCleanupPad( - unwrap(ParentPad), ArrayRef(Args, ArgCount), Name)); -} - -extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B, - LLVMValueRef CleanupPad, - LLVMBasicBlockRef UnwindBB) { - CleanupPadInst *Inst = cast(unwrap(CleanupPad)); - return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB))); -} - -extern "C" LLVMValueRef -LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad, - unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) { - Value **Args = unwrap(LLArgs); - return wrap(unwrap(B)->CreateCatchPad( - unwrap(ParentPad), ArrayRef(Args, ArgCount), Name)); -} - -extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B, - LLVMValueRef Pad, - LLVMBasicBlockRef BB) { - return wrap(unwrap(B)->CreateCatchRet(cast(unwrap(Pad)), - unwrap(BB))); -} - -extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B, - LLVMValueRef ParentPad, - LLVMBasicBlockRef BB, - unsigned NumHandlers, - const char *Name) { - if (ParentPad == nullptr) { - Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); - ParentPad = wrap(Constant::getNullValue(Ty)); - } - return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB), - NumHandlers, Name)); -} - extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef, LLVMBasicBlockRef Handler) { Value *CatchSwitch = unwrap(CatchSwitchRef); From f41e711b7eb3831ca986aca4b70e627703704a8f Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 3 Apr 2023 16:30:34 +0300 Subject: [PATCH 096/267] replace LLVMRustBuildIntCast -> LLVMBuildIntCast2 LLVMRustAddHandler -> LLVMAddHandler --- compiler/rustc_codegen_llvm/src/builder.rs | 4 ++-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 5 +++-- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 13 +------------ 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 6290452315b4..74f3a662d602 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -841,7 +841,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { - unsafe { llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) } + unsafe { llvm::LLVMBuildIntCast2(self.llbuilder, val, dest_ty, is_signed, UNNAMED) } } fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { @@ -1052,7 +1052,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let ret = ret.expect("LLVM does not have support for catchswitch"); for handler in handlers { unsafe { - llvm::LLVMRustAddHandler(ret, handler); + llvm::LLVMAddHandler(ret, handler); } } ret diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 727a3f90efaa..836fa8779f28 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1329,7 +1329,7 @@ extern "C" { NumHandlers: c_uint, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustAddHandler<'a>(CatchSwitch: &'a Value, Handler: &'a BasicBlock); + pub fn LLVMAddHandler<'a>(CatchSwitch: &'a Value, Dest: &'a BasicBlock); pub fn LLVMSetPersonalityFn<'a>(Func: &'a Value, Pers: &'a Value); // Add a case to the switch instruction @@ -1623,11 +1623,12 @@ extern "C" { DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMRustBuildIntCast<'a>( + pub fn LLVMBuildIntCast2<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, IsSigned: bool, + Name: *const c_char, ) -> &'a Value; // Comparisons diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index ea45b30351b2..578bc3ea6421 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1394,12 +1394,6 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, return true; } -extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef, - LLVMBasicBlockRef Handler) { - Value *CatchSwitch = unwrap(CatchSwitchRef); - cast(CatchSwitch)->addHandler(unwrap(Handler)); -} - extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, LLVMValueRef *Inputs, unsigned NumInputs) { @@ -1564,6 +1558,7 @@ extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMSetLinkage(V, fromRust(RustLinkage)); } +// FIXME: replace with LLVMConstInBoundsGEP2 when bumped minimal version to llvm-14 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal, LLVMValueRef *ConstantIndices, @@ -1641,12 +1636,6 @@ extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) { return toRust(LLVMGetVisibility(V)); } -// Oh hey, a binding that makes sense for once? (because LLVM’s own do not) -extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val, - LLVMTypeRef DestTy, bool isSigned) { - return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, "")); -} - extern "C" void LLVMRustSetVisibility(LLVMValueRef V, LLVMRustVisibility RustVisibility) { LLVMSetVisibility(V, fromRust(RustVisibility)); From ebde2ab363ea4cfff4fbb58ef821f3bcebc351a5 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 3 Apr 2023 21:30:13 +0100 Subject: [PATCH 097/267] Deny `use`ing tool paths --- compiler/rustc_resolve/messages.ftl | 4 ++++ compiler/rustc_resolve/src/errors.rs | 9 +++++++++ compiler/rustc_resolve/src/ident.rs | 18 +++++++----------- tests/ui/resolve/tool-import.rs | 8 ++++++++ tests/ui/resolve/tool-import.stderr | 9 +++++++++ 5 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 tests/ui/resolve/tool-import.rs create mode 100644 tests/ui/resolve/tool-import.stderr diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 817bb83ed786..2199ceee5326 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -207,5 +207,9 @@ resolve_expected_found = resolve_indeterminate = cannot determine resolution for the visibility +resolve_tool_module_imported = + cannot use a tool module through an import + .note = the tool module imported here + resolve_module_only = visibility must resolve to a module diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 867363f4246a..07aaaa1eb7f6 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -469,6 +469,15 @@ pub(crate) struct ExpectedFound { #[diag(resolve_indeterminate, code = "E0578")] pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span); +#[derive(Diagnostic)] +#[diag(resolve_tool_module_imported)] +pub(crate) struct ToolModuleImported { + #[primary_span] + pub(crate) span: Span, + #[note] + pub(crate) import: Span, +} + #[derive(Diagnostic)] #[diag(resolve_module_only)] pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 06206efb9abd..2467e604a15b 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -17,7 +17,7 @@ use crate::late::{ ConstantHasGenerics, ConstantItemKind, HasGenericParams, PathSource, Rib, RibKind, }; use crate::macros::{sub_namespace_match, MacroRulesScope}; -use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize}; +use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize}; use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res}; use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak}; @@ -1357,7 +1357,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - let is_last = i == path.len() - 1; + let is_last = i + 1 == path.len(); let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; let name = ident.name; @@ -1494,16 +1494,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(next_module) = binding.module() { module = Some(ModuleOrUniformRoot::Module(next_module)); record_segment_res(self, res); - } else if res == Res::ToolMod && i + 1 != path.len() { + } else if res == Res::ToolMod && !is_last && opt_ns.is_some() { if binding.is_import() { - self.tcx - .sess - .struct_span_err( - ident.span, - "cannot use a tool module through an import", - ) - .span_note(binding.span, "the tool module imported here") - .emit(); + self.tcx.sess.emit_err(errors::ToolModuleImported { + span: ident.span, + import: binding.span, + }); } let res = Res::NonMacroAttr(NonMacroAttrKind::Tool); return PathResult::NonModule(PartialRes::new(res)); diff --git a/tests/ui/resolve/tool-import.rs b/tests/ui/resolve/tool-import.rs new file mode 100644 index 000000000000..971993332f54 --- /dev/null +++ b/tests/ui/resolve/tool-import.rs @@ -0,0 +1,8 @@ +// edition: 2018 + +use clippy::time::Instant; +//~^ `clippy` is a tool module + +fn main() { + Instant::now(); +} diff --git a/tests/ui/resolve/tool-import.stderr b/tests/ui/resolve/tool-import.stderr new file mode 100644 index 000000000000..d3bdfc93d492 --- /dev/null +++ b/tests/ui/resolve/tool-import.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: `clippy` is a tool module, not a module + --> $DIR/tool-import.rs:3:5 + | +LL | use clippy::time::Instant; + | ^^^^^^ `clippy` is a tool module, not a module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. From 4bebdd7104c41fb1a32e2d9588f64874dd5a484f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 12:34:05 +0000 Subject: [PATCH 098/267] box a bunch of large types --- compiler/rustc_ast/src/ast.rs | 16 +++---- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 6 +-- compiler/rustc_ast_lowering/src/item.rs | 8 ++-- .../rustc_ast_passes/src/ast_validation.rs | 6 +-- .../rustc_ast_pretty/src/pprust/state/item.rs | 6 +-- .../src/global_allocator.rs | 4 +- compiler/rustc_builtin_macros/src/test.rs | 48 ++++++++++--------- compiler/rustc_expand/src/build.rs | 4 +- compiler/rustc_lint/src/unused.rs | 4 +- compiler/rustc_parse/src/parser/item.rs | 12 ++--- .../rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/late.rs | 8 ++-- .../src/redundant_static_lifetimes.rs | 4 +- .../clippy/clippy_utils/src/ast_utils.rs | 6 +-- src/tools/rustfmt/src/items.rs | 26 +++++----- 16 files changed, 83 insertions(+), 79 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 985b66e6bea6..14c190daf351 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2917,11 +2917,11 @@ pub enum ItemKind { /// A static item (`static`). /// /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. - Static(Static), + Static(Box), /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. - Const(ConstItem), + Const(Box), /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. @@ -3037,7 +3037,7 @@ pub type AssocItem = Item; pub enum AssocItemKind { /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. /// If `def` is parsed, then the constant is provided, and otherwise required. - Const(ConstItem), + Const(Box), /// An associated function. Fn(Box), /// An associated type. @@ -3049,7 +3049,7 @@ pub enum AssocItemKind { impl AssocItemKind { pub fn defaultness(&self) -> Defaultness { match *self { - Self::Const(ConstItem { defaultness, .. }) + Self::Const(box ConstItem { defaultness, .. }) | Self::Fn(box Fn { defaultness, .. }) | Self::Type(box TyAlias { defaultness, .. }) => defaultness, Self::MacCall(..) => Defaultness::Final, @@ -3099,7 +3099,7 @@ impl From for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { ForeignItemKind::Static(a, b, c) => { - ItemKind::Static(Static { ty: a, mutability: b, expr: c }) + ItemKind::Static(Static { ty: a, mutability: b, expr: c }.into()) } ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), @@ -3113,7 +3113,7 @@ impl TryFrom for ForeignItemKind { fn try_from(item_kind: ItemKind) -> Result { Ok(match item_kind { - ItemKind::Static(Static { ty: a, mutability: b, expr: c }) => { + ItemKind::Static(box Static { ty: a, mutability: b, expr: c }) => { ForeignItemKind::Static(a, b, c) } ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind), @@ -3132,8 +3132,8 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(AssocItem, 104); - static_assert_size!(AssocItemKind, 32); + static_assert_size!(AssocItem, 88); + static_assert_size!(AssocItemKind, 16); static_assert_size!(Attribute, 32); static_assert_size!(Block, 32); static_assert_size!(Expr, 72); diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index e99a2fee67c8..4d569e0fb94c 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1030,7 +1030,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { match kind { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(Static { ty, mutability: _, expr }) => { + ItemKind::Static(box Static { ty, mutability: _, expr }) => { vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 55a17efe4160..970bda58f350 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -305,8 +305,8 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { match &item.kind { ItemKind::ExternCrate(_) => {} ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false), - ItemKind::Static(Static { ty, mutability: _, expr }) - | ItemKind::Const(ConstItem { ty, expr, .. }) => { + ItemKind::Static(box Static { ty, mutability: _, expr }) + | ItemKind::Const(box ConstItem { ty, expr, .. }) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } @@ -675,7 +675,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, visitor.visit_ident(ident); walk_list!(visitor, visit_attribute, attrs); match kind { - AssocItemKind::Const(ConstItem { ty, expr, .. }) => { + AssocItemKind::Const(box ConstItem { ty, expr, .. }) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b41bb5017e51..803dbbffbd86 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -229,11 +229,11 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) } - ItemKind::Static(ast::Static { ty: t, mutability: m, expr: e }) => { + ItemKind::Static(box ast::Static { ty: t, mutability: m, expr: e }) => { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); hir::ItemKind::Static(ty, *m, body_id) } - ItemKind::Const(ast::ConstItem { ty, expr, .. }) => { + ItemKind::Const(box ast::ConstItem { ty, expr, .. }) => { let (ty, body_id) = self.lower_const_item(ty, span, expr.as_deref()); hir::ItemKind::Const(ty, body_id) } @@ -708,7 +708,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let trait_item_def_id = hir_id.expect_owner(); let (generics, kind, has_default) = match &i.kind { - AssocItemKind::Const(ConstItem { ty, expr, .. }) => { + AssocItemKind::Const(box ConstItem { ty, expr, .. }) => { let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = expr.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); @@ -809,7 +809,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_attrs(hir_id, &i.attrs); let (generics, kind) = match &i.kind { - AssocItemKind::Const(ConstItem { ty, expr, .. }) => { + AssocItemKind::Const(box ConstItem { ty, expr, .. }) => { let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); ( diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 43d086ec52d8..431a569c1e0d 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -983,14 +983,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.err_handler().emit_err(errors::FieldlessUnion { span: item.span }); } } - ItemKind::Const(ConstItem { defaultness, expr: None, .. }) => { + ItemKind::Const(box ConstItem { defaultness, expr: None, .. }) => { self.check_defaultness(item.span, *defaultness); self.session.emit_err(errors::ConstWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), }); } - ItemKind::Static(Static { expr: None, .. }) => { + ItemKind::Static(box Static { expr: None, .. }) => { self.session.emit_err(errors::StaticWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), @@ -1259,7 +1259,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if ctxt == AssocCtxt::Impl { match &item.kind { - AssocItemKind::Const(ConstItem { expr: None, .. }) => { + AssocItemKind::Const(box ConstItem { expr: None, .. }) => { self.session.emit_err(errors::AssocConstWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 92b9c8fd766a..e2d133eb233a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -157,7 +157,7 @@ impl<'a> State<'a> { self.print_use_tree(tree); self.word(";"); } - ast::ItemKind::Static(Static { ty, mutability: mutbl, expr: body }) => { + ast::ItemKind::Static(box Static { ty, mutability: mutbl, expr: body }) => { let def = ast::Defaultness::Final; self.print_item_const( item.ident, @@ -168,7 +168,7 @@ impl<'a> State<'a> { def, ); } - ast::ItemKind::Const(ast::ConstItem { defaultness, ty, expr }) => { + ast::ItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => { self.print_item_const( item.ident, None, @@ -515,7 +515,7 @@ impl<'a> State<'a> { ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs); } - ast::AssocItemKind::Const(ast::ConstItem { defaultness, ty, expr }) => { + ast::AssocItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => { self.print_item_const(ident, None, ty, expr.as_deref(), vis, *defaultness); } ast::AssocItemKind::Type(box ast::TyAlias { diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index f26e2572088b..34361a6d868e 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -25,12 +25,12 @@ pub fn expand( // FIXME - if we get deref patterns, use them to reduce duplication here let (item, is_stmt, ty_span) = if let Annotatable::Item(item) = &item - && let ItemKind::Static(ast::Static { ty, ..}) = &item.kind + && let ItemKind::Static(box ast::Static { ty, ..}) = &item.kind { (item, false, ecx.with_def_site_ctxt(ty.span)) } else if let Annotatable::Stmt(stmt) = &item && let StmtKind::Item(item) = &stmt.kind - && let ItemKind::Static(ast::Static { ty, ..}) = &item.kind + && let ItemKind::Static(box ast::Static { ty, ..}) = &item.kind { (item, true, ecx.with_def_site_ctxt(ty.span)) } else { diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index ced341e54130..a76ed4ee6cee 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -254,25 +254,27 @@ pub fn expand_test_or_bench( let location_info = get_location_info(cx, &item); - let mut test_const = cx.item( - sp, - Ident::new(item.ident.name, sp), - thin_vec![ - // #[cfg(test)] - cx.attr_nested_word(sym::cfg, sym::test, attr_sp), - // #[rustc_test_marker = "test_case_sort_key"] - cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp), - ], - // const $ident: test::TestDescAndFn = - ast::ItemKind::Const(ast::ConstItem { - defaultness: ast::Defaultness::Final, - ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), - // test::TestDescAndFn { - expr: Some( - cx.expr_struct( - sp, - test_path("TestDescAndFn"), - thin_vec![ + let mut test_const = + cx.item( + sp, + Ident::new(item.ident.name, sp), + thin_vec![ + // #[cfg(test)] + cx.attr_nested_word(sym::cfg, sym::test, attr_sp), + // #[rustc_test_marker = "test_case_sort_key"] + cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp), + ], + // const $ident: test::TestDescAndFn = + ast::ItemKind::Const( + ast::ConstItem { + defaultness: ast::Defaultness::Final, + ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), + // test::TestDescAndFn { + expr: Some( + cx.expr_struct( + sp, + test_path("TestDescAndFn"), + thin_vec![ // desc: test::TestDesc { field( "desc", @@ -359,10 +361,12 @@ pub fn expand_test_or_bench( // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...) field("testfn", test_fn), // } ], - ), // } + ), // } + ), + } + .into(), ), - }), - ); + ); test_const = test_const.map(|mut tc| { tc.vis.kind = ast::VisibilityKind::Public; tc diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 39fed9fdd0d4..59c588b39554 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -627,7 +627,7 @@ impl<'a> ExtCtxt<'a> { span, name, AttrVec::new(), - ast::ItemKind::Static(ast::Static { ty, mutability, expr: Some(expr) }), + ast::ItemKind::Static(ast::Static { ty, mutability, expr: Some(expr) }.into()), ) } @@ -643,7 +643,7 @@ impl<'a> ExtCtxt<'a> { span, name, AttrVec::new(), - ast::ItemKind::Const(ast::ConstItem { defaultness, ty, expr: Some(expr) }), + ast::ItemKind::Const(ast::ConstItem { defaultness, ty, expr: Some(expr) }.into()), ) } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index d920e237508c..c856e973e5c8 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -805,8 +805,8 @@ trait UnusedDelimLint { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - if let Const(ast::ConstItem { expr: Some(expr), .. }) - | Static(ast::Static { expr: Some(expr), .. }) = &item.kind + if let Const(box ast::ConstItem { expr: Some(expr), .. }) + | Static(box ast::Static { expr: Some(expr), .. }) = &item.kind { self.check_unused_delims_expr( cx, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index f6422d30ba50..66fa9fb38d42 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -228,7 +228,7 @@ impl<'a> Parser<'a> { self.bump(); // `static` let m = self.parse_mutability(); let (ident, ty, expr) = self.parse_item_global(Some(m))?; - (ident, ItemKind::Static(Static { ty, mutability: m, expr })) + (ident, ItemKind::Static(Box::new(Static { ty, mutability: m, expr }))) } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { @@ -237,7 +237,7 @@ impl<'a> Parser<'a> { } else { self.recover_const_mut(const_span); let (ident, ty, expr) = self.parse_item_global(None)?; - (ident, ItemKind::Const(ConstItem { defaultness: def_(), ty, expr })) + (ident, ItemKind::Const(Box::new(ConstItem { defaultness: def_(), ty, expr }))) } } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() { // TRAIT ITEM @@ -863,13 +863,13 @@ impl<'a> Parser<'a> { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Static(Static { ty, mutability: _, expr }) => { + ItemKind::Static(box Static { ty, mutability: _, expr }) => { self.sess.emit_err(errors::AssociatedStaticItemNotAllowed { span }); - AssocItemKind::Const(ConstItem { + AssocItemKind::Const(Box::new(ConstItem { defaultness: Defaultness::Final, ty, expr, - }) + })) } _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), }, @@ -1119,7 +1119,7 @@ impl<'a> Parser<'a> { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Const(ConstItem { ty, expr, .. }) => { + ItemKind::Const(box ConstItem { ty, expr, .. }) => { self.sess.emit_err(errors::ExternItemCannotBeConst { ident_span: ident.span, const_span: span.with_hi(ident.span.lo()), diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3a79ddca2eb4..10d282a21a7c 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -688,7 +688,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // These items live in the value namespace. - ItemKind::Static(ast::Static { mutability, .. }) => { + ItemKind::Static(box ast::Static { mutability, .. }) => { let res = Res::Def(DefKind::Static(mutability), def_id); self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 735644ec8d51..d38bfc62abd9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2346,8 +2346,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }); } - ItemKind::Static(ast::Static { ref ty, ref expr, .. }) - | ItemKind::Const(ast::ConstItem { ref ty, ref expr, .. }) => { + ItemKind::Static(box ast::Static { ref ty, ref expr, .. }) + | ItemKind::Const(box ast::ConstItem { ref ty, ref expr, .. }) => { self.with_static_rib(|this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { this.visit_ty(ty); @@ -2625,7 +2625,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { for item in trait_items { self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); match &item.kind { - AssocItemKind::Const(ast::ConstItem { ty, expr, .. }) => { + AssocItemKind::Const(box ast::ConstItem { ty, expr, .. }) => { self.visit_ty(ty); // Only impose the restrictions of `ConstRibKind` for an // actual constant expression in a provided default. @@ -2800,7 +2800,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { use crate::ResolutionError::*; self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis))); match &item.kind { - AssocItemKind::Const(ast::ConstItem { ty, expr, .. }) => { + AssocItemKind::Const(box ast::ConstItem { ty, expr, .. }) => { debug!("resolve_implementation AssocItemKind::Const"); // If this is a trait impl, ensure the const // exists in trait diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index d41f79f81315..aa47f3aed54d 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -100,13 +100,13 @@ impl EarlyLintPass for RedundantStaticLifetimes { } if !item.span.from_expansion() { - if let ItemKind::Const(ConstItem { ty: ref var_type, .. }) = item.kind { + if let ItemKind::Const(box ConstItem { ty: ref var_type, .. }) = item.kind { Self::visit_type(var_type, cx, "constants have by default a `'static` lifetime"); // Don't check associated consts because `'static` cannot be elided on those (issue // #2438) } - if let ItemKind::Static(Static{ ty: ref var_type,.. }) = item.kind { + if let ItemKind::Static(box Static { ty: ref var_type,.. }) = item.kind { Self::visit_type(var_type, cx, "statics have by default a `'static` lifetime"); } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index be841098dba3..0d2a7440c465 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -286,8 +286,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { match (l, r) { (ExternCrate(l), ExternCrate(r)) => l == r, (Use(l), Use(r)) => eq_use_tree(l, r), - (Static(ast::Static{ ty: lt, mutability: lm, expr: le}), Static(ast::Static { ty: rt, mutability: rm, expr: re})) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), - (Const(ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(ast::ConstItem { defaultness: rd, ty: rt, expr: re} )) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Static(box ast::Static{ ty: lt, mutability: lm, expr: le}), Static(box ast::Static { ty: rt, mutability: rm, expr: re})) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Const(box ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(box ast::ConstItem { defaultness: rd, ty: rt, expr: re} )) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { defaultness: ld, @@ -451,7 +451,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { use AssocItemKind::*; match (l, r) { - (Const(ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(ast::ConstItem { defaultness: rd, ty: rt, expr: re})) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Const(box ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(box ast::ConstItem { defaultness: rd, ty: rt, expr: re})) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { defaultness: ld, diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 0dc8a4e937f2..43779cfaecd3 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1804,13 +1804,15 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (defaultness, prefix, ty, mutability, expr) = match item.kind { - ast::ItemKind::Static(ast::Static { ref ty, mutability, ref expr}) => { - (None, "static", ty, mutability, expr) - } - ast::ItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => { - (Some(defaultness), "const", ty, ast::Mutability::Not, expr) - } + let (defaultness, prefix, ty, mutability, expr) = match &item.kind { + ast::ItemKind::Static(s) => (None, "static", &s.ty, s.mutability, &s.expr), + ast::ItemKind::Const(c) => ( + Some(c.defaultness), + "const", + &c.ty, + ast::Mutability::Not, + &c.expr, + ), _ => unreachable!(), }; StaticParts { @@ -1826,10 +1828,8 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { - let (defaultness, ty, expr_opt) = match ti.kind { - ast::AssocItemKind::Const(ast::ConstItem {defaultness, ref ty, ref expr}) => { - (defaultness, ty, expr) - } + let (defaultness, ty, expr_opt) = match &ti.kind { + ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr), _ => unreachable!(), }; StaticParts { @@ -1845,8 +1845,8 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { - let (defaultness, ty, expr) = match ii.kind { - ast::AssocItemKind::Const(ast::ConstItem { defaultness, ref ty, ref expr}) => (defaultness, ty, expr), + let (defaultness, ty, expr) = match &ii.kind { + ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr), _ => unreachable!(), }; StaticParts { From 72ef85d83e3095222dc83e0c03531e5150d074c9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 4 Apr 2023 13:23:33 +0000 Subject: [PATCH 099/267] Don't collect return-position impl traits for documentation --- src/librustdoc/visit_ast.rs | 10 +++++++++- tests/rustdoc/async-fn-opaque-item.rs | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc/async-fn-opaque-item.rs diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 060062db0027..c959bb3701ab 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -421,12 +421,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::TyAlias(..) - | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias, .. + }) | hir::ItemKind::Static(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { self.add_to_current_mod(item, renamed, import_id); } + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::AsyncFn(_) | hir::OpaqueTyOrigin::FnReturn(_), + .. + }) => { + // return-position impl traits are never nameable, and should never be documented. + } hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. diff --git a/tests/rustdoc/async-fn-opaque-item.rs b/tests/rustdoc/async-fn-opaque-item.rs new file mode 100644 index 000000000000..a73e84f3fdc4 --- /dev/null +++ b/tests/rustdoc/async-fn-opaque-item.rs @@ -0,0 +1,15 @@ +// compile-flags: --document-private-items --crate-type=lib +// edition: 2021 + +// Issue 109931 -- test against accidentally documenting the `impl Future` +// that comes from an async fn desugaring. + +// Check that we don't document an unnamed opaque type +// @!has async_fn_opaque_item/opaque..html + +// Checking there is only a "Functions" header and no "Opaque types". +// @has async_fn_opaque_item/index.html +// @count - '//*[@class="small-section-header"]' 1 +// @has - '//*[@class="small-section-header"]' 'Functions' + +pub async fn test() {} From 6f9b98857851cc79750dacd025b2e8bab5773470 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 4 Apr 2023 16:35:36 +0200 Subject: [PATCH 100/267] Move scrollbar on the
element rather than only on the code block to improve UX --- src/librustdoc/html/static/css/rustdoc.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 933a44c5aa78..726394d8348e 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -392,6 +392,7 @@ img { overflow-x: hidden; /* The sidebar is by default hidden */ overflow-y: hidden; + z-index: 1; } .sidebar, .mobile-topbar, .sidebar-menu-toggle, @@ -535,6 +536,9 @@ ul.block, .block li { .rustdoc .example-wrap > pre { margin: 0; flex-grow: 1; +} + +.rustdoc:not(.source) .example-wrap > pre { overflow: auto hidden; } From 8aef0c7926f18550d71346c570ed92b359cb73e9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 4 Apr 2023 16:35:53 +0200 Subject: [PATCH 101/267] Add GUI test for scrollbar position on source code page --- tests/rustdoc-gui/source-code-page-code-scroll.goml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/rustdoc-gui/source-code-page-code-scroll.goml diff --git a/tests/rustdoc-gui/source-code-page-code-scroll.goml b/tests/rustdoc-gui/source-code-page-code-scroll.goml new file mode 100644 index 000000000000..42f1da749e96 --- /dev/null +++ b/tests/rustdoc-gui/source-code-page-code-scroll.goml @@ -0,0 +1,8 @@ +// Checks that the scrollbar is visible on the page rather than the code block. +goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" +size: (800, 1000) +// "scrollWidth" should be superior than "clientWidth". +assert-property: ("body", {"scrollWidth": 1047, "clientWidth": 800}) + +// Both properties should be equal (ie, no scroll on the code block). +assert-property: (".example-wrap .rust", {"scrollWidth": 933, "clientWidth": 933}) From 373807a95cc427bb2672c96cb00ce71d8a5f4040 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Mar 2023 14:14:11 +0000 Subject: [PATCH 102/267] Rename `ast::Static` to `ast::StaticItem` to match `ast::ConstItem` --- compiler/rustc_ast/src/ast.rs | 8 +- compiler/rustc_ast/src/mut_visit.rs | 4 +- compiler/rustc_ast/src/visit.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 2 +- .../rustc_ast_passes/src/ast_validation.rs | 4 +- .../rustc_ast_pretty/src/pprust/state/item.rs | 4 +- .../src/global_allocator.rs | 4 +- compiler/rustc_expand/src/build.rs | 2 +- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 6 +- .../rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- .../src/redundant_static_lifetimes.rs | 4 +- .../clippy/clippy_utils/src/ast_utils.rs | 2 +- tests/ui/stats/hir-stats.stderr | 86 +++++++++---------- 15 files changed, 68 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 14c190daf351..fb9d71b52a8a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2891,7 +2891,7 @@ pub struct Fn { } #[derive(Clone, Encodable, Decodable, Debug)] -pub struct Static { +pub struct StaticItem { pub ty: P, pub mutability: Mutability, pub expr: Option>, @@ -2917,7 +2917,7 @@ pub enum ItemKind { /// A static item (`static`). /// /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. - Static(Box), + Static(Box), /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. @@ -3099,7 +3099,7 @@ impl From for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { ForeignItemKind::Static(a, b, c) => { - ItemKind::Static(Static { ty: a, mutability: b, expr: c }.into()) + ItemKind::Static(StaticItem { ty: a, mutability: b, expr: c }.into()) } ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), @@ -3113,7 +3113,7 @@ impl TryFrom for ForeignItemKind { fn try_from(item_kind: ItemKind) -> Result { Ok(match item_kind { - ItemKind::Static(box Static { ty: a, mutability: b, expr: c }) => { + ItemKind::Static(box StaticItem { ty: a, mutability: b, expr: c }) => { ForeignItemKind::Static(a, b, c) } ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4d569e0fb94c..2424073ae53a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -10,7 +10,7 @@ use crate::ptr::P; use crate::token::{self, Token}; use crate::tokenstream::*; -use crate::{ast::*, Static}; +use crate::{ast::*, StaticItem}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::sync::Lrc; @@ -1030,7 +1030,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { match kind { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(box Static { ty, mutability: _, expr }) => { + ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => { vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 970bda58f350..3b08467fde2b 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -13,7 +13,7 @@ //! instance, a walker looking for item names in a module will miss all of //! those that are created by the expansion of a macro. -use crate::{ast::*, Static}; +use crate::{ast::*, StaticItem}; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -305,7 +305,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { match &item.kind { ItemKind::ExternCrate(_) => {} ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false), - ItemKind::Static(box Static { ty, mutability: _, expr }) + ItemKind::Static(box StaticItem { ty, mutability: _, expr }) | ItemKind::Const(box ConstItem { ty, expr, .. }) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 803dbbffbd86..f89e254a2f54 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -229,7 +229,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) } - ItemKind::Static(box ast::Static { ty: t, mutability: m, expr: e }) => { + ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); hir::ItemKind::Static(ty, *m, body_id) } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 431a569c1e0d..236ebd04ae88 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -10,7 +10,7 @@ use itertools::{Either, Itertools}; use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; -use rustc_ast::{walk_list, Static}; +use rustc_ast::{walk_list, StaticItem}; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; use rustc_macros::Subdiagnostic; @@ -990,7 +990,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { replace_span: self.ending_semi_or_hi(item.span), }); } - ItemKind::Static(box Static { expr: None, .. }) => { + ItemKind::Static(box StaticItem { expr: None, .. }) => { self.session.emit_err(errors::StaticWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index e2d133eb233a..c465f8c948a8 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -2,7 +2,7 @@ use crate::pp::Breaks::Inconsistent; use crate::pprust::state::delimited::IterDelimited; use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; -use ast::Static; +use ast::StaticItem; use rustc_ast as ast; use rustc_ast::GenericBound; use rustc_ast::ModKind; @@ -157,7 +157,7 @@ impl<'a> State<'a> { self.print_use_tree(tree); self.word(";"); } - ast::ItemKind::Static(box Static { ty, mutability: mutbl, expr: body }) => { + ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => { let def = ast::Defaultness::Final; self.print_item_const( item.ident, diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 34361a6d868e..866cc5adbf3b 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -25,12 +25,12 @@ pub fn expand( // FIXME - if we get deref patterns, use them to reduce duplication here let (item, is_stmt, ty_span) = if let Annotatable::Item(item) = &item - && let ItemKind::Static(box ast::Static { ty, ..}) = &item.kind + && let ItemKind::Static(box ast::StaticItem { ty, ..}) = &item.kind { (item, false, ecx.with_def_site_ctxt(ty.span)) } else if let Annotatable::Stmt(stmt) = &item && let StmtKind::Item(item) = &stmt.kind - && let ItemKind::Static(box ast::Static { ty, ..}) = &item.kind + && let ItemKind::Static(box ast::StaticItem { ty, ..}) = &item.kind { (item, true, ecx.with_def_site_ctxt(ty.span)) } else { diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 59c588b39554..264f30fb10a1 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -627,7 +627,7 @@ impl<'a> ExtCtxt<'a> { span, name, AttrVec::new(), - ast::ItemKind::Static(ast::Static { ty, mutability, expr: Some(expr) }.into()), + ast::ItemKind::Static(ast::StaticItem { ty, mutability, expr: Some(expr) }.into()), ) } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index c856e973e5c8..ad328006051f 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -806,7 +806,7 @@ trait UnusedDelimLint { use ast::ItemKind::*; if let Const(box ast::ConstItem { expr: Some(expr), .. }) - | Static(box ast::Static { expr: Some(expr), .. }) = &item.kind + | Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind { self.check_unused_delims_expr( cx, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 66fa9fb38d42..6422b8ac1ba4 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -3,7 +3,7 @@ use crate::errors; use super::diagnostics::{dummy_arg, ConsumeClosingDelim}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; -use ast::Static; +use ast::StaticItem; use rustc_ast::ast::*; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, TokenKind}; @@ -228,7 +228,7 @@ impl<'a> Parser<'a> { self.bump(); // `static` let m = self.parse_mutability(); let (ident, ty, expr) = self.parse_item_global(Some(m))?; - (ident, ItemKind::Static(Box::new(Static { ty, mutability: m, expr }))) + (ident, ItemKind::Static(Box::new(StaticItem { ty, mutability: m, expr }))) } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { @@ -863,7 +863,7 @@ impl<'a> Parser<'a> { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Static(box Static { ty, mutability: _, expr }) => { + ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => { self.sess.emit_err(errors::AssociatedStaticItemNotAllowed { span }); AssocItemKind::Const(Box::new(ConstItem { defaultness: Defaultness::Final, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 10d282a21a7c..49c41470a151 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -688,7 +688,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // These items live in the value namespace. - ItemKind::Static(box ast::Static { mutability, .. }) => { + ItemKind::Static(box ast::StaticItem { mutability, .. }) => { let res = Res::Def(DefKind::Static(mutability), def_id); self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d38bfc62abd9..19f46d45af67 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2346,7 +2346,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }); } - ItemKind::Static(box ast::Static { ref ty, ref expr, .. }) + ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) | ItemKind::Const(box ast::ConstItem { ref ty, ref expr, .. }) => { self.with_static_rib(|this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index aa47f3aed54d..11b908e7e53d 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; -use rustc_ast::ast::{Item, ItemKind, Ty, TyKind, Static, ConstItem}; +use rustc_ast::ast::{Item, ItemKind, Ty, TyKind, StaticItem, ConstItem}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -106,7 +106,7 @@ impl EarlyLintPass for RedundantStaticLifetimes { // #2438) } - if let ItemKind::Static(box Static { ty: ref var_type,.. }) = item.kind { + if let ItemKind::Static(box StaticItem { ty: ref var_type,.. }) = item.kind { Self::visit_type(var_type, cx, "statics have by default a `'static` lifetime"); } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 0d2a7440c465..c5b58b0c060c 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -286,7 +286,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { match (l, r) { (ExternCrate(l), ExternCrate(r)) => l == r, (Use(l), Use(r)) => eq_use_tree(l, r), - (Static(box ast::Static{ ty: lt, mutability: lm, expr: le}), Static(box ast::Static { ty: rt, mutability: rm, expr: re})) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + (Static(box ast::StaticItem { ty: lt, mutability: lm, expr: le}), Static(box ast::StaticItem { ty: rt, mutability: rm, expr: re})) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), (Const(box ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(box ast::ConstItem { defaultness: rd, ty: rt, expr: re} )) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index ee62d8f2d25c..d723ff538a88 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -15,45 +15,45 @@ ast-stats-1 Arm 96 ( 1.5%) 2 48 ast-stats-1 ForeignItem 96 ( 1.5%) 1 96 ast-stats-1 - Fn 96 ( 1.5%) 1 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 -ast-stats-1 FieldDef 160 ( 2.4%) 2 80 -ast-stats-1 Stmt 160 ( 2.4%) 5 32 +ast-stats-1 FieldDef 160 ( 2.5%) 2 80 +ast-stats-1 Stmt 160 ( 2.5%) 5 32 ast-stats-1 - Local 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.5%) 3 -ast-stats-1 Param 160 ( 2.4%) 4 40 -ast-stats-1 Block 192 ( 2.9%) 6 32 +ast-stats-1 Param 160 ( 2.5%) 4 40 +ast-stats-1 Block 192 ( 3.0%) 6 32 ast-stats-1 Variant 208 ( 3.2%) 2 104 -ast-stats-1 GenericBound 224 ( 3.4%) 4 56 -ast-stats-1 - Trait 224 ( 3.4%) 4 -ast-stats-1 AssocItem 416 ( 6.3%) 4 104 -ast-stats-1 - Type 208 ( 3.2%) 2 -ast-stats-1 - Fn 208 ( 3.2%) 2 -ast-stats-1 GenericParam 480 ( 7.3%) 5 96 -ast-stats-1 Pat 504 ( 7.7%) 7 72 +ast-stats-1 GenericBound 224 ( 3.5%) 4 56 +ast-stats-1 - Trait 224 ( 3.5%) 4 +ast-stats-1 AssocItem 352 ( 5.4%) 4 88 +ast-stats-1 - Type 176 ( 2.7%) 2 +ast-stats-1 - Fn 176 ( 2.7%) 2 +ast-stats-1 GenericParam 480 ( 7.4%) 5 96 +ast-stats-1 Pat 504 ( 7.8%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 ast-stats-1 - Ident 360 ( 5.5%) 5 -ast-stats-1 Expr 576 ( 8.8%) 8 72 +ast-stats-1 Expr 576 ( 8.9%) 8 72 ast-stats-1 - Path 72 ( 1.1%) 1 ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Lit 144 ( 2.2%) 2 ast-stats-1 - Block 216 ( 3.3%) 3 -ast-stats-1 PathSegment 720 (11.0%) 30 24 -ast-stats-1 Ty 896 (13.7%) 14 64 +ast-stats-1 PathSegment 720 (11.1%) 30 24 +ast-stats-1 Ty 896 (13.8%) 14 64 ast-stats-1 - Ptr 64 ( 1.0%) 1 ast-stats-1 - Ref 64 ( 1.0%) 1 ast-stats-1 - ImplicitSelf 128 ( 2.0%) 2 -ast-stats-1 - Path 640 ( 9.8%) 10 -ast-stats-1 Item 1_224 (18.7%) 9 136 +ast-stats-1 - Path 640 ( 9.9%) 10 +ast-stats-1 Item 1_224 (18.9%) 9 136 ast-stats-1 - Trait 136 ( 2.1%) 1 ast-stats-1 - Enum 136 ( 2.1%) 1 ast-stats-1 - ForeignMod 136 ( 2.1%) 1 ast-stats-1 - Impl 136 ( 2.1%) 1 ast-stats-1 - Fn 272 ( 4.2%) 2 -ast-stats-1 - Use 408 ( 6.2%) 3 +ast-stats-1 - Use 408 ( 6.3%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_552 +ast-stats-1 Total 6_488 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -65,32 +65,32 @@ ast-stats-2 ExprField 48 ( 0.7%) 1 48 ast-stats-2 WherePredicate 56 ( 0.8%) 1 56 ast-stats-2 - BoundPredicate 56 ( 0.8%) 1 ast-stats-2 Local 72 ( 1.0%) 1 72 -ast-stats-2 Arm 96 ( 1.3%) 2 48 -ast-stats-2 ForeignItem 96 ( 1.3%) 1 96 -ast-stats-2 - Fn 96 ( 1.3%) 1 +ast-stats-2 Arm 96 ( 1.4%) 2 48 +ast-stats-2 ForeignItem 96 ( 1.4%) 1 96 +ast-stats-2 - Fn 96 ( 1.4%) 1 ast-stats-2 InlineAsm 120 ( 1.7%) 1 120 ast-stats-2 FnDecl 120 ( 1.7%) 5 24 ast-stats-2 Attribute 128 ( 1.8%) 4 32 -ast-stats-2 - DocComment 32 ( 0.4%) 1 -ast-stats-2 - Normal 96 ( 1.3%) 3 -ast-stats-2 FieldDef 160 ( 2.2%) 2 80 -ast-stats-2 Stmt 160 ( 2.2%) 5 32 -ast-stats-2 - Local 32 ( 0.4%) 1 -ast-stats-2 - Semi 32 ( 0.4%) 1 -ast-stats-2 - Expr 96 ( 1.3%) 3 -ast-stats-2 Param 160 ( 2.2%) 4 40 +ast-stats-2 - DocComment 32 ( 0.5%) 1 +ast-stats-2 - Normal 96 ( 1.4%) 3 +ast-stats-2 FieldDef 160 ( 2.3%) 2 80 +ast-stats-2 Stmt 160 ( 2.3%) 5 32 +ast-stats-2 - Local 32 ( 0.5%) 1 +ast-stats-2 - Semi 32 ( 0.5%) 1 +ast-stats-2 - Expr 96 ( 1.4%) 3 +ast-stats-2 Param 160 ( 2.3%) 4 40 ast-stats-2 Block 192 ( 2.7%) 6 32 ast-stats-2 Variant 208 ( 2.9%) 2 104 -ast-stats-2 GenericBound 224 ( 3.1%) 4 56 -ast-stats-2 - Trait 224 ( 3.1%) 4 -ast-stats-2 AssocItem 416 ( 5.8%) 4 104 -ast-stats-2 - Type 208 ( 2.9%) 2 -ast-stats-2 - Fn 208 ( 2.9%) 2 -ast-stats-2 GenericParam 480 ( 6.7%) 5 96 -ast-stats-2 Pat 504 ( 7.0%) 7 72 +ast-stats-2 GenericBound 224 ( 3.2%) 4 56 +ast-stats-2 - Trait 224 ( 3.2%) 4 +ast-stats-2 AssocItem 352 ( 5.0%) 4 88 +ast-stats-2 - Type 176 ( 2.5%) 2 +ast-stats-2 - Fn 176 ( 2.5%) 2 +ast-stats-2 GenericParam 480 ( 6.8%) 5 96 +ast-stats-2 Pat 504 ( 7.1%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 -ast-stats-2 - Ident 360 ( 5.0%) 5 +ast-stats-2 - Ident 360 ( 5.1%) 5 ast-stats-2 Expr 648 ( 9.1%) 9 72 ast-stats-2 - Path 72 ( 1.0%) 1 ast-stats-2 - Match 72 ( 1.0%) 1 @@ -98,22 +98,22 @@ ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Lit 144 ( 2.0%) 2 ast-stats-2 - Block 216 ( 3.0%) 3 -ast-stats-2 PathSegment 792 (11.1%) 33 24 -ast-stats-2 Ty 896 (12.5%) 14 64 +ast-stats-2 PathSegment 792 (11.2%) 33 24 +ast-stats-2 Ty 896 (12.6%) 14 64 ast-stats-2 - Ptr 64 ( 0.9%) 1 ast-stats-2 - Ref 64 ( 0.9%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2 -ast-stats-2 - Path 640 ( 8.9%) 10 -ast-stats-2 Item 1_496 (20.9%) 11 136 +ast-stats-2 - Path 640 ( 9.0%) 10 +ast-stats-2 Item 1_496 (21.1%) 11 136 ast-stats-2 - Trait 136 ( 1.9%) 1 ast-stats-2 - Enum 136 ( 1.9%) 1 ast-stats-2 - ExternCrate 136 ( 1.9%) 1 ast-stats-2 - ForeignMod 136 ( 1.9%) 1 ast-stats-2 - Impl 136 ( 1.9%) 1 ast-stats-2 - Fn 272 ( 3.8%) 2 -ast-stats-2 - Use 544 ( 7.6%) 4 +ast-stats-2 - Use 544 ( 7.7%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_152 +ast-stats-2 Total 7_088 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size From 1a8612e723f95b7bc0e35e8b4b570accb433f1d3 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 5 Apr 2023 01:01:45 +0900 Subject: [PATCH 103/267] Add regression test for #93911 Signed-off-by: Yuki Okushi --- tests/ui/lifetimes/issue-93911.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/ui/lifetimes/issue-93911.rs diff --git a/tests/ui/lifetimes/issue-93911.rs b/tests/ui/lifetimes/issue-93911.rs new file mode 100644 index 000000000000..b7ccac1ee521 --- /dev/null +++ b/tests/ui/lifetimes/issue-93911.rs @@ -0,0 +1,18 @@ +// check-pass +// edition:2021 + +#![allow(dead_code)] + +struct Foo<'a>(&'a u32); + +impl<'a> Foo<'a> { + async fn foo() { + struct Bar<'b>(&'b u32); + + impl<'b> Bar<'b> { + async fn bar() {} + } + } +} + +fn main() {} From 8528ac6e3595fa0afe47d05513cfb0de73171ebe Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 4 Apr 2023 18:31:25 +0000 Subject: [PATCH 104/267] Do not suppress temporary_cstring_as_ptr in macros. --- compiler/rustc_lint/src/methods.rs | 49 +++---------------- .../ui/lint/lint-temporary-cstring-as-ptr.rs | 8 +++ .../lint/lint-temporary-cstring-as-ptr.stderr | 19 ++++++- 3 files changed, 33 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index 3045fc1a4761..4c25d94a1f37 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -2,9 +2,9 @@ use crate::lints::CStringPtr; use crate::LateContext; use crate::LateLintPass; use crate::LintContext; -use rustc_hir::{Expr, ExprKind, PathSegment}; +use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; -use rustc_span::{symbol::sym, ExpnKind, Span}; +use rustc_span::{symbol::sym, Span}; declare_lint! { /// The `temporary_cstring_as_ptr` lint detects getting the inner pointer of @@ -34,47 +34,14 @@ declare_lint! { declare_lint_pass!(TemporaryCStringAsPtr => [TEMPORARY_CSTRING_AS_PTR]); -fn in_macro(span: Span) -> bool { - if span.from_expansion() { - !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..)) - } else { - false - } -} - -fn first_method_call<'tcx>( - expr: &'tcx Expr<'tcx>, -) -> Option<(&'tcx PathSegment<'tcx>, &'tcx Expr<'tcx>)> { - if let ExprKind::MethodCall(path, receiver, args, ..) = &expr.kind { - if args.iter().any(|e| e.span.from_expansion()) || receiver.span.from_expansion() { - None - } else { - Some((path, *receiver)) - } - } else { - None - } -} - impl<'tcx> LateLintPass<'tcx> for TemporaryCStringAsPtr { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if in_macro(expr.span) { - return; - } - - match first_method_call(expr) { - Some((path, unwrap_arg)) if path.ident.name == sym::as_ptr => { - let as_ptr_span = path.ident.span; - match first_method_call(unwrap_arg) { - Some((path, receiver)) - if path.ident.name == sym::unwrap || path.ident.name == sym::expect => - { - lint_cstring_as_ptr(cx, as_ptr_span, receiver, unwrap_arg); - } - _ => return, - } - } - _ => return, + if let ExprKind::MethodCall(as_ptr_path, as_ptr_receiver, ..) = expr.kind + && as_ptr_path.ident.name == sym::as_ptr + && let ExprKind::MethodCall(unwrap_path, unwrap_receiver, ..) = as_ptr_receiver.kind + && (unwrap_path.ident.name == sym::unwrap || unwrap_path.ident.name == sym::expect) + { + lint_cstring_as_ptr(cx, as_ptr_path.ident.span, unwrap_receiver, as_ptr_receiver); } } } diff --git a/tests/ui/lint/lint-temporary-cstring-as-ptr.rs b/tests/ui/lint/lint-temporary-cstring-as-ptr.rs index 7aa4f2e1e005..fab792f12841 100644 --- a/tests/ui/lint/lint-temporary-cstring-as-ptr.rs +++ b/tests/ui/lint/lint-temporary-cstring-as-ptr.rs @@ -3,7 +3,15 @@ use std::ffi::CString; +macro_rules! mymacro { + () => { + let s = CString::new("some text").unwrap().as_ptr(); + //~^ ERROR getting the inner pointer of a temporary `CString` + } +} + fn main() { let s = CString::new("some text").unwrap().as_ptr(); //~^ ERROR getting the inner pointer of a temporary `CString` + mymacro!(); } diff --git a/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr b/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr index 79ef57dd1a34..4e5c8aa06936 100644 --- a/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr +++ b/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr @@ -1,5 +1,5 @@ error: getting the inner pointer of a temporary `CString` - --> $DIR/lint-temporary-cstring-as-ptr.rs:7:48 + --> $DIR/lint-temporary-cstring-as-ptr.rs:14:48 | LL | let s = CString::new("some text").unwrap().as_ptr(); | ---------------------------------- ^^^^^^ this pointer will be invalid @@ -14,5 +14,20 @@ note: the lint level is defined here LL | #![deny(temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: getting the inner pointer of a temporary `CString` + --> $DIR/lint-temporary-cstring-as-ptr.rs:8:52 + | +LL | let s = CString::new("some text").unwrap().as_ptr(); + | ---------------------------------- ^^^^^^ this pointer will be invalid + | | + | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime +... +LL | mymacro!(); + | ---------- in this macro invocation + | + = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: for more information, see https://doc.rust-lang.org/reference/destructors.html + = note: this error originates in the macro `mymacro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors From c32953f44f98a16d49be5aa415855fdf26570336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 4 Apr 2023 21:07:19 +0200 Subject: [PATCH 105/267] Remove the use of `-use-gnu-stack` when BOLTing LLVM This flag (counterintuitively) was removing the `GNU_STACK` ELF attribute, which caused the optimized `libLLVM.so` file to be flagged as having an executable stack on SELinux. --- src/bootstrap/bolt.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/bootstrap/bolt.rs b/src/bootstrap/bolt.rs index 973dc4f602b2..10e6d2e7d6d0 100644 --- a/src/bootstrap/bolt.rs +++ b/src/bootstrap/bolt.rs @@ -45,8 +45,6 @@ pub fn optimize_with_bolt(path: &Path, profile_path: &Path, output_path: &Path) .arg("-split-all-cold") // Move jump tables to a separate section .arg("-jump-tables=move") - // Use GNU_STACK program header for new segment (workaround for issues with strip/objcopy) - .arg("-use-gnu-stack") // Fold functions with identical code .arg("-icf=1") // Update DWARF debug info in the final binary From 21bb8ef24eaf9d1f46d35f188687dfc73d72c204 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 2 Apr 2023 23:21:09 -0700 Subject: [PATCH 106/267] Use `FieldIdx` in `FieldsShape` Finally got to the main motivating example from the MCP :) --- compiler/rustc_abi/src/layout.rs | 75 ++++++++-------- compiler/rustc_abi/src/lib.rs | 23 +++-- compiler/rustc_index/src/vec.rs | 43 +++++++++ compiler/rustc_middle/src/ty/layout.rs | 3 +- compiler/rustc_mir_transform/src/generator.rs | 2 +- compiler/rustc_ty_utils/src/layout.rs | 87 +++++++++---------- compiler/rustc_ty_utils/src/lib.rs | 1 + 7 files changed, 133 insertions(+), 101 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index aea59ee6aea3..c863acde7b03 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -8,19 +8,6 @@ use rand_xoshiro::Xoshiro128StarStar; use tracing::debug; -// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`. -// This is used to go between `memory_index` (source field order to memory order) -// and `inverse_memory_index` (memory order to source field order). -// See also `FieldsShape::Arbitrary::memory_index` for more details. -// FIXME(eddyb) build a better abstraction for permutations, if possible. -fn invert_mapping(map: &[u32]) -> Vec { - let mut inverse = vec![0; map.len()]; - for i in 0..map.len() { - inverse[map[i] as usize] = i as u32; - } - inverse -} - pub trait LayoutCalculator { type TargetDataLayoutRef: Borrow; @@ -45,8 +32,8 @@ pub trait LayoutCalculator { LayoutS { variants: Variants::Single { index: FIRST_VARIANT }, fields: FieldsShape::Arbitrary { - offsets: vec![Size::ZERO, b_offset], - memory_index: vec![0, 1], + offsets: [Size::ZERO, b_offset].into(), + memory_index: [0, 1].into(), }, abi: Abi::ScalarPair(a, b), largest_niche, @@ -58,18 +45,18 @@ pub trait LayoutCalculator { fn univariant( &self, dl: &TargetDataLayout, - fields: &[Layout<'_>], + fields: &IndexSlice>, repr: &ReprOptions, kind: StructKind, ) -> Option { let pack = repr.pack; let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; - let mut inverse_memory_index: Vec = (0..fields.len() as u32).collect(); + let mut inverse_memory_index: IndexVec = fields.indices().collect(); let optimize = !repr.inhibit_struct_field_reordering_opt(); if optimize { let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; - let optimizing = &mut inverse_memory_index[..end]; + let optimizing = &mut inverse_memory_index.raw[..end]; let effective_field_align = |layout: Layout<'_>| { if let Some(pack) = pack { // return the packed alignment in bytes @@ -105,7 +92,7 @@ pub trait LayoutCalculator { // Place ZSTs first to avoid "interesting offsets", // especially with only one or two non-ZST fields. // Then place largest alignments first, largest niches within an alignment group last - let f = fields[x as usize]; + let f = fields[x]; let niche_size = f.largest_niche().map_or(0, |n| n.available(dl)); (!f.0.is_zst(), cmp::Reverse(effective_field_align(f)), niche_size) }); @@ -117,7 +104,7 @@ pub trait LayoutCalculator { // And put the largest niche in an alignment group at the end // so it can be used as discriminant in jagged enums optimizing.sort_by_key(|&x| { - let f = fields[x as usize]; + let f = fields[x]; let niche_size = f.largest_niche().map_or(0, |n| n.available(dl)); (effective_field_align(f), niche_size) }); @@ -135,7 +122,7 @@ pub trait LayoutCalculator { // At the bottom of this function, we invert `inverse_memory_index` to // produce `memory_index` (see `invert_mapping`). let mut sized = true; - let mut offsets = vec![Size::ZERO; fields.len()]; + let mut offsets = IndexVec::from_elem(Size::ZERO, &fields); let mut offset = Size::ZERO; let mut largest_niche = None; let mut largest_niche_available = 0; @@ -146,7 +133,7 @@ pub trait LayoutCalculator { offset = prefix_size.align_to(prefix_align); } for &i in &inverse_memory_index { - let field = &fields[i as usize]; + let field = &fields[i]; if !sized { self.delay_bug(&format!( "univariant: field #{} comes after unsized field", @@ -168,7 +155,7 @@ pub trait LayoutCalculator { align = align.max(field_align); debug!("univariant offset: {:?} field: {:#?}", offset, field); - offsets[i as usize] = offset; + offsets[i] = offset; if let Some(mut niche) = field.largest_niche() { let available = niche.available(dl); @@ -192,14 +179,18 @@ pub trait LayoutCalculator { // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0. // Field 5 would be the first element, so memory_index is i: // Note: if we didn't optimize, it's already right. - let memory_index = - if optimize { invert_mapping(&inverse_memory_index) } else { inverse_memory_index }; + let memory_index = if optimize { + inverse_memory_index.invert_bijective_mapping() + } else { + debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices())); + inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect() + }; let size = min_size.align_to(align.abi); let mut abi = Abi::Aggregate { sized }; // Unpack newtype ABIs and find scalar pairs. if sized && size.bytes() > 0 { // All other fields must be ZSTs. - let mut non_zst_fields = fields.iter().enumerate().filter(|&(_, f)| !f.0.is_zst()); + let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.0.is_zst()); match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) { // We have exactly one non-ZST field. @@ -238,13 +229,13 @@ pub trait LayoutCalculator { let pair = self.scalar_pair(a, b); let pair_offsets = match pair.fields { FieldsShape::Arbitrary { ref offsets, ref memory_index } => { - assert_eq!(memory_index, &[0, 1]); + assert_eq!(memory_index.raw, [0, 1]); offsets } _ => panic!(), }; - if offsets[i] == pair_offsets[0] - && offsets[j] == pair_offsets[1] + if offsets[i] == pair_offsets[FieldIdx::from_usize(0)] + && offsets[j] == pair_offsets[FieldIdx::from_usize(1)] && align == pair.align && size == pair.size { @@ -289,7 +280,7 @@ pub trait LayoutCalculator { fn layout_of_struct_or_enum( &self, repr: &ReprOptions, - variants: &IndexSlice>>, + variants: &IndexSlice>>, is_enum: bool, is_unsafe_cell: bool, scalar_valid_range: (Bound, Bound), @@ -312,7 +303,7 @@ pub trait LayoutCalculator { // but *not* an encoding of the discriminant (e.g., a tag value). // See issue #49298 for more details on the need to leave space // for non-ZST uninhabited data (mostly partial initialization). - let absent = |fields: &[Layout<'_>]| { + let absent = |fields: &IndexSlice>| { let uninhabited = fields.iter().any(|f| f.abi().is_uninhabited()); let is_zst = fields.iter().all(|f| f.0.is_zst()); uninhabited && is_zst @@ -510,7 +501,7 @@ pub trait LayoutCalculator { // It'll fit, but we need to make some adjustments. match layout.fields { FieldsShape::Arbitrary { ref mut offsets, .. } => { - for (j, offset) in offsets.iter_mut().enumerate() { + for (j, offset) in offsets.iter_enumerated_mut() { if !variants[i][j].0.is_zst() { *offset += this_offset; } @@ -577,8 +568,8 @@ pub trait LayoutCalculator { variants: IndexVec::new(), }, fields: FieldsShape::Arbitrary { - offsets: vec![niche_offset], - memory_index: vec![0], + offsets: [niche_offset].into(), + memory_index: [0].into(), }, abi, largest_niche, @@ -651,7 +642,8 @@ pub trait LayoutCalculator { st.variants = Variants::Single { index: i }; // Find the first field we can't move later // to make room for a larger discriminant. - for field in st.fields.index_by_increasing_offset().map(|j| &field_layouts[j]) { + for field_idx in st.fields.index_by_increasing_offset() { + let field = &field_layouts[FieldIdx::from_usize(field_idx)]; if !field.0.is_zst() || field.align().abi.bytes() != 1 { start_align = start_align.min(field.align().abi); break; @@ -802,13 +794,13 @@ pub trait LayoutCalculator { let pair = self.scalar_pair(tag, prim_scalar); let pair_offsets = match pair.fields { FieldsShape::Arbitrary { ref offsets, ref memory_index } => { - assert_eq!(memory_index, &[0, 1]); + assert_eq!(memory_index.raw, [0, 1]); offsets } _ => panic!(), }; - if pair_offsets[0] == Size::ZERO - && pair_offsets[1] == *offset + if pair_offsets[FieldIdx::from_u32(0)] == Size::ZERO + && pair_offsets[FieldIdx::from_u32(1)] == *offset && align == pair.align && size == pair.size { @@ -844,7 +836,10 @@ pub trait LayoutCalculator { tag_field: 0, variants: IndexVec::new(), }, - fields: FieldsShape::Arbitrary { offsets: vec![Size::ZERO], memory_index: vec![0] }, + fields: FieldsShape::Arbitrary { + offsets: [Size::ZERO].into(), + memory_index: [0].into(), + }, largest_niche, abi, align, @@ -883,7 +878,7 @@ pub trait LayoutCalculator { fn layout_of_union( &self, repr: &ReprOptions, - variants: &IndexSlice>>, + variants: &IndexSlice>>, ) -> Option { let dl = self.current_data_layout(); let dl = dl.borrow(); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 7b5732b488b4..da91776ef672 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1108,7 +1108,7 @@ pub enum FieldsShape { /// ordered to match the source definition order. /// This vector does not go in increasing order. // FIXME(eddyb) use small vector optimization for the common case. - offsets: Vec, + offsets: IndexVec, /// Maps source order field indices to memory order indices, /// depending on how the fields were reordered (if at all). @@ -1122,7 +1122,7 @@ pub enum FieldsShape { /// // FIXME(eddyb) build a better abstraction for permutations, if possible. // FIXME(camlorn) also consider small vector optimization here. - memory_index: Vec, + memory_index: IndexVec, }, } @@ -1157,7 +1157,7 @@ impl FieldsShape { assert!(i < count); stride * i } - FieldsShape::Arbitrary { ref offsets, .. } => offsets[i], + FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::from_usize(i)], } } @@ -1168,7 +1168,9 @@ impl FieldsShape { unreachable!("FieldsShape::memory_index: `Primitive`s have no fields") } FieldsShape::Union(_) | FieldsShape::Array { .. } => i, - FieldsShape::Arbitrary { ref memory_index, .. } => memory_index[i].try_into().unwrap(), + FieldsShape::Arbitrary { ref memory_index, .. } => { + memory_index[FieldIdx::from_usize(i)].try_into().unwrap() + } } } @@ -1176,20 +1178,17 @@ impl FieldsShape { #[inline] pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator + 'a { let mut inverse_small = [0u8; 64]; - let mut inverse_big = vec![]; + let mut inverse_big = IndexVec::new(); let use_small = self.count() <= inverse_small.len(); // We have to write this logic twice in order to keep the array small. if let FieldsShape::Arbitrary { ref memory_index, .. } = *self { if use_small { - for i in 0..self.count() { - inverse_small[memory_index[i] as usize] = i as u8; + for (field_idx, &mem_idx) in memory_index.iter_enumerated() { + inverse_small[mem_idx as usize] = field_idx.as_u32() as u8; } } else { - inverse_big = vec![0; self.count()]; - for i in 0..self.count() { - inverse_big[memory_index[i] as usize] = i as u32; - } + inverse_big = memory_index.invert_bijective_mapping(); } } @@ -1199,7 +1198,7 @@ impl FieldsShape { if use_small { inverse_small[i] as usize } else { - inverse_big[i] as usize + inverse_big[i as u32].as_usize() } } }) diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 5945de2302a5..45dcb25cea08 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -24,6 +24,7 @@ pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash { } #[inline] + #[must_use = "Use `increment_by` if you wanted to update the index in-place"] fn plus(self, amount: usize) -> Self { Self::new(self.index() + amount) } @@ -283,6 +284,11 @@ impl ToOwned for IndexSlice { } impl IndexSlice { + #[inline] + pub fn empty() -> &'static Self { + Default::default() + } + #[inline] pub fn from_raw(raw: &[T]) -> &Self { let ptr: *const [T] = raw; @@ -398,6 +404,36 @@ impl IndexSlice { } } +impl IndexSlice { + /// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`, + /// assuming the values in `self` are a permutation of `0..self.len()`. + /// + /// This is used to go between `memory_index` (source field order to memory order) + /// and `inverse_memory_index` (memory order to source field order). + /// See also `FieldsShape::Arbitrary::memory_index` for more details. + // FIXME(eddyb) build a better abstraction for permutations, if possible. + pub fn invert_bijective_mapping(&self) -> IndexVec { + debug_assert_eq!( + self.iter().map(|x| x.index() as u128).sum::(), + (0..self.len() as u128).sum::(), + "The values aren't 0..N in input {self:?}", + ); + + let mut inverse = IndexVec::from_elem_n(Idx::new(0), self.len()); + for (i1, &i2) in self.iter_enumerated() { + inverse[i2] = i1; + } + + debug_assert_eq!( + inverse.iter().map(|x| x.index() as u128).sum::(), + (0..inverse.len() as u128).sum::(), + "The values aren't 0..N in result {self:?}", + ); + + inverse + } +} + /// `IndexVec` is often used as a map, so it provides some map-like APIs. impl IndexVec> { #[inline] @@ -502,6 +538,13 @@ impl FromIterator for IndexVec { } } +impl From<[T; N]> for IndexVec { + #[inline] + fn from(array: [T; N]) -> Self { + IndexVec::from_raw(array.into()) + } +} + impl IntoIterator for IndexVec { type Item = T; type IntoIter = vec::IntoIter; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0f70b315aa6e..8af9acfadde9 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -5,6 +5,7 @@ use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt}; use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic}; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_index::vec::IndexVec; use rustc_session::config::OptLevel; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -635,7 +636,7 @@ where variants: Variants::Single { index: variant_index }, fields: match NonZeroUsize::new(fields) { Some(fields) => FieldsShape::Union(fields), - None => FieldsShape::Arbitrary { offsets: vec![], memory_index: vec![] }, + None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() }, }, abi: Abi::Uninhabited, largest_niche: None, diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index af6422c72464..8f29066b6e2d 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -287,7 +287,7 @@ impl<'tcx> TransformVisitor<'tcx> { statements.push(Statement { kind: StatementKind::Assign(Box::new(( Place::return_place(), - Rvalue::Aggregate(Box::new(kind), IndexVec::from_iter([val])), + Rvalue::Aggregate(Box::new(kind), [val].into()), ))), source_info, }); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 73f86f74d14f..d4420ec88db9 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -1,7 +1,7 @@ use hir::def_id::DefId; use rustc_hir as hir; use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; +use rustc_index::vec::{IndexSlice, IndexVec}; use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal}; use rustc_middle::ty::layout::{ IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES, @@ -62,23 +62,10 @@ fn layout_of<'tcx>( Ok(layout) } -// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`. -// This is used to go between `memory_index` (source field order to memory order) -// and `inverse_memory_index` (memory order to source field order). -// See also `FieldsShape::Arbitrary::memory_index` for more details. -// FIXME(eddyb) build a better abstraction for permutations, if possible. -fn invert_mapping(map: &[u32]) -> Vec { - let mut inverse = vec![0; map.len()]; - for i in 0..map.len() { - inverse[map[i] as usize] = i as u32; - } - inverse -} - fn univariant_uninterned<'tcx>( cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, ty: Ty<'tcx>, - fields: &[Layout<'_>], + fields: &IndexSlice>, repr: &ReprOptions, kind: StructKind, ) -> Result> { @@ -106,7 +93,7 @@ fn layout_of_uncached<'tcx>( }; let scalar = |value: Primitive| tcx.mk_layout(LayoutS::scalar(cx, scalar_unit(value))); - let univariant = |fields: &[Layout<'_>], repr: &ReprOptions, kind| { + let univariant = |fields: &IndexSlice>, repr: &ReprOptions, kind| { Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, repr, kind)?)) }; debug_assert!(!ty.has_non_region_infer()); @@ -256,12 +243,14 @@ fn layout_of_uncached<'tcx>( }), // Odd unit types. - ty::FnDef(..) => univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?, + ty::FnDef(..) => { + univariant(IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized)? + } ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => { let mut unit = univariant_uninterned( cx, ty, - &[], + IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized, )?; @@ -277,7 +266,7 @@ fn layout_of_uncached<'tcx>( ty::Closure(_, ref substs) => { let tys = substs.as_closure().upvar_tys(); univariant( - &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).collect::, _>>()?, + &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).try_collect::>()?, &ReprOptions::default(), StructKind::AlwaysSized, )? @@ -288,7 +277,7 @@ fn layout_of_uncached<'tcx>( if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; univariant( - &tys.iter().map(|k| Ok(cx.layout_of(k)?.layout)).collect::, _>>()?, + &tys.iter().map(|k| Ok(cx.layout_of(k)?.layout)).try_collect::>()?, &ReprOptions::default(), kind, )? @@ -393,7 +382,7 @@ fn layout_of_uncached<'tcx>( // Compute the placement of the vector fields: let fields = if is_array { - FieldsShape::Arbitrary { offsets: vec![Size::ZERO], memory_index: vec![0] } + FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() } } else { FieldsShape::Array { stride: e_ly.size, count: e_len } }; @@ -418,9 +407,9 @@ fn layout_of_uncached<'tcx>( v.fields .iter() .map(|field| Ok(cx.layout_of(field.ty(tcx, substs))?.layout)) - .collect::, _>>() + .try_collect::>() }) - .collect::, _>>()?; + .try_collect::>()?; if def.is_union() { if def.repr().pack.is_some() && def.repr().align.is_some() { @@ -492,8 +481,7 @@ fn layout_of_uncached<'tcx>( enum SavedLocalEligibility { Unassigned, Assigned(VariantIdx), - // FIXME: Use newtype_index so we aren't wasting bytes - Ineligible(Option), + Ineligible(Option), } // When laying out generators, we divide our saved local fields into two @@ -522,7 +510,7 @@ fn generator_saved_local_eligibility( use SavedLocalEligibility::*; let mut assignments: IndexVec = - IndexVec::from_elem_n(Unassigned, info.field_tys.len()); + IndexVec::from_elem(Unassigned, &info.field_tys); // The saved locals not eligible for overlap. These will get // "promoted" to the prefix of our generator. @@ -605,7 +593,7 @@ fn generator_saved_local_eligibility( // Write down the order of our locals that will be promoted to the prefix. { for (idx, local) in ineligible_locals.iter().enumerate() { - assignments[local] = Ineligible(Some(idx as u32)); + assignments[local] = Ineligible(Some(FieldIdx::from_usize(idx))); } } debug!("generator saved local assignments: {:?}", assignments); @@ -654,7 +642,7 @@ fn generator_layout<'tcx>( .map(|ty| Ok(cx.layout_of(ty)?.layout)) .chain(iter::once(Ok(tag_layout))) .chain(promoted_layouts) - .collect::, _>>()?; + .try_collect::>()?; let prefix = univariant_uninterned( cx, ty, @@ -672,26 +660,28 @@ fn generator_layout<'tcx>( debug!("prefix = {:#?}", prefix); let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields { FieldsShape::Arbitrary { mut offsets, memory_index } => { - let mut inverse_memory_index = invert_mapping(&memory_index); + let mut inverse_memory_index = memory_index.invert_bijective_mapping(); // "a" (`0..b_start`) and "b" (`b_start..`) correspond to // "outer" and "promoted" fields respectively. - let b_start = (tag_index + 1) as u32; - let offsets_b = offsets.split_off(b_start as usize); + let b_start = FieldIdx::from_usize(tag_index + 1); + let offsets_b = IndexVec::from_raw(offsets.raw.split_off(b_start.as_usize())); let offsets_a = offsets; // Disentangle the "a" and "b" components of `inverse_memory_index` // by preserving the order but keeping only one disjoint "half" each. // FIXME(eddyb) build a better abstraction for permutations, if possible. - let inverse_memory_index_b: Vec<_> = - inverse_memory_index.iter().filter_map(|&i| i.checked_sub(b_start)).collect(); - inverse_memory_index.retain(|&i| i < b_start); + let inverse_memory_index_b: IndexVec = inverse_memory_index + .iter() + .filter_map(|&i| i.as_u32().checked_sub(b_start.as_u32()).map(FieldIdx::from_u32)) + .collect(); + inverse_memory_index.raw.retain(|&i| i < b_start); let inverse_memory_index_a = inverse_memory_index; // Since `inverse_memory_index_{a,b}` each only refer to their // respective fields, they can be safely inverted - let memory_index_a = invert_mapping(&inverse_memory_index_a); - let memory_index_b = invert_mapping(&inverse_memory_index_b); + let memory_index_a = inverse_memory_index_a.invert_bijective_mapping(); + let memory_index_b = inverse_memory_index_b.invert_bijective_mapping(); let outer_fields = FieldsShape::Arbitrary { offsets: offsets_a, memory_index: memory_index_a }; @@ -722,7 +712,7 @@ fn generator_layout<'tcx>( ty, &variant_only_tys .map(|ty| Ok(cx.layout_of(ty)?.layout)) - .collect::, _>>()?, + .try_collect::>()?, &ReprOptions::default(), StructKind::Prefixed(prefix_size, prefix_align.abi), )?; @@ -741,13 +731,16 @@ fn generator_layout<'tcx>( // promoted fields were being used, but leave the elements not in the // subset as `INVALID_FIELD_IDX`, which we can filter out later to // obtain a valid (bijective) mapping. - const INVALID_FIELD_IDX: u32 = !0; - let mut combined_inverse_memory_index = - vec![INVALID_FIELD_IDX; promoted_memory_index.len() + memory_index.len()]; + const INVALID_FIELD_IDX: FieldIdx = FieldIdx::MAX; + debug_assert!(variant_fields.next_index() <= INVALID_FIELD_IDX); + + let mut combined_inverse_memory_index = IndexVec::from_elem_n( + INVALID_FIELD_IDX, + promoted_memory_index.len() + memory_index.len(), + ); let mut offsets_and_memory_index = iter::zip(offsets, memory_index); let combined_offsets = variant_fields - .iter() - .enumerate() + .iter_enumerated() .map(|(i, local)| { let (offset, memory_index) = match assignments[*local] { Unassigned => bug!(), @@ -756,19 +749,19 @@ fn generator_layout<'tcx>( (offset, promoted_memory_index.len() as u32 + memory_index) } Ineligible(field_idx) => { - let field_idx = field_idx.unwrap() as usize; + let field_idx = field_idx.unwrap(); (promoted_offsets[field_idx], promoted_memory_index[field_idx]) } }; - combined_inverse_memory_index[memory_index as usize] = i as u32; + combined_inverse_memory_index[memory_index] = i; offset }) .collect(); // Remove the unused slots and invert the mapping to obtain the // combined `memory_index` (also see previous comment). - combined_inverse_memory_index.retain(|&i| i != INVALID_FIELD_IDX); - let combined_memory_index = invert_mapping(&combined_inverse_memory_index); + combined_inverse_memory_index.raw.retain(|&i| i != INVALID_FIELD_IDX); + let combined_memory_index = combined_inverse_memory_index.invert_bijective_mapping(); variant.fields = FieldsShape::Arbitrary { offsets: combined_offsets, @@ -779,7 +772,7 @@ fn generator_layout<'tcx>( align = align.max(variant.align); Ok(variant) }) - .collect::, _>>()?; + .try_collect::>()?; size = size.align_to(align.abi); diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 3865a8f32236..9195964a2f36 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -5,6 +5,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(iterator_try_collect)] #![feature(let_chains)] #![feature(never_type)] #![feature(box_patterns)] From 6b57a344cba18b18178cdcf609d68880f33cc6eb Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 4 Apr 2023 13:42:38 -0700 Subject: [PATCH 107/267] Make rust-docs optional for the Windows MSI installer. --- src/bootstrap/dist.rs | 51 +++++++++++++++++++--------------- src/etc/installer/msi/rust.wxs | 6 ++++ 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 9eed2bf50237..8ce220c86478 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1585,11 +1585,10 @@ impl Step for Extended { prepare("rustc"); prepare("cargo"); prepare("rust-analysis"); - prepare("rust-docs"); prepare("rust-std"); prepare("clippy"); prepare("rust-analyzer"); - for tool in &["rust-demangler", "miri"] { + for tool in &["rust-docs", "rust-demangler", "miri"] { if built_tools.contains(tool) { prepare(tool); } @@ -1624,23 +1623,25 @@ impl Step for Extended { .arg("-out") .arg(exe.join("RustcGroup.wxs")), ); - builder.run( - Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rust-docs") - .args(&heat_flags) - .arg("-cg") - .arg("DocsGroup") - .arg("-dr") - .arg("Docs") - .arg("-var") - .arg("var.DocsDir") - .arg("-out") - .arg(exe.join("DocsGroup.wxs")) - .arg("-t") - .arg(etc.join("msi/squash-components.xsl")), - ); + if built_tools.contains("rust-docs") { + builder.run( + Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-docs") + .args(&heat_flags) + .arg("-cg") + .arg("DocsGroup") + .arg("-dr") + .arg("Docs") + .arg("-var") + .arg("var.DocsDir") + .arg("-out") + .arg(exe.join("DocsGroup.wxs")) + .arg("-t") + .arg(etc.join("msi/squash-components.xsl")), + ); + } builder.run( Command::new(&heat) .current_dir(&exe) @@ -1787,7 +1788,6 @@ impl Step for Extended { cmd.current_dir(&exe) .arg("-nologo") .arg("-dRustcDir=rustc") - .arg("-dDocsDir=rust-docs") .arg("-dCargoDir=cargo") .arg("-dStdDir=rust-std") .arg("-dAnalysisDir=rust-analysis") @@ -1799,6 +1799,9 @@ impl Step for Extended { .arg(&input); add_env(builder, &mut cmd, target); + if built_tools.contains("rust-docs") { + cmd.arg("-dDocsDir=rust-docs"); + } if built_tools.contains("rust-demangler") { cmd.arg("-dRustDemanglerDir=rust-demangler"); } @@ -1817,7 +1820,9 @@ impl Step for Extended { candle(&etc.join("msi/ui.wxs")); candle(&etc.join("msi/rustwelcomedlg.wxs")); candle("RustcGroup.wxs".as_ref()); - candle("DocsGroup.wxs".as_ref()); + if built_tools.contains("rust-docs") { + candle("DocsGroup.wxs".as_ref()); + } candle("CargoGroup.wxs".as_ref()); candle("StdGroup.wxs".as_ref()); candle("ClippyGroup.wxs".as_ref()); @@ -1854,7 +1859,6 @@ impl Step for Extended { .arg("ui.wixobj") .arg("rustwelcomedlg.wixobj") .arg("RustcGroup.wixobj") - .arg("DocsGroup.wixobj") .arg("CargoGroup.wixobj") .arg("StdGroup.wixobj") .arg("AnalysisGroup.wixobj") @@ -1870,6 +1874,9 @@ impl Step for Extended { if built_tools.contains("rust-demangler") { cmd.arg("RustDemanglerGroup.wixobj"); } + if built_tools.contains("rust-docs") { + cmd.arg("DocsGroup.wixobj"); + } if target.ends_with("windows-gnu") { cmd.arg("GccGroup.wixobj"); diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs index 0aa0784e5445..9f4e4fd0611d 100644 --- a/src/etc/installer/msi/rust.wxs +++ b/src/etc/installer/msi/rust.wxs @@ -167,7 +167,9 @@ + + @@ -209,6 +211,7 @@ + + @@ -256,6 +260,7 @@ + + Date: Tue, 4 Apr 2023 20:45:20 -0400 Subject: [PATCH 108/267] Move comment about python2 closer to the place it's used --- src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile index b5715024a848..34b93be412e5 100644 --- a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile @@ -1,8 +1,6 @@ FROM ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive -# NOTE: intentionally uses python2 for x.py so we can test it still works. -# validate-toolstate only runs in our CI, so it's ok for it to only support python3. RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ make \ @@ -33,4 +31,6 @@ RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-require COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ +# NOTE: intentionally uses python2 for x.py so we can test it still works. +# validate-toolstate only runs in our CI, so it's ok for it to only support python3. ENV SCRIPT python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest From 9aa9a846b6e131f9a2b1f477ecc19c2024609847 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 1 Apr 2023 01:46:36 -0700 Subject: [PATCH 109/267] Allow `transmute`s to produce `OperandValue`s instead of always using `alloca`s LLVM can usually optimize these away, but especially for things like transmutes of newtypes it's silly to generate the `alloc`+`store`+`load` at all when it's actually a nop at LLVM level. --- compiler/rustc_codegen_ssa/src/mir/operand.rs | 18 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 178 ++++++++++++++++-- .../rustc_codegen_ssa/src/traits/type_.rs | 11 ++ tests/codegen/intrinsics/transmute.rs | 153 ++++++++++++--- .../simd-intrinsic-transmute-array.rs | 51 ++++- tests/codegen/transmute-scalar.rs | 44 ++--- 6 files changed, 381 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index b45e7c834e72..ddef4aaee3ba 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -23,10 +23,26 @@ pub enum OperandValue { /// to be valid for the operand's lifetime. /// The second value, if any, is the extra data (vtable or length) /// which indicates that it refers to an unsized rvalue. + /// + /// An `OperandValue` has this variant for types which are neither + /// `Immediate` nor `Pair`s. The backend value in this variant must be a + /// pointer to the *non*-immediate backend type. That pointee type is the + /// one returned by [`LayoutTypeMethods::backend_type`]. Ref(V, Option, Align), - /// A single LLVM value. + /// A single LLVM immediate value. + /// + /// An `OperandValue` *must* be this variant for any type for which + /// [`LayoutTypeMethods::is_backend_immediate`] returns `true`. + /// The backend value in this variant must be the *immediate* backend type, + /// as returned by [`LayoutTypeMethods::immediate_backend_type`]. Immediate(V), /// A pair of immediate LLVM values. Used by fat pointers too. + /// + /// An `OperandValue` *must* be this variant for any type for which + /// [`LayoutTypeMethods::is_backend_scalar_pair`] returns `true`. + /// The backend values in this variant must be the *immediate* backend types, + /// as returned by [`LayoutTypeMethods::scalar_pair_element_backend_type`] + /// with `immediate: true`. Pair(V, V), } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 0a59fabdc17f..3b4522a99dd5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -10,7 +10,7 @@ use crate::MemFlags; use rustc_middle::mir; use rustc_middle::mir::Operand; use rustc_middle::ty::cast::{CastTy, IntTy}; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_target::abi::{self, FIRST_VARIANT}; @@ -159,8 +159,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { debug_assert!(dst.layout.is_sized()); if src.layout.size != dst.layout.size - || src.layout.abi == abi::Abi::Uninhabited - || dst.layout.abi == abi::Abi::Uninhabited + || src.layout.abi.is_uninhabited() + || dst.layout.abi.is_uninhabited() { // In all of these cases it's UB to run this transmute, but that's // known statically so might as well trap for it, rather than just @@ -169,22 +169,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - let size_in_bytes = src.layout.size.bytes(); - if size_in_bytes == 0 { - // Nothing to write + if let Some(val) = self.codegen_transmute_operand(bx, src, dst.layout) { + val.store(bx, dst); return; } match src.val { - OperandValue::Ref(src_llval, meta, src_align) => { - debug_assert_eq!(meta, None); - // For a place-to-place transmute, call `memcpy` directly so that - // both arguments get the best-available alignment information. - let bytes = bx.cx().const_usize(size_in_bytes); - let flags = MemFlags::empty(); - bx.memcpy(dst.llval, dst.align, src_llval, src_align, bytes, flags); + OperandValue::Ref(..) => { + span_bug!( + self.mir.span, + "Operand path should have handled transmute \ + from `Ref` {src:?} to place {dst:?}" + ); } - OperandValue::Immediate(_) | OperandValue::Pair(_, _) => { + OperandValue::Immediate(..) | OperandValue::Pair(..) => { // When we have immediate(s), the alignment of the source is irrelevant, // so we can store them using the destination's alignment. let llty = bx.backend_type(src.layout); @@ -194,6 +192,94 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + /// Attempts to transmute an `OperandValue` to another `OperandValue`. + /// + /// Returns `None` for cases that can't work in that framework, such as for + /// `Immediate`->`Ref` that needs an `alloc` to get the location. + fn codegen_transmute_operand( + &mut self, + bx: &mut Bx, + operand: OperandRef<'tcx, Bx::Value>, + cast: TyAndLayout<'tcx>, + ) -> Option> { + // Callers already checked that the layout sizes match + debug_assert_eq!(operand.layout.size, cast.size); + + let operand_kind = self.value_kind(operand.layout); + let cast_kind = self.value_kind(cast); + + match operand.val { + OperandValue::Ref(ptr, meta, align) => { + debug_assert_eq!(meta, None); + debug_assert!(matches!(operand_kind, OperandValueKind::Ref)); + let cast_bty = bx.backend_type(cast); + let cast_ptr = bx.pointercast(ptr, bx.type_ptr_to(cast_bty)); + let fake_place = PlaceRef::new_sized_aligned(cast_ptr, cast, align); + Some(bx.load_operand(fake_place).val) + } + OperandValue::Immediate(imm) => { + let OperandValueKind::Immediate(in_scalar) = operand_kind else { + bug!("Found {operand_kind:?} for operand {operand:?}"); + }; + if let OperandValueKind::Immediate(out_scalar) = cast_kind { + let cast_bty = bx.backend_type(cast); + Some(OperandValue::Immediate(Self::transmute_immediate( + bx, imm, in_scalar, out_scalar, cast_bty, + ))) + } else { + None + } + } + OperandValue::Pair(imm_a, imm_b) => { + let OperandValueKind::Pair(in_a, in_b) = operand_kind else { + bug!("Found {operand_kind:?} for operand {operand:?}"); + }; + if let OperandValueKind::Pair(out_a, out_b) = cast_kind { + let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false); + let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false); + Some(OperandValue::Pair( + Self::transmute_immediate(bx, imm_a, in_a, out_a, out_a_ibty), + Self::transmute_immediate(bx, imm_b, in_b, out_b, out_b_ibty), + )) + } else { + None + } + } + } + } + + /// Transmutes one of the immediates from an [`OperandValue::Immediate`] + /// or an [`OperandValue::Pair`] to an immediate of the target type. + /// + /// `to_backend_ty` must be the *non*-immediate backend type (so it will be + /// `i8`, not `i1`, for `bool`-like types.) + fn transmute_immediate( + bx: &mut Bx, + mut imm: Bx::Value, + from_scalar: abi::Scalar, + to_scalar: abi::Scalar, + to_backend_ty: Bx::Type, + ) -> Bx::Value { + use abi::Primitive::*; + imm = bx.from_immediate(imm); + imm = match (from_scalar.primitive(), to_scalar.primitive()) { + (Int(..) | F32 | F64, Int(..) | F32 | F64) => bx.bitcast(imm, to_backend_ty), + (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), + (Int(..), Pointer(..)) => bx.inttoptr(imm, to_backend_ty), + (Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty), + (F32 | F64, Pointer(..)) => { + let int_imm = bx.bitcast(imm, bx.cx().type_isize()); + bx.inttoptr(int_imm, to_backend_ty) + } + (Pointer(..), F32 | F64) => { + let int_imm = bx.ptrtoint(imm, bx.cx().type_isize()); + bx.bitcast(int_imm, to_backend_ty) + } + }; + imm = bx.to_immediate_scalar(imm, to_scalar); + imm + } + pub fn codegen_rvalue_unsized( &mut self, bx: &mut Bx, @@ -396,7 +482,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Immediate(newval) } mir::CastKind::Transmute => { - bug!("Transmute operand {:?} in `codegen_rvalue_operand`", operand); + self.codegen_transmute_operand(bx, operand, cast).unwrap_or_else(|| { + bug!("Unsupported transmute-as-operand of {operand:?} to {cast:?}"); + }) } }; OperandRef { val, layout: cast } @@ -739,10 +827,36 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { match *rvalue { - mir::Rvalue::Cast(mir::CastKind::Transmute, ..) => - // FIXME: Now that transmute is an Rvalue, it would be nice if - // it could create `Immediate`s for scalars, where possible. - false, + mir::Rvalue::Cast(mir::CastKind::Transmute, ref operand, cast_ty) => { + let operand_ty = operand.ty(self.mir, self.cx.tcx()); + let cast_layout = self.cx.layout_of(self.monomorphize(cast_ty)); + let operand_layout = self.cx.layout_of(self.monomorphize(operand_ty)); + if operand_layout.size != cast_layout.size + || operand_layout.abi.is_uninhabited() + || cast_layout.abi.is_uninhabited() + { + // Send UB cases to the full form so the operand version can + // `bitcast` without worrying about malformed IR. + return false; + } + + match (self.value_kind(operand_layout), self.value_kind(cast_layout)) { + // Can always load from a pointer as needed + (OperandValueKind::Ref, _) => true, + + // Need to generate an `alloc` to get a pointer from an immediate + (OperandValueKind::Immediate(..) | OperandValueKind::Pair(..), OperandValueKind::Ref) => false, + + // When we have scalar immediates, we can convert them as needed + (OperandValueKind::Immediate(..), OperandValueKind::Immediate(..)) | + (OperandValueKind::Pair(..), OperandValueKind::Pair(..)) => true, + + // Send mixings between scalars and pairs through the memory route + // FIXME: Maybe this could use insertvalue/extractvalue instead? + (OperandValueKind::Immediate(..), OperandValueKind::Pair(..)) | + (OperandValueKind::Pair(..), OperandValueKind::Immediate(..)) => false, + } + } mir::Rvalue::Ref(..) | mir::Rvalue::CopyForDeref(..) | mir::Rvalue::AddressOf(..) | @@ -767,4 +881,30 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // (*) this is only true if the type is suitable } + + /// Gets which variant of [`OperandValue`] is expected for a particular type. + fn value_kind(&self, layout: TyAndLayout<'tcx>) -> OperandValueKind { + if self.cx.is_backend_immediate(layout) { + debug_assert!(!self.cx.is_backend_scalar_pair(layout)); + OperandValueKind::Immediate(match layout.abi { + abi::Abi::Scalar(s) => s, + abi::Abi::Vector { element, .. } => element, + x => bug!("Couldn't translate {x:?} as backend immediate"), + }) + } else if self.cx.is_backend_scalar_pair(layout) { + let abi::Abi::ScalarPair(s1, s2) = layout.abi else { + bug!("Couldn't translate {:?} as backend scalar pair", layout.abi) + }; + OperandValueKind::Pair(s1, s2) + } else { + OperandValueKind::Ref + } + } +} + +#[derive(Debug, Copy, Clone)] +enum OperandValueKind { + Ref, + Immediate(abi::Scalar), + Pair(abi::Scalar, abi::Scalar), } diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 109161ccc836..32905b079d36 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -100,11 +100,22 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { impl<'tcx, T> DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {} pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { + /// The backend type used for a rust type when it's in memory, + /// such as when it's stack-allocated or when it's being loaded or stored. fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type; fn cast_backend_type(&self, ty: &CastTarget) -> Self::Type; fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Type; fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Type; fn reg_backend_type(&self, ty: &Reg) -> Self::Type; + /// The backend type used for a rust type when it's in an SSA register. + /// + /// For nearly all types this is the same as the [`Self::backend_type`], however + /// `bool` (and other `0`-or-`1` values) are kept as [`BaseTypeMethods::type_i1`] + /// in registers but as [`BaseTypeMethods::type_i8`] in memory. + /// + /// Converting values between the two different backend types is done using + /// [`from_immediate`](super::BuilderMethods::from_immediate) and + /// [`to_immediate_scalar`](super::BuilderMethods::to_immediate_scalar). fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type; fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool; fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool; diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index cefcf9ed9caa..7ad0e62213cb 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -6,6 +6,7 @@ #![feature(core_intrinsics)] #![feature(custom_mir)] #![feature(inline_const)] +#![allow(unreachable_code)] use std::mem::transmute; @@ -24,6 +25,9 @@ pub struct Scalar64(i64); #[repr(C, align(4))] pub struct Aggregate64(u16, u8, i8, f32); +#[repr(C)] +pub struct Aggregate8(u8); + // CHECK-LABEL: @check_bigger_size( #[no_mangle] #[custom_mir(dialect = "runtime", phase = "initial")] @@ -76,23 +80,80 @@ pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 { } } +// CHECK-LABEL: @check_intermediate_passthrough( +#[no_mangle] +pub unsafe fn check_intermediate_passthrough(x: u32) -> i32 { + // CHECK: start + // CHECK: %[[TMP:.+]] = add i32 1, %x + // CHECK: %[[RET:.+]] = add i32 %[[TMP]], 1 + // CHECK: ret i32 %[[RET]] + unsafe { + transmute::(1 + x) + 1 + } +} + +// CHECK-LABEL: @check_nop_pair( +#[no_mangle] +pub unsafe fn check_nop_pair(x: (u8, i8)) -> (i8, u8) { + // CHECK-NOT: alloca + // CHECK: %0 = insertvalue { i8, i8 } poison, i8 %x.0, 0 + // CHECK: %1 = insertvalue { i8, i8 } %0, i8 %x.1, 1 + // CHECK: ret { i8, i8 } %1 + unsafe { + transmute(x) + } +} + // CHECK-LABEL: @check_to_newtype( #[no_mangle] pub unsafe fn check_to_newtype(x: u64) -> Scalar64 { - // CHECK: %0 = alloca i64 - // CHECK: store i64 %x, ptr %0 - // CHECK: %1 = load i64, ptr %0 - // CHECK: ret i64 %1 + // CHECK-NOT: alloca + // CHECK: ret i64 %x transmute(x) } // CHECK-LABEL: @check_from_newtype( #[no_mangle] pub unsafe fn check_from_newtype(x: Scalar64) -> u64 { - // CHECK: %0 = alloca i64 - // CHECK: store i64 %x, ptr %0 - // CHECK: %1 = load i64, ptr %0 - // CHECK: ret i64 %1 + // CHECK-NOT: alloca + // CHECK: ret i64 %x + transmute(x) +} + +// CHECK-LABEL: @check_aggregate_to_bool( +#[no_mangle] +pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool { + // CHECK: %x = alloca %Aggregate8, align 1 + // CHECK: %[[BYTE:.+]] = load i8, ptr %x, align 1 + // CHECK: %[[BOOL:.+]] = trunc i8 %[[BYTE]] to i1 + // CHECK: ret i1 %[[BOOL]] + transmute(x) +} + +// CHECK-LABEL: @check_aggregate_from_bool( +#[no_mangle] +pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 { + // CHECK: %0 = alloca %Aggregate8, align 1 + // CHECK: %[[BYTE:.+]] = zext i1 %x to i8 + // CHECK: store i8 %[[BYTE]], ptr %0, align 1 + transmute(x) +} + +// CHECK-LABEL: @check_byte_to_bool( +#[no_mangle] +pub unsafe fn check_byte_to_bool(x: u8) -> bool { + // CHECK-NOT: alloca + // CHECK: %0 = trunc i8 %x to i1 + // CHECK: ret i1 %0 + transmute(x) +} + +// CHECK-LABEL: @check_byte_from_bool( +#[no_mangle] +pub unsafe fn check_byte_from_bool(x: bool) -> u8 { + // CHECK-NOT: alloca + // CHECK: %0 = zext i1 %x to i8 + // CHECK: ret i8 %0 transmute(x) } @@ -122,20 +183,18 @@ pub unsafe fn check_from_pair(x: Option) -> u64 { // CHECK-LABEL: @check_to_float( #[no_mangle] pub unsafe fn check_to_float(x: u32) -> f32 { - // CHECK: %0 = alloca float - // CHECK: store i32 %x, ptr %0 - // CHECK: %1 = load float, ptr %0 - // CHECK: ret float %1 + // CHECK-NOT: alloca + // CHECK: %0 = bitcast i32 %x to float + // CHECK: ret float %0 transmute(x) } // CHECK-LABEL: @check_from_float( #[no_mangle] pub unsafe fn check_from_float(x: f32) -> u32 { - // CHECK: %0 = alloca i32 - // CHECK: store float %x, ptr %0 - // CHECK: %1 = load i32, ptr %0 - // CHECK: ret i32 %1 + // CHECK-NOT: alloca + // CHECK: %0 = bitcast float %x to i32 + // CHECK: ret i32 %0 transmute(x) } @@ -144,19 +203,15 @@ pub unsafe fn check_from_float(x: f32) -> u32 { pub unsafe fn check_to_bytes(x: u32) -> [u8; 4] { // CHECK: %0 = alloca [4 x i8], align 1 // CHECK: store i32 %x, ptr %0, align 1 - // CHECK: %1 = load i32, ptr %0, align 1 - // CHECK: ret i32 %1 transmute(x) } // CHECK-LABEL: @check_from_bytes( #[no_mangle] pub unsafe fn check_from_bytes(x: [u8; 4]) -> u32 { - // CHECK: %1 = alloca i32, align 4 // CHECK: %x = alloca [4 x i8], align 1 - // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %1, ptr align 1 %x, i64 4, i1 false) - // CHECK: %3 = load i32, ptr %1, align 4 - // CHECK: ret i32 %3 + // CHECK: %[[VAL:.+]] = load i32, ptr %x, align 1 + // CHECK: ret i32 %[[VAL]] transmute(x) } @@ -173,7 +228,9 @@ pub unsafe fn check_to_aggregate(x: u64) -> Aggregate64 { // CHECK-LABEL: @check_from_aggregate( #[no_mangle] pub unsafe fn check_from_aggregate(x: Aggregate64) -> u64 { - // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %{{[0-9]+}}, ptr align 4 %x, i64 8, i1 false) + // CHECK: %x = alloca %Aggregate64, align 4 + // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 4 + // CHECK: ret i64 %[[VAL]] transmute(x) } @@ -194,3 +251,53 @@ pub unsafe fn check_long_array_more_aligned(x: [u8; 100]) -> [u32; 25] { // CHECK-NEXT: ret void transmute(x) } + +// CHECK-LABEL: @check_pair_with_bool( +#[no_mangle] +pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) { + // CHECK-NOT: alloca + // CHECK: trunc i8 %x.0 to i1 + // CHECK: zext i1 %x.1 to i8 + transmute(x) +} + +// CHECK-LABEL: @check_float_to_pointer( +#[no_mangle] +pub unsafe fn check_float_to_pointer(x: f64) -> *const () { + // CHECK-NOT: alloca + // CHECK: %0 = bitcast double %x to i64 + // CHECK: %1 = inttoptr i64 %0 to ptr + // CHECK: ret ptr %1 + transmute(x) +} + +// CHECK-LABEL: @check_float_from_pointer( +#[no_mangle] +pub unsafe fn check_float_from_pointer(x: *const ()) -> f64 { + // CHECK-NOT: alloca + // CHECK: %0 = ptrtoint ptr %x to i64 + // CHECK: %1 = bitcast i64 %0 to double + // CHECK: ret double %1 + transmute(x) +} + +// CHECK-LABEL: @check_array_to_pair( +#[no_mangle] +pub unsafe fn check_array_to_pair(x: [u8; 16]) -> (i64, u64) { + // CHECK-NOT: alloca + // CHECK: %[[FST:.+]] = load i64, ptr %{{.+}}, align 1, !noundef ! + // CHECK: %[[SND:.+]] = load i64, ptr %{{.+}}, align 1, !noundef ! + // CHECK: %[[PAIR0:.+]] = insertvalue { i64, i64 } poison, i64 %[[FST]], 0 + // CHECK: %[[PAIR01:.+]] = insertvalue { i64, i64 } %[[PAIR0]], i64 %[[SND]], 1 + // CHECK: ret { i64, i64 } %[[PAIR01]] + transmute(x) +} + +// CHECK-LABEL: @check_pair_to_array( +#[no_mangle] +pub unsafe fn check_pair_to_array(x: (i64, u64)) -> [u8; 16] { + // CHECK-NOT: alloca + // CHECK: store i64 %x.0, ptr %{{.+}}, align 1 + // CHECK: store i64 %x.1, ptr %{{.+}}, align 1 + transmute(x) +} diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index 7c77398dfcce..fd488a14bd37 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -4,7 +4,8 @@ #![crate_type = "lib"] #![allow(non_camel_case_types)] -#![feature(repr_simd, platform_intrinsics, min_const_generics)] +#![feature(repr_simd, platform_intrinsics)] +#![feature(inline_const)] #[repr(simd)] #[derive(Copy, Clone)] @@ -18,23 +19,65 @@ pub struct T([f32; 4]); #[derive(Copy, Clone)] pub struct U(f32, f32, f32, f32); +// CHECK-LABEL: @array_align( +#[no_mangle] +pub fn array_align() -> usize { + // CHECK: ret [[USIZE:i[0-9]+]] [[ARRAY_ALIGN:[0-9]+]] + const { std::mem::align_of::() } +} + +// CHECK-LABEL: @vector_align( +#[no_mangle] +pub fn vector_align() -> usize { + // CHECK: ret [[USIZE]] [[VECTOR_ALIGN:[0-9]+]] + const { std::mem::align_of::() } +} + // CHECK-LABEL: @build_array_s #[no_mangle] pub fn build_array_s(x: [f32; 4]) -> S<4> { - // CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false) S::<4>(x) } +// CHECK-LABEL: @build_array_transmute_s +#[no_mangle] +pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> { + // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]] + // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]] + unsafe { std::mem::transmute(x) } +} + // CHECK-LABEL: @build_array_t #[no_mangle] pub fn build_array_t(x: [f32; 4]) -> T { - // CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false) T(x) } +// CHECK-LABEL: @build_array_transmute_t +#[no_mangle] +pub fn build_array_transmute_t(x: [f32; 4]) -> T { + // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]] + // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]] + unsafe { std::mem::transmute(x) } +} + // CHECK-LABEL: @build_array_u #[no_mangle] pub fn build_array_u(x: [f32; 4]) -> U { - // CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false) + // CHECK: store float %a, {{.+}}, align [[VECTOR_ALIGN]] + // CHECK: store float %b, {{.+}}, align [[ARRAY_ALIGN]] + // CHECK: store float %c, {{.+}}, align + // CHECK: store float %d, {{.+}}, align [[ARRAY_ALIGN]] + let [a, b, c, d] = x; + U(a, b, c, d) +} + +// CHECK-LABEL: @build_array_transmute_u +#[no_mangle] +pub fn build_array_transmute_u(x: [f32; 4]) -> U { + // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]] + // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]] unsafe { std::mem::transmute(x) } } diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs index 4d7a80bfbe5c..af2cef472ec6 100644 --- a/tests/codegen/transmute-scalar.rs +++ b/tests/codegen/transmute-scalar.rs @@ -5,63 +5,53 @@ // With opaque ptrs in LLVM, `transmute` can load/store any `alloca` as any type, // without needing to pointercast, and SRoA will turn that into a `bitcast`. -// As such, there's no longer special-casing in `transmute` to attempt to -// generate `bitcast` ourselves, as that just made the IR longer. +// Thus memory-to-memory transmutes don't need to generate them ourselves. -// FIXME: That said, `bitcast`s could still be a valuable addition if they could -// be done in `rvalue_creates_operand`, and thus avoid the `alloca`s entirely. +// However, `bitcast`s and `ptrtoint`s and `inttoptr`s are still worth doing when +// that allows us to avoid the `alloca`s entirely; see `rvalue_creates_operand`. // CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float noundef %x) -// CHECK: store float %{{.*}}, ptr %0 -// CHECK-NEXT: %[[RES:.*]] = load i32, ptr %0 -// CHECK: ret i32 %[[RES]] +// CHECK: %0 = bitcast float %x to i32 +// CHECK-NEXT: ret i32 %0 #[no_mangle] pub fn f32_to_bits(x: f32) -> u32 { unsafe { std::mem::transmute(x) } } // CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 noundef zeroext %b) -// CHECK: %1 = zext i1 %b to i8 -// CHECK-NEXT: store i8 %1, {{.*}} %0 -// CHECK-NEXT: %2 = load i8, {{.*}} %0 -// CHECK: ret i8 %2 +// CHECK: %0 = zext i1 %b to i8 +// CHECK-NEXT: ret i8 %0 #[no_mangle] pub fn bool_to_byte(b: bool) -> u8 { unsafe { std::mem::transmute(b) } } // CHECK-LABEL: define{{.*}}noundef zeroext i1 @byte_to_bool(i8 noundef %byte) -// CHECK: store i8 %byte, ptr %0 -// CHECK-NEXT: %1 = load i8, {{.*}} %0 -// CHECK-NEXT: %2 = trunc i8 %1 to i1 -// CHECK: ret i1 %2 +// CHECK: %0 = trunc i8 %byte to i1 +// CHECK-NEXT: ret i1 %0 #[no_mangle] pub unsafe fn byte_to_bool(byte: u8) -> bool { std::mem::transmute(byte) } -// CHECK-LABEL: define{{.*}}{{i8\*|ptr}} @ptr_to_ptr({{i16\*|ptr}} noundef %p) -// CHECK: store {{i8\*|ptr}} %{{.*}}, {{.*}} %0 -// CHECK-NEXT: %[[RES:.*]] = load {{i8\*|ptr}}, {{.*}} %0 -// CHECK: ret {{i8\*|ptr}} %[[RES]] +// CHECK-LABEL: define{{.*}}ptr @ptr_to_ptr(ptr noundef %p) +// CHECK: ret ptr %p #[no_mangle] pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 { unsafe { std::mem::transmute(p) } } -// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int({{i16\*|ptr}} noundef %p) -// CHECK: store {{i16\*|ptr}} %p, {{.*}} -// CHECK-NEXT: %[[RES:.*]] = load [[USIZE]], {{.*}} %0 -// CHECK: ret [[USIZE]] %[[RES]] +// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(ptr noundef %p) +// CHECK: %0 = ptrtoint ptr %p to [[USIZE]] +// CHECK-NEXT: ret [[USIZE]] %0 #[no_mangle] pub fn ptr_to_int(p: *mut u16) -> usize { unsafe { std::mem::transmute(p) } } -// CHECK: define{{.*}}{{i16\*|ptr}} @int_to_ptr([[USIZE]] noundef %i) -// CHECK: store [[USIZE]] %i, {{.*}} -// CHECK-NEXT: %[[RES:.*]] = load {{i16\*|ptr}}, {{.*}} %0 -// CHECK: ret {{i16\*|ptr}} %[[RES]] +// CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] noundef %i) +// CHECK: %0 = inttoptr [[USIZE]] %i to ptr +// CHECK-NEXT: ret ptr %0 #[no_mangle] pub fn int_to_ptr(i: usize) -> *mut u16 { unsafe { std::mem::transmute(i) } From 422c33030f8d1137f78e4d9fef2777b12184e13f Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 5 Apr 2023 03:06:37 +0100 Subject: [PATCH 110/267] Disable path trimming during graphviz output --- compiler/rustc_mir_dataflow/src/framework/engine.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index 91c3bf0ad21f..2abdee064a68 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -15,6 +15,7 @@ use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::{self, traversal, BasicBlock}; use rustc_middle::mir::{create_dump_file, dump_enabled}; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; @@ -285,7 +286,7 @@ where if tcx.sess.opts.unstable_opts.graphviz_dark_mode { render_opts.push(dot::RenderOption::DarkTheme); } - dot::render_opts(&graphviz, &mut buf, &render_opts)?; + with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)?); file.write_all(&buf)?; From 4a4fc3bb5b1efe6857cf5d6c0b554ff36b966996 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 30 Mar 2023 03:51:27 +0000 Subject: [PATCH 111/267] Implement support for GeneratorWitnessMIR in new solver --- .../solve/trait_goals/structural_traits.rs | 49 +++++++++++++++++-- .../auto-with-drop_tracking_mir.fail.stderr | 18 +++++++ .../new-solver/auto-with-drop_tracking_mir.rs | 26 ++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr create mode 100644 tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs index 9817186b874c..a691b008e9d7 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs @@ -1,7 +1,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::{def_id::DefId, Movability, Mutability}; use rustc_infer::traits::query::NoSolution; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, +}; use crate::solve::EvalCtxt; @@ -60,7 +62,16 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()), - ty::GeneratorWitnessMIR(..) => todo!(), + ty::GeneratorWitnessMIR(def_id, substs) => Ok(ecx + .tcx() + .generator_hidden_types(def_id) + .map(|bty| { + ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars( + tcx, + bty.subst(tcx, substs), + )) + }) + .collect()), // For `PhantomData`, we pass `T`. ty::Adt(def, substs) if def.is_phantom_data() => Ok(vec![substs.type_at(0)]), @@ -76,6 +87,29 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>( } } +fn replace_erased_lifetimes_with_bound_vars<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, +) -> ty::Binder<'tcx, Ty<'tcx>> { + debug_assert!(!ty.has_late_bound_regions()); + let mut counter = 0; + let ty = tcx.fold_regions(ty, |mut r, current_depth| { + if let ty::ReErased = r.kind() { + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(counter), + kind: ty::BrAnon(counter, None), + }; + counter += 1; + r = tcx.mk_re_late_bound(current_depth, br); + } + r + }); + let bound_vars = tcx.mk_bound_variable_kinds_from_iter( + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))), + ); + ty::Binder::bind_with_vars(ty, bound_vars) +} + pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, @@ -178,7 +212,16 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()), - ty::GeneratorWitnessMIR(..) => todo!(), + ty::GeneratorWitnessMIR(def_id, substs) => Ok(ecx + .tcx() + .generator_hidden_types(def_id) + .map(|bty| { + ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars( + ecx.tcx(), + bty.subst(ecx.tcx(), substs), + )) + }) + .collect()), } } diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr new file mode 100644 index 000000000000..6a926534e079 --- /dev/null +++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr @@ -0,0 +1,18 @@ +error[E0277]: `impl Future` cannot be sent between threads safely + --> $DIR/auto-with-drop_tracking_mir.rs:24:13 + | +LL | is_send(foo()); + | ------- ^^^^^ `impl Future` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `impl Future` +note: required by a bound in `is_send` + --> $DIR/auto-with-drop_tracking_mir.rs:23:24 + | +LL | fn is_send(_: impl Send) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs new file mode 100644 index 000000000000..a5db7c4636b3 --- /dev/null +++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs @@ -0,0 +1,26 @@ +// compile-flags: -Ztrait-solver=next -Zdrop-tracking-mir +// edition: 2021 +// revisions: pass fail +//[pass] check-pass + +#![feature(negative_impls)] + +struct NotSync; +impl !Sync for NotSync {} + +async fn foo() { + #[cfg(pass)] + let x = &(); + #[cfg(fail)] + let x = &NotSync; + bar().await; + drop(x); +} + +async fn bar() {} + +fn main() { + fn is_send(_: impl Send) {} + is_send(foo()); + //[fail]~^ ERROR `impl Future` cannot be sent between threads safely +} From 786fc90855a368a90cdbad3163a2993efd793da4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 25 Mar 2023 20:10:41 +0000 Subject: [PATCH 112/267] Tweak debug outputs to make debugging new solver easier --- compiler/rustc_middle/src/infer/canonical.rs | 2 +- compiler/rustc_middle/src/traits/solve.rs | 4 +- .../src/solve/assembly.rs | 7 +++ .../src/solve/eval_ctxt.rs | 4 +- .../rustc_trait_selection/src/solve/mod.rs | 26 ++++++-- .../src/solve/search_graph/mod.rs | 1 + ..._of_reborrow.SimplifyCfg-initial.after.mir | 60 +++++++++---------- ...ignment.main.SimplifyCfg-initial.after.mir | 4 +- .../issue_101867.main.built.after.mir | 4 +- ...ceiver_ptr_mutability.main.built.after.mir | 8 +-- .../issue_72181_1.main.built.after.mir | 4 +- .../mir-opt/issue_99325.main.built.after.mir | 4 +- 12 files changed, 76 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 7f8fc17744dc..2f42849f390b 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -35,9 +35,9 @@ use std::ops::Index; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct Canonical<'tcx, V> { + pub value: V, pub max_universe: ty::UniverseIndex, pub variables: CanonicalVarInfos<'tcx>, - pub value: V, } pub type CanonicalVarInfos<'tcx> = &'tcx List>; diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 512d67f34b97..0d6f9813e767 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -20,8 +20,8 @@ pub type EvaluationCache<'tcx> = Cache, QueryResult<'tcx>>; /// we're currently typechecking while the `predicate` is some trait bound. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] pub struct Goal<'tcx, P> { - pub param_env: ty::ParamEnv<'tcx>, pub predicate: P, + pub param_env: ty::ParamEnv<'tcx>, } impl<'tcx, P> Goal<'tcx, P> { @@ -41,10 +41,10 @@ impl<'tcx, P> Goal<'tcx, P> { #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] pub struct Response<'tcx> { + pub certainty: Certainty, pub var_values: CanonicalVarValues<'tcx>, /// Additional constraints returned by this query. pub external_constraints: ExternalConstraints<'tcx>, - pub certainty: Certainty, } #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 856b1c08b723..f8a54f73a33e 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -270,6 +270,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { /// To deal with this, we first try to normalize the self type and add the candidates for the normalized /// self type to the list of candidates in case that succeeds. We also have to consider candidates with the /// projection as a self type as well + #[instrument(level = "debug", skip_all)] fn assemble_candidates_after_normalizing_self_ty>( &mut self, goal: Goal<'tcx, G>, @@ -315,6 +316,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + #[instrument(level = "debug", skip_all)] fn assemble_impl_candidates>( &mut self, goal: Goal<'tcx, G>, @@ -333,6 +335,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ); } + #[instrument(level = "debug", skip_all)] fn assemble_builtin_impl_candidates>( &mut self, goal: Goal<'tcx, G>, @@ -390,6 +393,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + #[instrument(level = "debug", skip_all)] fn assemble_param_env_candidates>( &mut self, goal: Goal<'tcx, G>, @@ -405,6 +409,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + #[instrument(level = "debug", skip_all)] fn assemble_alias_bound_candidates>( &mut self, goal: Goal<'tcx, G>, @@ -452,6 +457,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + #[instrument(level = "debug", skip_all)] fn assemble_object_bound_candidates>( &mut self, goal: Goal<'tcx, G>, @@ -514,6 +520,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + #[instrument(level = "debug", skip_all)] fn assemble_coherence_unknowable_candidates>( &mut self, goal: Goal<'tcx, G>, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 705e79aebd8c..cdbab5bd8d27 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -106,7 +106,7 @@ pub trait InferCtxtEvalExt<'tcx> { } impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self), ret)] fn evaluate_root_goal( &self, goal: Goal<'tcx, ty::Predicate<'tcx>>, @@ -552,7 +552,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { /// /// If possible, try using `eq` instead which automatically handles nested /// goals correctly. - #[instrument(level = "debug", skip(self, param_env), ret)] + #[instrument(level = "trace", skip(self, param_env), ret)] pub(super) fn eq_and_get_goals>( &self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index a96ec2c60f09..9ddae8f8dcd4 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -153,13 +153,22 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ) -> QueryResult<'tcx> { let tcx = self.tcx(); // We may need to invert the alias relation direction if dealing an alias on the RHS. + #[derive(Debug)] enum Invert { No, Yes, } let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other, direction, invert| { - debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other); + let span = tracing::span!( + tracing::Level::DEBUG, + "compute_alias_relate_goal(evaluate_normalizes_to)", + ?alias, + ?other, + ?direction, + ?invert + ); + let _enter = span.enter(); let result = ecx.probe(|ecx| { let other = match direction { // This is purely an optimization. @@ -184,7 +193,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { )); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }); - debug!("evaluate_normalizes_to({alias}, {other}, {direction:?}) -> {result:?}"); + debug!(?result); result }; @@ -210,7 +219,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } (Some(alias_lhs), Some(alias_rhs)) => { - debug!("compute_alias_relate_goal: both sides are aliases"); + debug!("both sides are aliases"); let candidates = vec![ // LHS normalizes-to RHS @@ -219,9 +228,14 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes), // Relate via substs self.probe(|ecx| { - debug!( - "compute_alias_relate_goal: alias defids are equal, equating substs" + let span = tracing::span!( + tracing::Level::DEBUG, + "compute_alias_relate_goal(relate_via_substs)", + ?alias_lhs, + ?alias_rhs, + ?direction ); + let _enter = span.enter(); match direction { ty::AliasRelationDirection::Equate => { @@ -275,6 +289,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { debug!("added_goals={:?}", &self.nested_goals.goals[current_len..]); } + #[instrument(level = "debug", skip(self, responses))] fn try_merge_responses( &mut self, responses: impl Iterator>, @@ -304,6 +319,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { }); // FIXME(-Ztrait-solver=next): We should take the intersection of the constraints on all the // responses and use that for the constraints of this ambiguous response. + debug!(">1 response, bailing with {certainty:?}"); let response = self.evaluate_added_goals_and_make_canonical_response(certainty); if let Ok(response) = &response { assert!(response.has_no_inference_or_external_constraints()); diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index aeb676660352..42c28686f5c1 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -209,6 +209,7 @@ impl<'tcx> SearchGraph<'tcx> { ) -> QueryResult<'tcx> { if self.should_use_global_cache() { if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_goal, tcx) { + debug!(?canonical_goal, ?result, "cache hit"); return result; } } diff --git a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir index 5f8b2f9312b7..b1d34a1962ec 100644 --- a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -1,36 +1,36 @@ // MIR for `address_of_reborrow` after SimplifyCfg-initial | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:7:5: 7:18, inferred_ty: *const [i32; 10] -| 1: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:9:5: 9:25, inferred_ty: *const dyn std::marker::Send -| 2: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:13:12: 13:20, inferred_ty: *const [i32; 10] -| 3: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:13:12: 13:20, inferred_ty: *const [i32; 10] -| 4: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address_of.rs:14:12: 14:28, inferred_ty: *const [i32; 10] -| 5: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address_of.rs:14:12: 14:28, inferred_ty: *const [i32; 10] -| 6: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:15:12: 15:27, inferred_ty: *const dyn std::marker::Send -| 7: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:15:12: 15:27, inferred_ty: *const dyn std::marker::Send -| 8: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address_of.rs:16:12: 16:24, inferred_ty: *const [i32] -| 9: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address_of.rs:16:12: 16:24, inferred_ty: *const [i32] -| 10: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:18:5: 18:18, inferred_ty: *const [i32; 10] -| 11: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:20:5: 20:25, inferred_ty: *const dyn std::marker::Send -| 12: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:23:12: 23:20, inferred_ty: *const [i32; 10] -| 13: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) }, span: $DIR/address_of.rs:23:12: 23:20, inferred_ty: *const [i32; 10] -| 14: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address_of.rs:24:12: 24:28, inferred_ty: *const [i32; 10] -| 15: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) }, span: $DIR/address_of.rs:24:12: 24:28, inferred_ty: *const [i32; 10] -| 16: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:25:12: 25:27, inferred_ty: *const dyn std::marker::Send -| 17: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) }, span: $DIR/address_of.rs:25:12: 25:27, inferred_ty: *const dyn std::marker::Send -| 18: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address_of.rs:26:12: 26:24, inferred_ty: *const [i32] -| 19: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) }, span: $DIR/address_of.rs:26:12: 26:24, inferred_ty: *const [i32] -| 20: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) }, span: $DIR/address_of.rs:28:5: 28:16, inferred_ty: *mut [i32; 10] -| 21: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) }, span: $DIR/address_of.rs:30:5: 30:23, inferred_ty: *mut dyn std::marker::Send -| 22: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) }, span: $DIR/address_of.rs:33:12: 33:18, inferred_ty: *mut [i32; 10] -| 23: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) }, span: $DIR/address_of.rs:33:12: 33:18, inferred_ty: *mut [i32; 10] -| 24: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) }, span: $DIR/address_of.rs:34:12: 34:26, inferred_ty: *mut [i32; 10] -| 25: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) }, span: $DIR/address_of.rs:34:12: 34:26, inferred_ty: *mut [i32; 10] -| 26: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) }, span: $DIR/address_of.rs:35:12: 35:25, inferred_ty: *mut dyn std::marker::Send -| 27: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) }, span: $DIR/address_of.rs:35:12: 35:25, inferred_ty: *mut dyn std::marker::Send -| 28: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32]) }, span: $DIR/address_of.rs:36:12: 36:22, inferred_ty: *mut [i32] -| 29: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32]) }, span: $DIR/address_of.rs:36:12: 36:22, inferred_ty: *mut [i32] +| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:7:5: 7:18, inferred_ty: *const [i32; 10] +| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:9:5: 9:25, inferred_ty: *const dyn std::marker::Send +| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:13:12: 13:20, inferred_ty: *const [i32; 10] +| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:13:12: 13:20, inferred_ty: *const [i32; 10] +| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:14:12: 14:28, inferred_ty: *const [i32; 10] +| 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:14:12: 14:28, inferred_ty: *const [i32; 10] +| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:15:12: 15:27, inferred_ty: *const dyn std::marker::Send +| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:15:12: 15:27, inferred_ty: *const dyn std::marker::Send +| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:16:12: 16:24, inferred_ty: *const [i32] +| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:16:12: 16:24, inferred_ty: *const [i32] +| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:18:5: 18:18, inferred_ty: *const [i32; 10] +| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:20:5: 20:25, inferred_ty: *const dyn std::marker::Send +| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:23:12: 23:20, inferred_ty: *const [i32; 10] +| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:23:12: 23:20, inferred_ty: *const [i32; 10] +| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:24:12: 24:28, inferred_ty: *const [i32; 10] +| 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:24:12: 24:28, inferred_ty: *const [i32; 10] +| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:25:12: 25:27, inferred_ty: *const dyn std::marker::Send +| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:25:12: 25:27, inferred_ty: *const dyn std::marker::Send +| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:26:12: 26:24, inferred_ty: *const [i32] +| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:26:12: 26:24, inferred_ty: *const [i32] +| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:28:5: 28:16, inferred_ty: *mut [i32; 10] +| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:30:5: 30:23, inferred_ty: *mut dyn std::marker::Send +| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:33:12: 33:18, inferred_ty: *mut [i32; 10] +| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:33:12: 33:18, inferred_ty: *mut [i32; 10] +| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:34:12: 34:26, inferred_ty: *mut [i32; 10] +| 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:34:12: 34:26, inferred_ty: *mut [i32; 10] +| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:35:12: 35:25, inferred_ty: *mut dyn std::marker::Send +| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:35:12: 35:25, inferred_ty: *mut dyn std::marker::Send +| 28: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:36:12: 36:22, inferred_ty: *mut [i32] +| 29: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:36:12: 36:22, inferred_ty: *mut [i32] | fn address_of_reborrow() -> () { let mut _0: (); // return place in scope 0 at $DIR/address_of.rs:+0:26: +0:26 diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir index f20b534259ad..6d1c7bd18dce 100644 --- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after SimplifyCfg-initial | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option>) }, span: $DIR/basic_assignment.rs:20:17: 20:33, inferred_ty: std::option::Option> -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option>) }, span: $DIR/basic_assignment.rs:20:17: 20:33, inferred_ty: std::option::Option> +| 0: user_ty: Canonical { value: Ty(std::option::Option>), max_universe: U0, variables: [] }, span: $DIR/basic_assignment.rs:20:17: 20:33, inferred_ty: std::option::Option> +| 1: user_ty: Canonical { value: Ty(std::option::Option>), max_universe: U0, variables: [] }, span: $DIR/basic_assignment.rs:20:17: 20:33, inferred_ty: std::option::Option> | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/basic_assignment.rs:+0:11: +0:11 diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir index 628a33f1020a..44c25ce673b8 100644 --- a/tests/mir-opt/building/issue_101867.main.built.after.mir +++ b/tests/mir-opt/building/issue_101867.main.built.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue_101867.rs:3:12: 3:22, inferred_ty: std::option::Option -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue_101867.rs:3:12: 3:22, inferred_ty: std::option::Option +| 0: user_ty: Canonical { value: Ty(std::option::Option), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:3:12: 3:22, inferred_ty: std::option::Option +| 1: user_ty: Canonical { value: Ty(std::option::Option), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:3:12: 3:22, inferred_ty: std::option::Option | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue_101867.rs:+0:11: +0:11 diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir index 41eb00363bd9..7a6944dee03a 100644 --- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir +++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir @@ -1,10 +1,10 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut Test) }, span: $DIR/receiver_ptr_mutability.rs:14:14: 14:23, inferred_ty: *mut Test -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(*mut Test) }, span: $DIR/receiver_ptr_mutability.rs:14:14: 14:23, inferred_ty: *mut Test -| 2: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], value: Ty(&&&&*mut Test) }, span: $DIR/receiver_ptr_mutability.rs:18:18: 18:31, inferred_ty: &&&&*mut Test -| 3: user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], value: Ty(&&&&*mut Test) }, span: $DIR/receiver_ptr_mutability.rs:18:18: 18:31, inferred_ty: &&&&*mut Test +| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:14:14: 14:23, inferred_ty: *mut Test +| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:14:14: 14:23, inferred_ty: *mut Test +| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:18:18: 18:31, inferred_ty: &&&&*mut Test +| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:18:18: 18:31, inferred_ty: &&&&*mut Test | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/receiver_ptr_mutability.rs:+0:11: +0:11 diff --git a/tests/mir-opt/issue_72181_1.main.built.after.mir b/tests/mir-opt/issue_72181_1.main.built.after.mir index 2172f3aa9e28..e1d896cbcfbe 100644 --- a/tests/mir-opt/issue_72181_1.main.built.after.mir +++ b/tests/mir-opt/issue_72181_1.main.built.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(Void) }, span: $DIR/issue_72181_1.rs:16:12: 16:16, inferred_ty: Void -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(Void) }, span: $DIR/issue_72181_1.rs:16:12: 16:16, inferred_ty: Void +| 0: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [] }, span: $DIR/issue_72181_1.rs:16:12: 16:16, inferred_ty: Void +| 1: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [] }, span: $DIR/issue_72181_1.rs:16:12: 16:16, inferred_ty: Void | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue_72181_1.rs:+0:11: +0:11 diff --git a/tests/mir-opt/issue_99325.main.built.after.mir b/tests/mir-opt/issue_99325.main.built.after.mir index 3e035c18db86..c08f03deeafa 100644 --- a/tests/mir-opt/issue_99325.main.built.after.mir +++ b/tests/mir-opt/issue_99325.main.built.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }) }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }) }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue_99325.rs:+0:15: +0:15 From 96102c7725e485f6222afedbfa5d381dc1e1219f Mon Sep 17 00:00:00 2001 From: Albert Larsan <74931857+albertlarsan68@users.noreply.github.com> Date: Mon, 23 Jan 2023 18:34:10 +0000 Subject: [PATCH 113/267] Add T-bootstrap label to tools --- triagebot.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 20a8be283b99..2d7be7d12734 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -186,13 +186,17 @@ trigger_files = [ "configure", "Cargo.toml", "config.example.toml", - "src/stage0.json" + "src/stage0.json", + "src/tools/compiletest", + "src/tools/tidy", ] [autolabel."T-infra"] trigger_files = [ "src/ci", "src/tools/bump-stage0", + "src/tools/cargotest", + "src/tools/tier-check", ] [autolabel."T-style"] From 6861750e663dbbf8c347e90a35e056d8d2e8c5b1 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Wed, 5 Apr 2023 00:37:30 -0700 Subject: [PATCH 114/267] Fix buffer overrun in (test-only) symlink_junction --- library/std/src/sys/windows/fs.rs | 34 +++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 373157bd9e83..956db577d537 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -1403,24 +1403,40 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> { opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); let f = File::open(junction, &opts)?; let h = f.as_inner().as_raw_handle(); - unsafe { let mut data = Align8([MaybeUninit::::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]); let data_ptr = data.0.as_mut_ptr(); + let data_end = data_ptr.add(c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE); let db = data_ptr.cast::(); // Zero the header to ensure it's fully initialized, including reserved parameters. *db = mem::zeroed(); - let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::(); - let mut i = 0; + let reparse_target_slice = { + let buf_start = ptr::addr_of_mut!((*db).ReparseTarget).cast::(); + // Compute offset in bytes and then divide so that we round down + // rather than hit any UB (admittedly this arithmetic should work + // out so that this isn't necessary) + let buf_len_bytes = usize::try_from(data_end.byte_offset_from(buf_start)).unwrap(); + let buf_len_wchars = buf_len_bytes / core::mem::size_of::(); + core::slice::from_raw_parts_mut(buf_start, buf_len_wchars) + }; + // FIXME: this conversion is very hacky - let v = br"\??\"; - let v = v.iter().map(|x| *x as u16); - for c in v.chain(original.as_os_str().encode_wide()) { - *buf.add(i) = c; + let iter = br"\??\" + .iter() + .map(|x| *x as u16) + .chain(original.as_os_str().encode_wide()) + .chain(core::iter::once(0)); + let mut i = 0; + for c in iter { + if i >= reparse_target_slice.len() { + return Err(crate::io::const_io_error!( + crate::io::ErrorKind::InvalidFilename, + "Input filename is too long" + )); + } + reparse_target_slice[i] = c; i += 1; } - *buf.add(i) = 0; - i += 1; (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT; (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD; (*db).ReparseTargetLength = ((i - 1) * 2) as c::WORD; From 12dff54a6acf271e367a8fb0c3d149d6554d9d90 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Wed, 5 Apr 2023 00:54:46 -0700 Subject: [PATCH 115/267] Fix same issue in bootstrap --- src/bootstrap/util.rs | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 9a6aaffe22b2..8cea8c974077 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -212,18 +212,35 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> { struct Align8(T); let mut data = Align8([0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]); let db = data.0.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER; - let buf = core::ptr::addr_of_mut!((*db).ReparseTarget) as *mut u16; - let mut i = 0; + let end = db.cast::().add(MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize); + let reparse_target_slice = { + let buf_start = core::ptr::addr_of_mut!((*db).ReparseTarget).cast::(); + // Compute offset in bytes and then divide so that we round down + // rather than hit any UB (admittedly this arithmetic should work + // out so that this isn't necessary) + let buf_len_bytes = + usize::try_from(end.offset_from(buf_start.cast::())).unwrap(); + let buf_len_wchars = buf_len_bytes / core::mem::size_of::(); + core::slice::from_raw_parts_mut(buf_start, buf_len_wchars) + }; + // FIXME: this conversion is very hacky - let v = br"\??\"; - let v = v.iter().map(|x| *x as u16); - for c in v.chain(target.as_os_str().encode_wide().skip(4)) { - *buf.offset(i) = c; + let iter = br"\??\" + .iter() + .map(|x| *x as u16) + .chain(path.iter().copied()) + .chain(core::iter::once(0)); + let mut i = 0; + for c in iter { + if i >= reparse_target_slice.len() { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("path too long for reparse target: {target:?}"), + )); + } + reparse_target_slice[i] = c; i += 1; } - *buf.offset(i) = 0; - i += 1; - (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; (*db).ReparseTargetMaximumLength = (i * 2) as u16; (*db).ReparseTargetLength = ((i - 1) * 2) as u16; From 457a162d008befc6baa9acde637f29780c079844 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 5 Apr 2023 08:07:29 +0000 Subject: [PATCH 116/267] Use elsa =1.7.1 as 1.8.0 was an accidental copy of 1.7.0 --- Cargo.lock | 4 ++-- compiler/rustc_data_structures/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c7bd689b2d86..07dcca0fd47b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,9 +1418,9 @@ dependencies = [ [[package]] name = "elsa" -version = "1.8.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f74077c3c3aedb99a2683919698285596662518ea13e5eedcf8bdd43b0d0453b" +checksum = "848fe615fbb0a74d9ae68dcaa510106d32e37d9416207bbea4bd008bd89c47ed" dependencies = [ "stable_deref_trait", ] diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 0b2b03da2080..24b6b5cfb1f7 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -32,7 +32,7 @@ stacker = "0.1.15" tempfile = "3.2" thin-vec = "0.2.12" tracing = "0.1" -elsa = "1.8" +elsa = "=1.7.1" [dependencies.parking_lot] version = "0.11" From 42e38e89498ec4690479b268066ad1ca58917aec Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Wed, 5 Apr 2023 01:27:11 -0700 Subject: [PATCH 117/267] Use the `junction` crate in bootstrap instead of manually creating the junction --- src/bootstrap/Cargo.lock | 11 ++++ src/bootstrap/Cargo.toml | 3 + src/bootstrap/util.rs | 116 +-------------------------------------- 3 files changed, 15 insertions(+), 115 deletions(-) diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 965dfa5f3986..a158d1f718e2 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -45,6 +45,7 @@ dependencies = [ "hex", "ignore", "is-terminal", + "junction", "libc", "object", "once_cell", @@ -349,6 +350,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +[[package]] +name = "junction" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca39ef0d69b18e6a2fd14c2f0a1d593200f4a4ed949b240b5917ab51fac754cb" +dependencies = [ + "scopeguard", + "winapi", +] + [[package]] name = "lazy_static" version = "1.4.0" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 2fbe7aa57aa5..eeda6d7c121f 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -61,6 +61,9 @@ sysinfo = { version = "0.26.0", optional = true } [target.'cfg(not(target_os = "solaris"))'.dependencies] fd-lock = "3.0.8" +[target.'cfg(windows)'.dependencies.junction] +version = "1.0.0" + [target.'cfg(windows)'.dependencies.windows] version = "0.46.0" features = [ diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 8cea8c974077..2e1adbf63bb1 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -146,123 +146,9 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> { fs::symlink(src, dest) } - // Creating a directory junction on windows involves dealing with reparse - // points and the DeviceIoControl function, and this code is a skeleton of - // what can be found here: - // - // http://www.flexhex.com/docs/articles/hard-links.phtml #[cfg(windows)] fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> { - use std::ffi::OsStr; - use std::os::windows::ffi::OsStrExt; - - use windows::{ - core::PCWSTR, - Win32::Foundation::{CloseHandle, HANDLE}, - Win32::Storage::FileSystem::{ - CreateFileW, FILE_ACCESS_FLAGS, FILE_FLAG_BACKUP_SEMANTICS, - FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, - MAXIMUM_REPARSE_DATA_BUFFER_SIZE, OPEN_EXISTING, - }, - Win32::System::Ioctl::FSCTL_SET_REPARSE_POINT, - Win32::System::SystemServices::{GENERIC_WRITE, IO_REPARSE_TAG_MOUNT_POINT}, - Win32::System::IO::DeviceIoControl, - }; - - #[allow(non_snake_case)] - #[repr(C)] - struct REPARSE_MOUNTPOINT_DATA_BUFFER { - ReparseTag: u32, - ReparseDataLength: u32, - Reserved: u16, - ReparseTargetLength: u16, - ReparseTargetMaximumLength: u16, - Reserved1: u16, - ReparseTarget: u16, - } - - fn to_u16s>(s: S) -> io::Result> { - Ok(s.as_ref().encode_wide().chain(Some(0)).collect()) - } - - // We're using low-level APIs to create the junction, and these are more - // picky about paths. For example, forward slashes cannot be used as a - // path separator, so we should try to canonicalize the path first. - let target = fs::canonicalize(target)?; - - fs::create_dir(junction)?; - - let path = to_u16s(junction)?; - - let h = unsafe { - CreateFileW( - PCWSTR(path.as_ptr()), - FILE_ACCESS_FLAGS(GENERIC_WRITE), - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - None, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, - HANDLE::default(), - ) - } - .map_err(|_| io::Error::last_os_error())?; - - unsafe { - #[repr(C, align(8))] - struct Align8(T); - let mut data = Align8([0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]); - let db = data.0.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER; - let end = db.cast::().add(MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize); - let reparse_target_slice = { - let buf_start = core::ptr::addr_of_mut!((*db).ReparseTarget).cast::(); - // Compute offset in bytes and then divide so that we round down - // rather than hit any UB (admittedly this arithmetic should work - // out so that this isn't necessary) - let buf_len_bytes = - usize::try_from(end.offset_from(buf_start.cast::())).unwrap(); - let buf_len_wchars = buf_len_bytes / core::mem::size_of::(); - core::slice::from_raw_parts_mut(buf_start, buf_len_wchars) - }; - - // FIXME: this conversion is very hacky - let iter = br"\??\" - .iter() - .map(|x| *x as u16) - .chain(path.iter().copied()) - .chain(core::iter::once(0)); - let mut i = 0; - for c in iter { - if i >= reparse_target_slice.len() { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("path too long for reparse target: {target:?}"), - )); - } - reparse_target_slice[i] = c; - i += 1; - } - (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; - (*db).ReparseTargetMaximumLength = (i * 2) as u16; - (*db).ReparseTargetLength = ((i - 1) * 2) as u16; - (*db).ReparseDataLength = ((*db).ReparseTargetLength + 12) as u32; - - let mut ret = 0u32; - DeviceIoControl( - h, - FSCTL_SET_REPARSE_POINT, - Some(db.cast()), - (*db).ReparseDataLength + 8, - None, - 0, - Some(&mut ret), - None, - ) - .ok() - .map_err(|_| io::Error::last_os_error())?; - } - - unsafe { CloseHandle(h) }; - Ok(()) + junction::create(&target, &junction) } } From 2175dab137d8e5e6b16f43d4089546e6ffe604d2 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 5 Apr 2023 12:40:04 +0200 Subject: [PATCH 118/267] Update to LLVM 16.0.1 --- .gitmodules | 2 +- src/llvm-project | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 0bbccb571302..4596ae17d023 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,7 +25,7 @@ [submodule "src/llvm-project"] path = src/llvm-project url = https://github.com/rust-lang/llvm-project.git - branch = rustc/16.0-2023-03-06 + branch = rustc/16.0-2023-04-05 [submodule "src/doc/embedded-book"] path = src/doc/embedded-book url = https://github.com/rust-embedded/book.git diff --git a/src/llvm-project b/src/llvm-project index 2b9c52f66815..585a6eb3ebf7 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 2b9c52f66815bb8d6ea74a4b26df3410602be9b0 +Subproject commit 585a6eb3ebf7c40fd7c1b23e3ece557b3cc2aa36 From 5a4066ebb788a81eaee6057bcd9c6487d210d8ca Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Wed, 5 Apr 2023 14:02:28 +0300 Subject: [PATCH 119/267] submodule detection for proper fix on #96188 This commit resolves an internal FIXME note within the bootstrap by implementing submodule detection. This is accomplished through an iterative process over the `.gitmodules` file. Signed-off-by: ozkanonur --- src/bootstrap/builder.rs | 50 ++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 4d528a767e43..ade8fa4c74dc 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -4,8 +4,9 @@ use std::collections::BTreeSet; use std::env; use std::ffi::OsStr; use std::fmt::{Debug, Write}; -use std::fs::{self}; +use std::fs::{self, File}; use std::hash::Hash; +use std::io::{BufRead, BufReader}; use std::ops::Deref; use std::path::{Component, Path, PathBuf}; use std::process::Command; @@ -28,8 +29,11 @@ use crate::{clean, dist}; use crate::{Build, CLang, DocTests, GitRepo, Mode}; pub use crate::Compiler; -// FIXME: replace with std::lazy after it gets stabilized and reaches beta -use once_cell::sync::Lazy; +// FIXME: +// - use std::lazy for `Lazy` +// - use std::cell for `OnceCell` +// Once they get stabilized and reach beta. +use once_cell::sync::{Lazy, OnceCell}; pub struct Builder<'a> { pub build: &'a Build, @@ -484,17 +488,43 @@ impl<'a> ShouldRun<'a> { // multiple aliases for the same job pub fn paths(mut self, paths: &[&str]) -> Self { + static SUBMODULES_PATHS: OnceCell> = OnceCell::new(); + + let init_submodules_paths = |src: &PathBuf| { + let file = File::open(src.join(".gitmodules")).unwrap(); + + let mut submodules_paths = vec![]; + for line in BufReader::new(file).lines() { + if let Ok(line) = line { + let line = line.trim(); + + if line.starts_with("path") { + let actual_path = + line.split(' ').last().expect("Couldn't get value of path"); + submodules_paths.push(actual_path.to_owned()); + } + } + } + + submodules_paths + }; + + let submodules_paths = + SUBMODULES_PATHS.get_or_init(|| init_submodules_paths(&self.builder.src)); + self.paths.insert(PathSet::Set( paths .iter() .map(|p| { - // FIXME(#96188): make sure this is actually a path. - // This currently breaks for paths within submodules. - //assert!( - // self.builder.src.join(p).exists(), - // "`should_run.paths` should correspond to real on-disk paths - use `alias` if there is no relevant path: {}", - // p - //); + // assert only if `p` isn't submodule + if !submodules_paths.iter().find(|sm_p| p.contains(*sm_p)).is_some() { + assert!( + self.builder.src.join(p).exists(), + "`should_run.paths` should correspond to real on-disk paths - use `alias` if there is no relevant path: {}", + p + ); + } + TaskPath { path: p.into(), kind: Some(self.kind) } }) .collect(), From a6810ccb258b6ca5a6436848f47ae91393822162 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 2 Apr 2023 19:45:27 -0400 Subject: [PATCH 120/267] Reduce the default max number of files in a UI test directory It doesn't make sense for the root directory to have a lower limit than subdirectories. --- src/tools/tidy/src/ui_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index f582666ab283..0f08f5d0b700 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -7,8 +7,8 @@ use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; -const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. +const ENTRY_LIMIT: usize = 885; const ROOT_ENTRY_LIMIT: usize = 881; const ISSUES_ENTRY_LIMIT: usize = 1978; From c0bc00174f0b033a689a12c108f0abddc3420f9f Mon Sep 17 00:00:00 2001 From: klensy Date: Wed, 5 Apr 2023 15:08:17 +0300 Subject: [PATCH 121/267] review --- compiler/rustc_codegen_llvm/src/consts.rs | 17 ++++++------- .../src/debuginfo/metadata.rs | 25 ++++++------------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 +-- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 2 +- 4 files changed, 16 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 9116e71beac8..940358acde9a 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -7,7 +7,6 @@ use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; use cstr::cstr; -use libc::c_uint; use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -486,10 +485,10 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { // go into custom sections of the wasm executable. if self.tcx.sess.target.is_like_wasm { if let Some(section) = attrs.link_section { - let section = llvm::LLVMMDStringInContext( + let section = llvm::LLVMMDStringInContext2( self.llcx, section.as_str().as_ptr().cast(), - section.as_str().len() as c_uint, + section.as_str().len(), ); assert!(alloc.provenance().ptrs().is_empty()); @@ -498,17 +497,15 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { // as part of the interpreter execution). let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()); - let alloc = llvm::LLVMMDStringInContext( - self.llcx, - bytes.as_ptr().cast(), - bytes.len() as c_uint, - ); + let alloc = + llvm::LLVMMDStringInContext2(self.llcx, bytes.as_ptr().cast(), bytes.len()); let data = [section, alloc]; - let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2); + let meta = llvm::LLVMMDNodeInContext2(self.llcx, data.as_ptr(), data.len()); + let val = llvm::LLVMMetadataAsValue(self.llcx, meta); llvm::LLVMAddNamedMetadataOperand( self.llmod, "wasm.custom_sections\0".as_ptr().cast(), - meta, + val, ); } } else { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 78197ca8529a..0ff206cda6c9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -881,8 +881,6 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( ); if tcx.sess.opts.unstable_opts.profile { - let cu_desc_metadata = - llvm::LLVMMetadataAsValue(debug_context.llcontext, unit_metadata); let default_gcda_path = &output_filenames.with_extension("gcda"); let gcda_path = tcx.sess.opts.unstable_opts.profile_emit.as_ref().unwrap_or(default_gcda_path); @@ -890,20 +888,17 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( let gcov_cu_info = [ path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")), path_to_mdstring(debug_context.llcontext, gcda_path), - cu_desc_metadata, + unit_metadata, ]; - let gcov_metadata = llvm::LLVMMDNodeInContext( + let gcov_metadata = llvm::LLVMMDNodeInContext2( debug_context.llcontext, gcov_cu_info.as_ptr(), - gcov_cu_info.len() as c_uint, + gcov_cu_info.len(), ); + let val = llvm::LLVMMetadataAsValue(debug_context.llcontext, gcov_metadata); let llvm_gcov_ident = cstr!("llvm.gcov"); - llvm::LLVMAddNamedMetadataOperand( - debug_context.llmod, - llvm_gcov_ident.as_ptr(), - gcov_metadata, - ); + llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, llvm_gcov_ident.as_ptr(), val); } // Insert `llvm.ident` metadata on the wasm targets since that will @@ -924,15 +919,9 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( return unit_metadata; }; - fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { + fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll llvm::Metadata { let path_str = path_to_c_string(path); - unsafe { - llvm::LLVMMDStringInContext( - llcx, - path_str.as_ptr(), - path_str.as_bytes().len() as c_uint, - ) - } + unsafe { llvm::LLVMMDStringInContext2(llcx, path_str.as_ptr(), path_str.as_bytes().len()) } } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 836fa8779f28..dc498f784b31 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1075,7 +1075,6 @@ extern "C" { // FIXME: deprecated, replace with LLVMMDStringInContext2 pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value; - // LLVMMDStringInContext but don't own string pub fn LLVMMDStringInContext2(C: &Context, Str: *const c_char, SLen: size_t) -> &Metadata; // FIXME: deprecated, replace with LLVMMDNodeInContext2 @@ -1117,7 +1116,7 @@ extern "C" { Packed: Bool, ) -> &'a Value; - // FIXME: replace with LLVMConstArray2 + // FIXME: replace with LLVMConstArray2 when bumped minimal version to llvm-17 // https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc pub fn LLVMConstArray<'a>( ElementTy: &'a Type, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 578bc3ea6421..29e5b7d494d8 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1137,7 +1137,7 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, } // LLVMArrayType function does not support 64-bit ElementCount -// FIXME: replace with LLVMArrayType2 +// FIXME: replace with LLVMArrayType2 when bumped minimal version to llvm-17 // https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, uint64_t ElementCount) { From 2df3f490dd71e50fd074ade846397f4ac9cbb6f7 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 5 Apr 2023 21:20:07 +0900 Subject: [PATCH 122/267] Add regression test for #80409 Signed-off-by: Yuki Okushi --- tests/ui/inference/issue-80409.rs | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/ui/inference/issue-80409.rs diff --git a/tests/ui/inference/issue-80409.rs b/tests/ui/inference/issue-80409.rs new file mode 100644 index 000000000000..80cad6dfc46e --- /dev/null +++ b/tests/ui/inference/issue-80409.rs @@ -0,0 +1,36 @@ +// check-pass + +#![allow(unreachable_code, unused)] + +use std::marker::PhantomData; + +struct FsmBuilder { + _fsm: PhantomData, +} + +impl FsmBuilder { + fn state(&mut self) -> FsmStateBuilder { + todo!() + } +} + +struct FsmStateBuilder { + _state: PhantomData, +} + +impl FsmStateBuilder { + fn on_entry)>(&self, _action: TAction) {} +} + +trait Fsm { + type Context; +} + +struct StateContext<'a, TFsm: Fsm> { + context: &'a mut TFsm::Context, +} + +fn main() { + let mut builder: FsmBuilder = todo!(); + builder.state().on_entry(|_| {}); +} From b8e90766b596df4cad9ed0256eed5ba445c7e4ae Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 5 Apr 2023 21:32:13 +0900 Subject: [PATCH 123/267] Add regression test for #86351 Signed-off-by: Yuki Okushi --- tests/ui/const_prop/issue-86351.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/ui/const_prop/issue-86351.rs diff --git a/tests/ui/const_prop/issue-86351.rs b/tests/ui/const_prop/issue-86351.rs new file mode 100644 index 000000000000..b5f1e7f7449a --- /dev/null +++ b/tests/ui/const_prop/issue-86351.rs @@ -0,0 +1,22 @@ +// compile-flags: --crate-type=lib -Zmir-opt-level=2 +// build-pass +// ^-- Must be build-pass, because check-pass will not run const prop. + +pub trait TestTrait { + type MyType; + fn func() -> Option + where + Self: Sized; +} + +impl dyn TestTrait +where + Self: Sized, +{ + pub fn other_func() -> Option { + match Self::func() { + Some(me) => Some(me), + None => None, + } + } +} From 689beda166719ba423faa8ceaab009b85cf03c4a Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 5 Apr 2023 13:25:04 +0000 Subject: [PATCH 124/267] Implement `OwnedSlice` --- compiler/rustc_data_structures/src/lib.rs | 3 + .../rustc_data_structures/src/owned_slice.rs | 113 ++++++++++++++++++ compiler/rustc_data_structures/src/sync.rs | 9 +- 3 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 compiler/rustc_data_structures/src/owned_slice.rs diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 9b52638e6124..62e22127b77c 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -27,6 +27,8 @@ #![feature(thread_id_value)] #![feature(vec_into_raw_parts)] #![feature(get_mut_unchecked)] +#![feature(lint_reasons)] +#![feature(unwrap_infallible)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] @@ -82,6 +84,7 @@ pub mod vec_linked_list; pub mod work_queue; pub use atomic_ref::AtomicRef; pub mod frozen; +pub mod owned_slice; pub mod sso; pub mod steal; pub mod tagged_ptr; diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs new file mode 100644 index 000000000000..dce209adfaa8 --- /dev/null +++ b/compiler/rustc_data_structures/src/owned_slice.rs @@ -0,0 +1,113 @@ +use std::{borrow::Borrow, ops::Deref}; + +// Use our fake Send/Sync traits when on not parallel compiler, +// so that `OwnedSlice` only implements/requires Send/Sync +// for parallel compiler builds. +use crate::sync::{Send, Sync}; + +/// An owned slice. +/// +/// This is similar to `Box<[u8]>` but allows slicing and using anything as the +/// backing buffer. +/// +/// See [`slice_owned`] for `OwnedSlice` construction and examples. +/// +/// --------------------------------------------------------------------------- +/// +/// This is essentially a replacement for `owning_ref` which is a lot simpler +/// and even sound! 🌸 +pub struct OwnedSlice { + /// This is conceptually a `&'self.owner [u8]`. + bytes: *const [u8], + + // +---------------------------------------+ + // | We expect `dead_code` lint here, | + // | because we don't want to accidentally | + // | touch the owner — otherwise the owner | + // | could invalidate out `bytes` pointer | + // | | + // | so be quite | + // +----+ +-------------------------------+ + // \/ + // ⊂(´・◡・⊂ )∘˚˳° + #[expect(dead_code)] + owner: Box, +} + +/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function. +/// +/// ## Examples +/// +/// ```rust +/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned}; +/// let vec = vec![1, 2, 3, 4]; +/// +/// // Identical to slicing via `&v[1..3]` but produces an owned slice +/// let slice: OwnedSlice = slice_owned(vec, |v| &v[1..3]); +/// assert_eq!(&*slice, [2, 3]); +/// ``` +/// +/// ```rust +/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned}; +/// # use std::ops::Deref; +/// let vec = vec![1, 2, 3, 4]; +/// +/// // Identical to slicing via `&v[..]` but produces an owned slice +/// let slice: OwnedSlice = slice_owned(vec, Deref::deref); +/// assert_eq!(&*slice, [1, 2, 3, 4]); +/// ``` +pub fn slice_owned(owner: O, slicer: F) -> OwnedSlice +where + O: Send + Sync + 'static, + F: Fn(&O) -> &[u8], +{ + try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok() +} + +/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function that can fail. +/// +/// See [`slice_owned`] for the infallible version. +pub fn try_slice_owned(owner: O, slicer: F) -> Result +where + O: Send + Sync + 'static, + F: Fn(&O) -> Result<&[u8], E>, +{ + // We box the owner of the bytes, so it doesn't move. + // + // Since the owner does not move and we don't access it in any way + // before drop, there is nothing that can invalidate the bytes pointer. + // + // Thus, "extending" the lifetime of the reference returned from `F` is fine. + // We pretend that we pass it a reference that lives as long as the returned slice. + // + // N.B. the HRTB on the `slicer` is important — without it the caller could provide + // a short lived slice, unrelated to the owner. + + let owner = Box::new(owner); + let bytes = slicer(&*owner)?; + + Ok(OwnedSlice { bytes, owner }) +} + +impl Deref for OwnedSlice { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + // Safety: + // `self.bytes` is valid per the construction in `slice_owned` + // (which is the only constructor) + unsafe { &*self.bytes } + } +} + +impl Borrow<[u8]> for OwnedSlice { + fn borrow(&self) -> &[u8] { + self + } +} + +// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box)`, which is `Send` +unsafe impl Send for OwnedSlice {} + +// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box)`, which is `Sync` +unsafe impl Sync for OwnedSlice {} diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 4e2126fff7be..8a53e28034b7 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -57,11 +57,8 @@ mod vec; cfg_if! { if #[cfg(not(parallel_compiler))] { - pub auto trait Send {} - pub auto trait Sync {} - - impl Send for T {} - impl Sync for T {} + pub unsafe auto trait Send {} + pub unsafe auto trait Sync {} #[macro_export] macro_rules! rustc_erase_owner { @@ -69,6 +66,8 @@ cfg_if! { $v.erase_owner() } } + unsafe impl Send for T {} + unsafe impl Sync for T {} use std::ops::Add; From c0ceefdfaf9a1e131bfbf4849bbaaac23af621a4 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 5 Apr 2023 13:26:26 +0000 Subject: [PATCH 125/267] Use `OwnedSlice` instead of `owning_ref` --- .../rustc_codegen_ssa/src/back/metadata.rs | 13 +++++------ compiler/rustc_data_structures/src/sync.rs | 6 ++--- compiler/rustc_metadata/src/lib.rs | 2 -- compiler/rustc_metadata/src/locator.rs | 22 +++++++++---------- compiler/rustc_metadata/src/rmeta/decoder.rs | 6 ----- .../src/rmeta/def_path_hash_map.rs | 14 ++++++------ 6 files changed, 27 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 4ab56699922f..c0f263d14781 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -13,8 +13,7 @@ use object::{ use snap::write::FrameEncoder; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::owning_ref::OwningRef; -use rustc_data_structures::rustc_erase_owner; +use rustc_data_structures::owned_slice::try_slice_owned; use rustc_data_structures::sync::MetadataRef; use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; @@ -38,14 +37,14 @@ pub struct DefaultMetadataLoader; fn load_metadata_with( path: &Path, - f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>, + f: impl for<'a> Fn(&'a [u8]) -> Result<&'a [u8], String>, ) -> Result { let file = File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?; - let data = unsafe { Mmap::map(file) } - .map_err(|e| format!("failed to mmap file '{}': {}", path.display(), e))?; - let metadata = OwningRef::new(data).try_map(f)?; - return Ok(rustc_erase_owner!(metadata.map_owner_box())); + + unsafe { Mmap::map(file) } + .map_err(|e| format!("failed to mmap file '{}': {}", path.display(), e)) + .and_then(|mmap| try_slice_owned(mmap, |mmap| f(mmap))) } impl MetadataLoader for DefaultMetadataLoader { diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 8a53e28034b7..855a7eb331f8 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -42,7 +42,7 @@ //! //! [^2] `MTLockRef` is a typedef. -use crate::owning_ref::{Erased, OwningRef}; +use crate::owned_slice::OwnedSlice; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; use std::ops::{Deref, DerefMut}; @@ -188,7 +188,7 @@ cfg_if! { } } - pub type MetadataRef = OwningRef, [u8]>; + pub type MetadataRef = OwnedSlice; pub use std::rc::Rc as Lrc; pub use std::rc::Weak as Weak; @@ -371,7 +371,7 @@ cfg_if! { }); } - pub type MetadataRef = OwningRef, [u8]>; + pub type MetadataRef = OwnedSlice; /// This makes locks panic if they are already held. /// It is only useful when you are running in a single thread diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 880da5ca5937..81e62eccb8a5 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -22,8 +22,6 @@ extern crate proc_macro; extern crate rustc_macros; #[macro_use] extern crate rustc_middle; -#[macro_use] -extern crate rustc_data_structures; #[macro_use] extern crate tracing; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 79c42a128e79..2515269ea2ff 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -218,7 +218,7 @@ use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::owning_ref::OwningRef; +use rustc_data_structures::owned_slice::slice_owned; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg}; @@ -236,6 +236,7 @@ use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; use std::borrow::Cow; use std::io::{Read, Result as IoResult, Write}; +use std::ops::Deref; use std::path::{Path, PathBuf}; use std::{cmp, fmt}; @@ -814,15 +815,14 @@ fn get_metadata_section<'p>( // Assume the decompressed data will be at least the size of the compressed data, so we // don't have to grow the buffer as much. let mut inflated = Vec::with_capacity(compressed_bytes.len()); - match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) { - Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()), - Err(_) => { - return Err(MetadataError::LoadFailure(format!( - "failed to decompress metadata: {}", - filename.display() - ))); - } - } + FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated).map_err(|_| { + MetadataError::LoadFailure(format!( + "failed to decompress metadata: {}", + filename.display() + )) + })?; + + slice_owned(inflated, Deref::deref) } CrateFlavor::Rmeta => { // mmap the file, because only a small fraction of it is read. @@ -840,7 +840,7 @@ fn get_metadata_section<'p>( )) })?; - rustc_erase_owner!(OwningRef::new(mmap).map_owner_box()) + slice_owned(mmap, Deref::deref) } }; let blob = MetadataBlob::new(raw_bytes); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 43e5946f3135..b5390e52c85f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -51,12 +51,6 @@ mod cstore_impl; #[derive(Clone)] pub(crate) struct MetadataBlob(Lrc); -// This is needed so we can create an OwningRef into the blob. -// The data behind a `MetadataBlob` has a stable address because it is -// contained within an Rc/Arc. -unsafe impl rustc_data_structures::owning_ref::StableAddress for MetadataBlob {} - -// This is needed so we can create an OwningRef into the blob. impl std::ops::Deref for MetadataBlob { type Target = [u8]; diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index a6133f1b417a..02cab561b8f6 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -1,14 +1,14 @@ use crate::rmeta::DecodeContext; use crate::rmeta::EncodeContext; -use crate::rmeta::MetadataBlob; -use rustc_data_structures::owning_ref::OwningRef; +use rustc_data_structures::owned_slice::slice_owned; +use rustc_data_structures::owned_slice::OwnedSlice; use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; use rustc_middle::parameterized_over_tcx; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::def_id::{DefIndex, DefPathHash}; pub(crate) enum DefPathHashMapRef<'tcx> { - OwnedFromMetadata(odht::HashTable>), + OwnedFromMetadata(odht::HashTable), BorrowedFromTcx(&'tcx DefPathHashMap), } @@ -50,11 +50,11 @@ impl<'a, 'tcx> Decodable> for DefPathHashMapRef<'static> let len = d.read_usize(); let pos = d.position(); - let o = OwningRef::new(d.blob().clone()).map(|x| &x[pos..pos + len]); + let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]); - // Although we already have the data we need via the OwningRef, we still need - // to advance the DecodeContext's position so it's in a valid state after - // the method. We use read_raw_bytes() for that. + // Although we already have the data we need via the `OwnedSlice`, we still need + // to advance the `DecodeContext`'s position so it's in a valid state after + // the method. We use `read_raw_bytes()` for that. let _ = d.read_raw_bytes(len); let inner = odht::HashTable::from_raw_bytes(o).unwrap_or_else(|e| { From d7056548f9dd51d44d9d29fd0376ac509605076b Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 5 Apr 2023 13:28:25 +0000 Subject: [PATCH 126/267] Yeet `owning_ref` Turns out - `owning_ref` is unsound due to `Box` aliasing stuff - `rustc` doesn't need 99% of the `owning_ref` API - `rustc` can use a far simpler abstraction that is `OwnedSlice` --- compiler/rustc_data_structures/src/lib.rs | 1 - compiler/rustc_data_structures/src/memmap.rs | 10 +- .../src/owning_ref/LICENSE | 21 - .../src/owning_ref/mod.rs | 1211 ----------------- .../src/owning_ref/tests.rs | 711 ---------- compiler/rustc_data_structures/src/sync.rs | 18 - 6 files changed, 1 insertion(+), 1971 deletions(-) delete mode 100644 compiler/rustc_data_structures/src/owning_ref/LICENSE delete mode 100644 compiler/rustc_data_structures/src/owning_ref/mod.rs delete mode 100644 compiler/rustc_data_structures/src/owning_ref/tests.rs diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 62e22127b77c..47d8c84ba205 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -61,7 +61,6 @@ pub mod intern; pub mod jobserver; pub mod macros; pub mod obligation_forest; -pub mod owning_ref; pub mod sip128; pub mod small_c_str; pub mod small_str; diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs index 3d44e17f31d1..1556873f5976 100644 --- a/compiler/rustc_data_structures/src/memmap.rs +++ b/compiler/rustc_data_structures/src/memmap.rs @@ -2,9 +2,7 @@ use std::fs::File; use std::io; use std::ops::{Deref, DerefMut}; -use crate::owning_ref::StableAddress; - -/// A trivial wrapper for [`memmap2::Mmap`] that implements [`StableAddress`]. +/// A trivial wrapper for [`memmap2::Mmap`] (or `Vec` on WASM). #[cfg(not(target_arch = "wasm32"))] pub struct Mmap(memmap2::Mmap); @@ -46,12 +44,6 @@ impl AsRef<[u8]> for Mmap { } } -// SAFETY: On architectures other than WASM, mmap is used as backing storage. The address of this -// memory map is stable. On WASM, `Vec` is used as backing storage. The `Mmap` type doesn't -// export any function that can cause the `Vec` to be re-allocated. As such the address of the -// bytes inside this `Vec` is stable. -unsafe impl StableAddress for Mmap {} - #[cfg(not(target_arch = "wasm32"))] pub struct MmapMut(memmap2::MmapMut); diff --git a/compiler/rustc_data_structures/src/owning_ref/LICENSE b/compiler/rustc_data_structures/src/owning_ref/LICENSE deleted file mode 100644 index dff72d1e4325..000000000000 --- a/compiler/rustc_data_structures/src/owning_ref/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Marvin Löbel - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs deleted file mode 100644 index d1d92b905b82..000000000000 --- a/compiler/rustc_data_structures/src/owning_ref/mod.rs +++ /dev/null @@ -1,1211 +0,0 @@ -#![warn(missing_docs)] - -/*! -# An owning reference. - -This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut` -that enables it to bundle a reference together with the owner of the data it points to. -This allows moving and dropping of an `OwningRef` without needing to recreate the reference. - -This can sometimes be useful because Rust borrowing rules normally prevent -moving a type that has been moved from. For example, this kind of code gets rejected: - -```compile_fail,E0515 -fn return_owned_and_referenced<'a>() -> (Vec, &'a [u8]) { - let v = vec![1, 2, 3, 4]; - let s = &v[1..3]; - (v, s) -} -``` - -Even though, from a memory-layout point of view, this can be entirely safe -if the new location of the vector still lives longer than the lifetime `'a` -of the reference because the backing allocation of the vector does not change. - -This library enables this safe usage by keeping the owner and the reference -bundled together in a wrapper type that ensure that lifetime constraint: - -``` -# use rustc_data_structures::owning_ref::OwningRef; -# fn main() { -fn return_owned_and_referenced() -> OwningRef, [u8]> { - let v = vec![1, 2, 3, 4]; - let or = OwningRef::new(v); - let or = or.map(|v| &v[1..3]); - or -} -# } -``` - -It works by requiring owner types to dereference to stable memory locations -and preventing mutable access to root containers, which in practice requires heap allocation -as provided by `Box`, `Rc`, etc. - -Also provided are typedefs for common owner type combinations, -which allow for less verbose type signatures. -For example, `BoxRef` instead of `OwningRef, T>`. - -The crate also provides the more advanced `OwningHandle` type, -which allows more freedom in bundling a dependent handle object -along with the data it depends on, at the cost of some unsafe needed in the API. -See the documentation around `OwningHandle` for more details. - -# Examples - -## Basics - -``` -use rustc_data_structures::owning_ref::BoxRef; - -fn main() { - // Create an array owned by a Box. - let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>; - - // Transfer into a BoxRef. - let arr: BoxRef<[i32]> = BoxRef::new(arr); - assert_eq!(&*arr, &[1, 2, 3, 4]); - - // We can slice the array without losing ownership or changing type. - let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]); - assert_eq!(&*arr, &[2, 3]); - - // Also works for Arc, Rc, String and Vec! -} -``` - -## Caching a reference to a struct field - -``` -use rustc_data_structures::owning_ref::BoxRef; - -fn main() { - struct Foo { - tag: u32, - x: u16, - y: u16, - z: u16, - } - let foo = Foo { tag: 1, x: 100, y: 200, z: 300 }; - - let or = BoxRef::new(Box::new(foo)).map(|foo| { - match foo.tag { - 0 => &foo.x, - 1 => &foo.y, - 2 => &foo.z, - _ => panic!(), - } - }); - - assert_eq!(*or, 200); -} -``` - -## Caching a reference to an entry in a vector - -``` -use rustc_data_structures::owning_ref::VecRef; - -fn main() { - let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]); - assert_eq!(*v, 4); -} -``` - -## Caching a subslice of a String - -``` -use rustc_data_structures::owning_ref::StringRef; - -fn main() { - let s = StringRef::new("hello world".to_owned()) - .map(|s| s.split(' ').nth(1).unwrap()); - - assert_eq!(&*s, "world"); -} -``` - -## Reference counted slices that share ownership of the backing storage - -``` -use rustc_data_structures::owning_ref::RcRef; -use std::rc::Rc; - -fn main() { - let rc: RcRef<[i32]> = RcRef::new(Rc::new([1, 2, 3, 4]) as Rc<[i32]>); - assert_eq!(&*rc, &[1, 2, 3, 4]); - - let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]); - let rc_b = rc.clone().map(|s| &s[1..3]); - let rc_c = rc.clone().map(|s| &s[2..4]); - assert_eq!(&*rc_a, &[1, 2]); - assert_eq!(&*rc_b, &[2, 3]); - assert_eq!(&*rc_c, &[3, 4]); - - let rc_c_a = rc_c.clone().map(|s| &s[1]); - assert_eq!(&*rc_c_a, &4); -} -``` - -## Atomic reference counted slices that share ownership of the backing storage - -``` -use rustc_data_structures::owning_ref::ArcRef; -use std::sync::Arc; - -fn main() { - use std::thread; - - fn par_sum(rc: ArcRef<[i32]>) -> i32 { - if rc.len() == 0 { - return 0; - } else if rc.len() == 1 { - return rc[0]; - } - let mid = rc.len() / 2; - let left = rc.clone().map(|s| &s[..mid]); - let right = rc.map(|s| &s[mid..]); - - let left = thread::spawn(move || par_sum(left)); - let right = thread::spawn(move || par_sum(right)); - - left.join().unwrap() + right.join().unwrap() - } - - let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]); - let rc: ArcRef<[i32]> = rc.into(); - - assert_eq!(par_sum(rc), 10); -} -``` - -## References into RAII locks - -``` -use rustc_data_structures::owning_ref::RefRef; -use std::cell::{RefCell, Ref}; - -fn main() { - let refcell = RefCell::new((1, 2, 3, 4)); - // Also works with Mutex and RwLock - - let refref = { - let refref = RefRef::new(refcell.borrow()).map(|x| &x.3); - assert_eq!(*refref, 4); - - // We move the RAII lock and the reference to one of - // the subfields in the data it guards here: - refref - }; - - assert_eq!(*refref, 4); - - drop(refref); - - assert_eq!(*refcell.borrow(), (1, 2, 3, 4)); -} -``` - -## Mutable reference - -When the owned container implements `DerefMut`, it is also possible to make -a _mutable owning reference_. (e.g., with `Box`, `RefMut`, `MutexGuard`) - -``` -use rustc_data_structures::owning_ref::RefMutRefMut; -use std::cell::{RefCell, RefMut}; - -fn main() { - let refcell = RefCell::new((1, 2, 3, 4)); - - let mut refmut_refmut = { - let mut refmut_refmut = RefMutRefMut::new(refcell.borrow_mut()).map_mut(|x| &mut x.3); - assert_eq!(*refmut_refmut, 4); - *refmut_refmut *= 2; - - refmut_refmut - }; - - assert_eq!(*refmut_refmut, 8); - *refmut_refmut *= 2; - - drop(refmut_refmut); - - assert_eq!(*refcell.borrow(), (1, 2, 3, 16)); -} -``` -*/ - -pub use stable_deref_trait::{ - CloneStableDeref as CloneStableAddress, StableDeref as StableAddress, -}; -use std::mem; - -/// An owning reference. -/// -/// This wraps an owner `O` and a reference `&T` pointing -/// at something reachable from `O::Target` while keeping -/// the ability to move `self` around. -/// -/// The owner is usually a pointer that points at some base type. -/// -/// For more details and examples, see the module and method docs. -pub struct OwningRef { - owner: O, - reference: *const T, -} - -/// An mutable owning reference. -/// -/// This wraps an owner `O` and a reference `&mut T` pointing -/// at something reachable from `O::Target` while keeping -/// the ability to move `self` around. -/// -/// The owner is usually a pointer that points at some base type. -/// -/// For more details and examples, see the module and method docs. -pub struct OwningRefMut { - owner: O, - reference: *mut T, -} - -/// Helper trait for an erased concrete type an owner dereferences to. -/// This is used in form of a trait object for keeping -/// something around to (virtually) call the destructor. -pub trait Erased {} -impl Erased for T {} - -/// Helper trait for erasing the concrete type of what an owner dereferences to, -/// for example `Box -> Box`. This would be unneeded with -/// higher kinded types support in the language. -#[allow(unused_lifetimes)] -pub unsafe trait IntoErased<'a> { - /// Owner with the dereference type substituted to `Erased`. - type Erased; - /// Performs the type erasure. - fn into_erased(self) -> Self::Erased; -} - -/// Helper trait for erasing the concrete type of what an owner dereferences to, -/// for example `Box -> Box`. This would be unneeded with -/// higher kinded types support in the language. -#[allow(unused_lifetimes)] -pub unsafe trait IntoErasedSend<'a> { - /// Owner with the dereference type substituted to `Erased + Send`. - type Erased: Send; - /// Performs the type erasure. - fn into_erased_send(self) -> Self::Erased; -} - -/// Helper trait for erasing the concrete type of what an owner dereferences to, -/// for example `Box -> Box`. This would be unneeded with -/// higher kinded types support in the language. -#[allow(unused_lifetimes)] -pub unsafe trait IntoErasedSendSync<'a> { - /// Owner with the dereference type substituted to `Erased + Send + Sync`. - type Erased: Send + Sync; - /// Performs the type erasure. - fn into_erased_send_sync(self) -> Self::Erased; -} - -///////////////////////////////////////////////////////////////////////////// -// OwningRef -///////////////////////////////////////////////////////////////////////////// - -impl OwningRef { - /// Creates a new owning reference from an owner - /// initialized to the direct dereference of it. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new(42)); - /// assert_eq!(*owning_ref, 42); - /// } - /// ``` - pub fn new(o: O) -> Self - where - O: StableAddress, - O: Deref, - { - OwningRef { reference: &*o, owner: o } - } - - /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. - /// Instead, the caller is responsible to make the same promises as implementing the trait. - /// - /// This is useful for cases where coherence rules prevents implementing the trait - /// without adding a dependency to this crate in a third-party library. - pub unsafe fn new_assert_stable_address(o: O) -> Self - where - O: Deref, - { - OwningRef { reference: &*o, owner: o } - } - - /// Converts `self` into a new owning reference that points at something reachable - /// from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref.map(|array| &array[2]); - /// assert_eq!(*owning_ref, 3); - /// } - /// ``` - pub fn map(self, f: F) -> OwningRef - where - O: StableAddress, - F: FnOnce(&T) -> &U, - { - OwningRef { reference: f(&self), owner: self.owner } - } - - /// Tries to convert `self` into a new owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref.try_map(|array| { - /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref.unwrap(), 3); - /// } - /// ``` - pub fn try_map(self, f: F) -> Result, E> - where - O: StableAddress, - F: FnOnce(&T) -> Result<&U, E>, - { - Ok(OwningRef { reference: f(&self)?, owner: self.owner }) - } - - /// Converts `self` into a new owning reference with a different owner type. - /// - /// The new owner type needs to still contain the original owner in some way - /// so that the reference into it remains valid. This function is marked unsafe - /// because the user needs to manually uphold this guarantee. - pub unsafe fn map_owner(self, f: F) -> OwningRef - where - O: StableAddress, - P: StableAddress, - F: FnOnce(O) -> P, - { - OwningRef { reference: self.reference, owner: f(self.owner) } - } - - /// Converts `self` into a new owning reference where the owner is wrapped - /// in an additional `Box`. - /// - /// This can be used to safely erase the owner of any `OwningRef` - /// to an `OwningRef, T>`. - pub fn map_owner_box(self) -> OwningRef, T> { - OwningRef { reference: self.reference, owner: Box::new(self.owner) } - } - - /// Erases the concrete base type of the owner with a trait object. - /// - /// This allows mixing of owned references with different owner base types. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::{OwningRef, Erased}; - /// - /// fn main() { - /// // N.B., using the concrete types here for explicitness. - /// // For less verbose code type aliases like `BoxRef` are provided. - /// - /// let owning_ref_a: OwningRef, [i32; 4]> - /// = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// let owning_ref_b: OwningRef>, Vec<(i32, bool)>> - /// = OwningRef::new(Box::new(vec![(0, false), (1, true)])); - /// - /// let owning_ref_a: OwningRef, i32> - /// = owning_ref_a.map(|a| &a[0]); - /// - /// let owning_ref_b: OwningRef>, i32> - /// = owning_ref_b.map(|a| &a[1].0); - /// - /// let owning_refs: [OwningRef, i32>; 2] - /// = [owning_ref_a.erase_owner(), owning_ref_b.erase_owner()]; - /// - /// assert_eq!(*owning_refs[0], 1); - /// assert_eq!(*owning_refs[1], 1); - /// } - /// ``` - pub fn erase_owner<'a>(self) -> OwningRef - where - O: IntoErased<'a>, - { - OwningRef { reference: self.reference, owner: self.owner.into_erased() } - } - - /// Erases the concrete base type of the owner with a trait object which implements `Send`. - /// - /// This allows mixing of owned references with different owner base types. - pub fn erase_send_owner<'a>(self) -> OwningRef - where - O: IntoErasedSend<'a>, - { - OwningRef { reference: self.reference, owner: self.owner.into_erased_send() } - } - - /// Erases the concrete base type of the owner with a trait object - /// which implements `Send` and `Sync`. - /// - /// This allows mixing of owned references with different owner base types. - pub fn erase_send_sync_owner<'a>(self) -> OwningRef - where - O: IntoErasedSendSync<'a>, - { - OwningRef { reference: self.reference, owner: self.owner.into_erased_send_sync() } - } - - // UNIMPLEMENTED: wrap_owner - - // FIXME: Naming convention? - /// A getter for the underlying owner. - pub fn owner(&self) -> &O { - &self.owner - } - - // FIXME: Naming convention? - /// Discards the reference and retrieves the owner. - pub fn into_inner(self) -> O { - self.owner - } -} - -impl OwningRefMut { - /// Creates a new owning reference from an owner - /// initialized to the direct dereference of it. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new(42)); - /// assert_eq!(*owning_ref_mut, 42); - /// } - /// ``` - pub fn new(mut o: O) -> Self - where - O: StableAddress, - O: DerefMut, - { - OwningRefMut { reference: &mut *o, owner: o } - } - - /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. - /// Instead, the caller is responsible to make the same promises as implementing the trait. - /// - /// This is useful for cases where coherence rules prevents implementing the trait - /// without adding a dependency to this crate in a third-party library. - pub unsafe fn new_assert_stable_address(mut o: O) -> Self - where - O: DerefMut, - { - OwningRefMut { reference: &mut *o, owner: o } - } - - /// Converts `self` into a new _shared_ owning reference that points at - /// something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref_mut.map(|array| &array[2]); - /// assert_eq!(*owning_ref, 3); - /// } - /// ``` - pub fn map(mut self, f: F) -> OwningRef - where - O: StableAddress, - F: FnOnce(&mut T) -> &U, - { - OwningRef { reference: f(&mut self), owner: self.owner } - } - - /// Converts `self` into a new _mutable_ owning reference that points at - /// something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref_mut = owning_ref_mut.map_mut(|array| &mut array[2]); - /// assert_eq!(*owning_ref_mut, 3); - /// } - /// ``` - pub fn map_mut(mut self, f: F) -> OwningRefMut - where - O: StableAddress, - F: FnOnce(&mut T) -> &mut U, - { - OwningRefMut { reference: f(&mut self), owner: self.owner } - } - - /// Tries to convert `self` into a new _shared_ owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref_mut.try_map(|array| { - /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref.unwrap(), 3); - /// } - /// ``` - pub fn try_map(mut self, f: F) -> Result, E> - where - O: StableAddress, - F: FnOnce(&mut T) -> Result<&U, E>, - { - Ok(OwningRef { reference: f(&mut self)?, owner: self.owner }) - } - - /// Tries to convert `self` into a new _mutable_ owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref_mut = owning_ref_mut.try_map_mut(|array| { - /// if array[2] == 3 { Ok(&mut array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref_mut.unwrap(), 3); - /// } - /// ``` - pub fn try_map_mut(mut self, f: F) -> Result, E> - where - O: StableAddress, - F: FnOnce(&mut T) -> Result<&mut U, E>, - { - Ok(OwningRefMut { reference: f(&mut self)?, owner: self.owner }) - } - - /// Converts `self` into a new owning reference with a different owner type. - /// - /// The new owner type needs to still contain the original owner in some way - /// so that the reference into it remains valid. This function is marked unsafe - /// because the user needs to manually uphold this guarantee. - pub unsafe fn map_owner(self, f: F) -> OwningRefMut - where - O: StableAddress, - P: StableAddress, - F: FnOnce(O) -> P, - { - OwningRefMut { reference: self.reference, owner: f(self.owner) } - } - - /// Converts `self` into a new owning reference where the owner is wrapped - /// in an additional `Box`. - /// - /// This can be used to safely erase the owner of any `OwningRefMut` - /// to an `OwningRefMut, T>`. - pub fn map_owner_box(self) -> OwningRefMut, T> { - OwningRefMut { reference: self.reference, owner: Box::new(self.owner) } - } - - /// Erases the concrete base type of the owner with a trait object. - /// - /// This allows mixing of owned references with different owner base types. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::{OwningRefMut, Erased}; - /// - /// fn main() { - /// // N.B., using the concrete types here for explicitness. - /// // For less verbose code type aliases like `BoxRef` are provided. - /// - /// let owning_ref_mut_a: OwningRefMut, [i32; 4]> - /// = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// let owning_ref_mut_b: OwningRefMut>, Vec<(i32, bool)>> - /// = OwningRefMut::new(Box::new(vec![(0, false), (1, true)])); - /// - /// let owning_ref_mut_a: OwningRefMut, i32> - /// = owning_ref_mut_a.map_mut(|a| &mut a[0]); - /// - /// let owning_ref_mut_b: OwningRefMut>, i32> - /// = owning_ref_mut_b.map_mut(|a| &mut a[1].0); - /// - /// let owning_refs_mut: [OwningRefMut, i32>; 2] - /// = [owning_ref_mut_a.erase_owner(), owning_ref_mut_b.erase_owner()]; - /// - /// assert_eq!(*owning_refs_mut[0], 1); - /// assert_eq!(*owning_refs_mut[1], 1); - /// } - /// ``` - pub fn erase_owner<'a>(self) -> OwningRefMut - where - O: IntoErased<'a>, - { - OwningRefMut { reference: self.reference, owner: self.owner.into_erased() } - } - - // UNIMPLEMENTED: wrap_owner - - // FIXME: Naming convention? - /// A getter for the underlying owner. - pub fn owner(&self) -> &O { - &self.owner - } - - // FIXME: Naming convention? - /// Discards the reference and retrieves the owner. - pub fn into_inner(self) -> O { - self.owner - } -} - -///////////////////////////////////////////////////////////////////////////// -// OwningHandle -///////////////////////////////////////////////////////////////////////////// - -use std::ops::{Deref, DerefMut}; - -/// `OwningHandle` is a complement to `OwningRef`. Where `OwningRef` allows -/// consumers to pass around an owned object and a dependent reference, -/// `OwningHandle` contains an owned object and a dependent _object_. -/// -/// `OwningHandle` can encapsulate a `RefMut` along with its associated -/// `RefCell`, or an `RwLockReadGuard` along with its associated `RwLock`. -/// However, the API is completely generic and there are no restrictions on -/// what types of owning and dependent objects may be used. -/// -/// `OwningHandle` is created by passing an owner object (which dereferences -/// to a stable address) along with a callback which receives a pointer to -/// that stable location. The callback may then dereference the pointer and -/// mint a dependent object, with the guarantee that the returned object will -/// not outlive the referent of the pointer. -/// -/// Since the callback needs to dereference a raw pointer, it requires `unsafe` -/// code. To avoid forcing this unsafety on most callers, the `ToHandle` trait is -/// implemented for common data structures. Types that implement `ToHandle` can -/// be wrapped into an `OwningHandle` without passing a callback. -pub struct OwningHandle -where - O: StableAddress, - H: Deref, -{ - handle: H, - _owner: O, -} - -impl Deref for OwningHandle -where - O: StableAddress, - H: Deref, -{ - type Target = H::Target; - fn deref(&self) -> &H::Target { - self.handle.deref() - } -} - -unsafe impl StableAddress for OwningHandle -where - O: StableAddress, - H: StableAddress, -{ -} - -impl DerefMut for OwningHandle -where - O: StableAddress, - H: DerefMut, -{ - fn deref_mut(&mut self) -> &mut H::Target { - self.handle.deref_mut() - } -} - -/// Trait to implement the conversion of owner to handle for common types. -pub trait ToHandle { - /// The type of handle to be encapsulated by the OwningHandle. - type Handle: Deref; - - /// Given an appropriately-long-lived pointer to ourselves, create a - /// handle to be encapsulated by the `OwningHandle`. - unsafe fn to_handle(x: *const Self) -> Self::Handle; -} - -/// Trait to implement the conversion of owner to mutable handle for common types. -pub trait ToHandleMut { - /// The type of handle to be encapsulated by the OwningHandle. - type HandleMut: DerefMut; - - /// Given an appropriately-long-lived pointer to ourselves, create a - /// mutable handle to be encapsulated by the `OwningHandle`. - unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut; -} - -impl OwningHandle -where - O: StableAddress>, - H: Deref, -{ - /// Creates a new `OwningHandle` for a type that implements `ToHandle`. For types - /// that don't implement `ToHandle`, callers may invoke `new_with_fn`, which accepts - /// a callback to perform the conversion. - pub fn new(o: O) -> Self { - OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle(x) }) - } -} - -impl OwningHandle -where - O: StableAddress>, - H: DerefMut, -{ - /// Creates a new mutable `OwningHandle` for a type that implements `ToHandleMut`. - pub fn new_mut(o: O) -> Self { - OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle_mut(x) }) - } -} - -impl OwningHandle -where - O: StableAddress, - H: Deref, -{ - /// Creates a new OwningHandle. The provided callback will be invoked with - /// a pointer to the object owned by `o`, and the returned value is stored - /// as the object to which this `OwningHandle` will forward `Deref` and - /// `DerefMut`. - pub fn new_with_fn(o: O, f: F) -> Self - where - F: FnOnce(*const O::Target) -> H, - { - let h: H; - { - h = f(o.deref() as *const O::Target); - } - - OwningHandle { handle: h, _owner: o } - } - - /// Creates a new OwningHandle. The provided callback will be invoked with - /// a pointer to the object owned by `o`, and the returned value is stored - /// as the object to which this `OwningHandle` will forward `Deref` and - /// `DerefMut`. - pub fn try_new(o: O, f: F) -> Result - where - F: FnOnce(*const O::Target) -> Result, - { - let h: H; - { - h = f(o.deref() as *const O::Target)?; - } - - Ok(OwningHandle { handle: h, _owner: o }) - } -} - -///////////////////////////////////////////////////////////////////////////// -// std traits -///////////////////////////////////////////////////////////////////////////// - -use std::borrow::Borrow; -use std::cmp::Ordering; -use std::fmt::{self, Debug}; -use std::hash::{Hash, Hasher}; - -impl Deref for OwningRef { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.reference } - } -} - -impl Deref for OwningRefMut { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.reference } - } -} - -impl DerefMut for OwningRefMut { - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.reference } - } -} - -unsafe impl StableAddress for OwningRef {} - -impl AsRef for OwningRef { - fn as_ref(&self) -> &T { - self - } -} - -impl AsRef for OwningRefMut { - fn as_ref(&self) -> &T { - self - } -} - -impl AsMut for OwningRefMut { - fn as_mut(&mut self) -> &mut T { - self - } -} - -impl Borrow for OwningRef { - fn borrow(&self) -> &T { - self - } -} - -impl From for OwningRef -where - O: StableAddress, - O: Deref, -{ - fn from(owner: O) -> Self { - OwningRef::new(owner) - } -} - -impl From for OwningRefMut -where - O: StableAddress, - O: DerefMut, -{ - fn from(owner: O) -> Self { - OwningRefMut::new(owner) - } -} - -impl From> for OwningRef -where - O: StableAddress, - O: DerefMut, -{ - fn from(other: OwningRefMut) -> Self { - OwningRef { owner: other.owner, reference: other.reference } - } -} - -// ^ FIXME: Is an Into impl for calling into_inner() possible as well? - -impl Debug for OwningRef -where - O: Debug, - T: Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "OwningRef {{ owner: {:?}, reference: {:?} }}", self.owner(), &**self) - } -} - -impl Debug for OwningRefMut -where - O: Debug, - T: Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "OwningRefMut {{ owner: {:?}, reference: {:?} }}", self.owner(), &**self) - } -} - -impl Clone for OwningRef -where - O: CloneStableAddress, -{ - fn clone(&self) -> Self { - OwningRef { owner: self.owner.clone(), reference: self.reference } - } -} - -unsafe impl CloneStableAddress for OwningRef where O: CloneStableAddress {} - -unsafe impl Send for OwningRef -where - O: Send, - for<'a> &'a T: Send, -{ -} -unsafe impl Sync for OwningRef -where - O: Sync, - for<'a> &'a T: Sync, -{ -} - -unsafe impl Send for OwningRefMut -where - O: Send, - for<'a> &'a mut T: Send, -{ -} -unsafe impl Sync for OwningRefMut -where - O: Sync, - for<'a> &'a mut T: Sync, -{ -} - -impl Debug for dyn Erased { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "",) - } -} - -impl PartialEq for OwningRef -where - T: PartialEq, -{ - fn eq(&self, other: &Self) -> bool { - self.deref().eq(other.deref()) - } -} - -impl Eq for OwningRef where T: Eq {} - -impl PartialOrd for OwningRef -where - T: PartialOrd, -{ - fn partial_cmp(&self, other: &Self) -> Option { - self.deref().partial_cmp(other.deref()) - } -} - -impl Ord for OwningRef -where - T: Ord, -{ - fn cmp(&self, other: &Self) -> Ordering { - self.deref().cmp(other.deref()) - } -} - -impl Hash for OwningRef -where - T: Hash, -{ - fn hash(&self, state: &mut H) { - self.deref().hash(state); - } -} - -impl PartialEq for OwningRefMut -where - T: PartialEq, -{ - fn eq(&self, other: &Self) -> bool { - self.deref().eq(other.deref()) - } -} - -impl Eq for OwningRefMut where T: Eq {} - -impl PartialOrd for OwningRefMut -where - T: PartialOrd, -{ - fn partial_cmp(&self, other: &Self) -> Option { - self.deref().partial_cmp(other.deref()) - } -} - -impl Ord for OwningRefMut -where - T: Ord, -{ - fn cmp(&self, other: &Self) -> Ordering { - self.deref().cmp(other.deref()) - } -} - -impl Hash for OwningRefMut -where - T: Hash, -{ - fn hash(&self, state: &mut H) { - self.deref().hash(state); - } -} - -///////////////////////////////////////////////////////////////////////////// -// std types integration and convenience type defs -///////////////////////////////////////////////////////////////////////////// - -use std::cell::{Ref, RefCell, RefMut}; -use std::rc::Rc; -use std::sync::Arc; -use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard}; - -impl ToHandle for RefCell { - type Handle = Ref<'static, T>; - unsafe fn to_handle(x: *const Self) -> Self::Handle { - (*x).borrow() - } -} - -impl ToHandleMut for RefCell { - type HandleMut = RefMut<'static, T>; - unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut { - (*x).borrow_mut() - } -} - -// N.B., implementing ToHandle{,Mut} for Mutex and RwLock requires a decision -// about which handle creation to use (i.e., read() vs try_read()) as well as -// what to do with error results. - -/// Typedef of an owning reference that uses a `Box` as the owner. -pub type BoxRef = OwningRef, U>; -/// Typedef of an owning reference that uses a `Vec` as the owner. -pub type VecRef = OwningRef, U>; -/// Typedef of an owning reference that uses a `String` as the owner. -pub type StringRef = OwningRef; - -/// Typedef of an owning reference that uses an `Rc` as the owner. -pub type RcRef = OwningRef, U>; -/// Typedef of an owning reference that uses an `Arc` as the owner. -pub type ArcRef = OwningRef, U>; - -/// Typedef of an owning reference that uses a `Ref` as the owner. -pub type RefRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of an owning reference that uses a `RefMut` as the owner. -pub type RefMutRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of an owning reference that uses a `MutexGuard` as the owner. -pub type MutexGuardRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of an owning reference that uses an `RwLockReadGuard` as the owner. -pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of an owning reference that uses an `RwLockWriteGuard` as the owner. -pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef, U>; - -/// Typedef of a mutable owning reference that uses a `Box` as the owner. -pub type BoxRefMut = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `Vec` as the owner. -pub type VecRefMut = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `String` as the owner. -pub type StringRefMut = OwningRefMut; - -/// Typedef of a mutable owning reference that uses a `RefMut` as the owner. -pub type RefMutRefMut<'a, T, U = T> = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner. -pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses an `RwLockWriteGuard` as the owner. -pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef, U>; - -unsafe impl<'a, T: 'a> IntoErased<'a> for Box { - type Erased = Box; - fn into_erased(self) -> Self::Erased { - self - } -} -unsafe impl<'a, T: 'a> IntoErased<'a> for Rc { - type Erased = Rc; - fn into_erased(self) -> Self::Erased { - self - } -} -unsafe impl<'a, T: 'a> IntoErased<'a> for Arc { - type Erased = Arc; - fn into_erased(self) -> Self::Erased { - self - } -} - -unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box { - type Erased = Box; - fn into_erased_send(self) -> Self::Erased { - self - } -} - -unsafe impl<'a, T: Send + 'a> IntoErasedSendSync<'a> for Box { - type Erased = Box; - fn into_erased_send_sync(self) -> Self::Erased { - let result: Box = self; - // This is safe since Erased can always implement Sync - // Only the destructor is available and it takes &mut self - unsafe { mem::transmute(result) } - } -} - -unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Arc { - type Erased = Arc; - fn into_erased_send_sync(self) -> Self::Erased { - self - } -} - -/// Typedef of an owning reference that uses an erased `Box` as the owner. -pub type ErasedBoxRef = OwningRef, U>; -/// Typedef of an owning reference that uses an erased `Rc` as the owner. -pub type ErasedRcRef = OwningRef, U>; -/// Typedef of an owning reference that uses an erased `Arc` as the owner. -pub type ErasedArcRef = OwningRef, U>; - -/// Typedef of a mutable owning reference that uses an erased `Box` as the owner. -pub type ErasedBoxRefMut = OwningRefMut, U>; - -#[cfg(test)] -mod tests; diff --git a/compiler/rustc_data_structures/src/owning_ref/tests.rs b/compiler/rustc_data_structures/src/owning_ref/tests.rs deleted file mode 100644 index a9b187c4ce0a..000000000000 --- a/compiler/rustc_data_structures/src/owning_ref/tests.rs +++ /dev/null @@ -1,711 +0,0 @@ -// FIXME: owning_ref is not sound under stacked borrows. Preferably, get rid of it. -#[cfg(not(miri))] -mod owning_ref { - use super::super::OwningRef; - use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef}; - use std::cmp::Ordering; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - use std::hash::{Hash, Hasher}; - use std::rc::Rc; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRef, ()> = OwningRef::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn into() { - let or: OwningRef, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRef = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &x.0); - assert_eq!(&*or, &42); - - let or: BoxRef = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRef = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRef<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_chained() { - let or: BoxRef = Box::new(example().1).into(); - let or: BoxRef<_, str> = or.map(|x| &x[1..5]); - let or: BoxRef<_, str> = or.map(|x| &x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRef::new(Box::new(example().1)).map(|x| &x[..5]).map(|x| &x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn owner() { - let or: BoxRef = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRef = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRef = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRef = BoxRef::new(Box::new(example())).map(|x| &x.1[..]); - - let o2: BoxRef = BoxRef::new(Box::new(example().1)).map(|x| &x[..]); - - let os: Vec> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn raii_locks() { - use super::super::{MutexGuardRef, RwLockReadGuardRef, RwLockWriteGuardRef}; - use super::super::{RefMutRef, RefRef}; - use std::cell::RefCell; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefRef::new(a.borrow()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RefCell::new(1); - let a = { - let a = RefMutRef::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRef::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockReadGuardRef::new(a.read().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRef::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key = RcRef::::new(Rc::new("foo-bar".to_string())).map(|s| &s[..]); - - hash.insert(key.clone().map(|s| &s[..3]), 42); - hash.insert(key.clone().map(|s| &s[4..]), 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRef, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef, [u8]> = - OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef>, [u8]> = unsafe { a.map_owner(Rc::new) }; - let d: OwningRef>, [u8]> = unsafe { b.map_owner(Rc::new) }; - - let e: OwningRef, [u8]> = c.erase_owner(); - let f: OwningRef, [u8]> = d.erase_owner(); - - let _g = e.clone(); - let _h = f.clone(); - } - - #[test] - fn total_erase_box() { - let a: OwningRef, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef, [u8]> = - OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef>, [u8]> = a.map_owner_box(); - let d: OwningRef>, [u8]> = b.map_owner_box(); - - let _e: OwningRef, [u8]> = c.erase_owner(); - let _f: OwningRef, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(OwningRef::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_ok()); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(!OwningRef::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_err()); - } -} - -mod owning_handle { - use super::super::OwningHandle; - use super::super::RcRef; - use std::cell::RefCell; - use std::rc::Rc; - use std::sync::Arc; - use std::sync::RwLock; - - #[test] - fn owning_handle() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = - OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_ok() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - Ok(unsafe { x.as_ref() }.unwrap().borrow_mut()) - }) - .unwrap(); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_err() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - if false { - return Ok(unsafe { x.as_ref() }.unwrap().borrow_mut()); - } - Err(()) - }); - assert!(handle.is_err()); - } - - #[test] - fn nested() { - use std::cell::RefCell; - use std::sync::{Arc, RwLock}; - - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = - OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| { - unsafe { x.as_ref() }.unwrap().try_write().unwrap() - }); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } - - #[test] - fn owning_handle_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::new(cell_ref); - assert_eq!(*handle, 2); - } - - #[test] - fn owning_handle_mut_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::new_mut(cell_ref); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn owning_handle_safe_2() { - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = - OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| { - unsafe { x.as_ref() }.unwrap().try_write().unwrap() - }); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } -} - -// FIXME: owning_ref is not sound under stacked borrows. Preferably, get rid of it. -#[cfg(not(miri))] -mod owning_ref_mut { - use super::super::BoxRef; - use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut}; - use std::cmp::Ordering; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - use std::hash::{Hash, Hasher}; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRefMut, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn new_deref_mut() { - let mut or: OwningRefMut, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&mut *or, &mut ()); - } - - #[test] - fn mutate() { - let mut or: OwningRefMut, usize> = OwningRefMut::new(Box::new(0)); - assert_eq!(&*or, &0); - *or = 1; - assert_eq!(&*or, &1); - } - - #[test] - fn into() { - let or: OwningRefMut, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_offset_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRefMut<_, u8> = or.map_mut(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_mut_heap_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_static_ref() { - static mut MUT_S: [u8; 5] = *b"hello"; - - let mut_s: &'static mut [u8] = unsafe { &mut MUT_S }; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRefMut<_, [u8]> = or.map_mut(move |_| mut_s); - assert_eq!(&*or, b"hello"); - } - - #[test] - fn map_mut_chained() { - let or: BoxRefMut = Box::new(example().1).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[1..5]); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRefMut::new(Box::new(example().1)) - .map_mut(|x| &mut x[..5]) - .map_mut(|x| &mut x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn try_map_mut() { - let or: BoxRefMut = Box::new(example().1).into(); - let or: Result, ()> = or.try_map_mut(|x| Ok(&mut x[1..5])); - assert_eq!(&*or.unwrap(), "ello"); - - let or: BoxRefMut = Box::new(example().1).into(); - let or: Result, ()> = or.try_map_mut(|_| Err(())); - assert!(or.is_err()); - } - - #[test] - fn owner() { - let or: BoxRefMut = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRefMut = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRefMut = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, "OwningRefMut { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRefMut = - BoxRefMut::new(Box::new(example())).map_mut(|x| &mut x.1[..]); - - let o2: BoxRefMut = - BoxRefMut::new(Box::new(example().1)).map_mut(|x| &mut x[..]); - - let os: Vec> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn raii_locks() { - use super::super::RefMutRefMut; - use super::super::{MutexGuardRefMut, RwLockWriteGuardRefMut}; - use std::cell::RefCell; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefMutRefMut::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRefMut::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRefMut::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key1 = BoxRefMut::::new(Box::new("foo".to_string())).map(|s| &s[..]); - let key2 = BoxRefMut::::new(Box::new("bar".to_string())).map(|s| &s[..]); - - hash.insert(key1, 42); - hash.insert(key2, 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRefMut, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut, [u8]> = - OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut>, [u8]> = unsafe { a.map_owner(Box::new) }; - let d: OwningRefMut>, [u8]> = unsafe { b.map_owner(Box::new) }; - - let _e: OwningRefMut, [u8]> = c.erase_owner(); - let _f: OwningRefMut, [u8]> = d.erase_owner(); - } - - #[test] - fn total_erase_box() { - let a: OwningRefMut, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut, [u8]> = - OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut>, [u8]> = a.map_owner_box(); - let d: OwningRefMut>, [u8]> = b.map_owner_box(); - - let _e: OwningRefMut, [u8]> = c.erase_owner(); - let _f: OwningRefMut, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::().ok_or(())).is_ok()); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(!OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::().ok_or(())).is_err()); - } - - #[test] - fn try_map3() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(OwningRefMut::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_ok()); - } - - #[test] - fn try_map4() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(!OwningRefMut::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_err()); - } - - #[test] - fn into_owning_ref() { - use super::super::BoxRef; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<()> = or.into(); - assert_eq!(&*or, &()); - } - - struct Foo { - u: u32, - } - struct Bar { - f: Foo, - } - - #[test] - fn ref_mut() { - use std::cell::RefCell; - - let a = RefCell::new(Bar { f: Foo { u: 42 } }); - let mut b = OwningRefMut::new(a.borrow_mut()); - assert_eq!(b.f.u, 42); - b.f.u = 43; - let mut c = b.map_mut(|x| &mut x.f); - assert_eq!(c.u, 43); - c.u = 44; - let mut d = c.map_mut(|x| &mut x.u); - assert_eq!(*d, 44); - *d = 45; - assert_eq!(*d, 45); - } -} diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 855a7eb331f8..215b80887415 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -7,9 +7,6 @@ //! while the serial versions degenerate straightforwardly to serial execution. //! The operations include `join`, `parallel`, `par_iter`, and `par_for_each`. //! -//! `rustc_erase_owner!` erases an `OwningRef` owner into `Erased` for the -//! serial version and `Erased + Send + Sync` for the parallel version. -//! //! Types //! ----- //! The parallel versions of types provide various kinds of synchronization, @@ -60,12 +57,6 @@ cfg_if! { pub unsafe auto trait Send {} pub unsafe auto trait Sync {} - #[macro_export] - macro_rules! rustc_erase_owner { - ($v:expr) => { - $v.erase_owner() - } - } unsafe impl Send for T {} unsafe impl Sync for T {} @@ -376,15 +367,6 @@ cfg_if! { /// This makes locks panic if they are already held. /// It is only useful when you are running in a single thread const ERROR_CHECKING: bool = false; - - #[macro_export] - macro_rules! rustc_erase_owner { - ($v:expr) => {{ - let v = $v; - ::rustc_data_structures::sync::assert_send_val(&v); - v.erase_send_sync_owner() - }} - } } } From 9405f586f5ce5db00b01468788bdd71c09ffd1bc Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 5 Apr 2023 13:48:19 +0000 Subject: [PATCH 127/267] Fix typo --- compiler/rustc_data_structures/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 47d8c84ba205..e373bd18402a 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -1,5 +1,5 @@ //! Various data structures used by the Rust compiler. The intention -//! is that code in here should be not be *specific* to rustc, so that +//! is that code in here should not be *specific* to rustc, so that //! it can be easily unit tested and so forth. //! //! # Note From c325fda0bfb32affaeba76c360779585278b8c61 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 3 Apr 2023 21:20:45 -0700 Subject: [PATCH 128/267] rustdoc: migrate `item_union` to an Askama template --- src/librustdoc/html/format.rs | 4 - src/librustdoc/html/render/mod.rs | 77 +-- src/librustdoc/html/render/print_item.rs | 569 ++++++++++-------- src/librustdoc/html/templates/item_union.html | 23 + 4 files changed, 382 insertions(+), 291 deletions(-) create mode 100644 src/librustdoc/html/templates/item_union.html diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0895bb510d48..77c2cd5b425d 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -136,10 +136,6 @@ impl Buffer { self.into_inner() } - pub(crate) fn is_for_html(&self) -> bool { - self.for_html - } - pub(crate) fn reserve(&mut self, additional: usize) { self.buffer.reserve(additional) } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 49986433dfbb..1e3cd2668506 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -660,7 +660,7 @@ fn short_item_info( // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). pub(crate) fn render_impls( cx: &mut Context<'_>, - w: &mut Buffer, + mut w: impl Write, impls: &[&Impl], containing_item: &clean::Item, toggle_open_by_default: bool, @@ -672,7 +672,7 @@ pub(crate) fn render_impls( let did = i.trait_did().unwrap(); let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx); let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods); - let mut buffer = if w.is_for_html() { Buffer::html() } else { Buffer::new() }; + let mut buffer = Buffer::new(); render_impl( &mut buffer, cx, @@ -693,7 +693,7 @@ pub(crate) fn render_impls( }) .collect::>(); rendered_impls.sort(); - w.write_str(&rendered_impls.join("")); + w.write_str(&rendered_impls.join("")).unwrap(); } /// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item. @@ -1080,61 +1080,68 @@ impl<'a> AssocItemLink<'a> { } } -fn write_impl_section_heading(w: &mut Buffer, title: &str, id: &str) { +fn write_impl_section_heading(mut w: impl fmt::Write, title: &str, id: &str) { write!( w, "" - ); + ) + .unwrap(); } pub(crate) fn render_all_impls( - w: &mut Buffer, + mut w: impl Write, cx: &mut Context<'_>, containing_item: &clean::Item, concrete: &[&Impl], synthetic: &[&Impl], blanket_impl: &[&Impl], ) { - let mut impls = Buffer::empty_from(w); + let mut impls = Buffer::html(); render_impls(cx, &mut impls, concrete, containing_item, true); let impls = impls.into_inner(); if !impls.is_empty() { - write_impl_section_heading(w, "Trait Implementations", "trait-implementations"); - write!(w, "
{}
", impls); + write_impl_section_heading(&mut w, "Trait Implementations", "trait-implementations"); + write!(w, "
{}
", impls).unwrap(); } if !synthetic.is_empty() { - write_impl_section_heading(w, "Auto Trait Implementations", "synthetic-implementations"); - w.write_str("
"); - render_impls(cx, w, synthetic, containing_item, false); - w.write_str("
"); + write_impl_section_heading( + &mut w, + "Auto Trait Implementations", + "synthetic-implementations", + ); + w.write_str("
").unwrap(); + render_impls(cx, &mut w, synthetic, containing_item, false); + w.write_str("
").unwrap(); } if !blanket_impl.is_empty() { - write_impl_section_heading(w, "Blanket Implementations", "blanket-implementations"); - w.write_str("
"); - render_impls(cx, w, blanket_impl, containing_item, false); - w.write_str("
"); + write_impl_section_heading(&mut w, "Blanket Implementations", "blanket-implementations"); + w.write_str("
").unwrap(); + render_impls(cx, &mut w, blanket_impl, containing_item, false); + w.write_str("
").unwrap(); } } -fn render_assoc_items( - w: &mut Buffer, - cx: &mut Context<'_>, - containing_item: &clean::Item, +fn render_assoc_items<'a, 'cx: 'a>( + cx: &'a mut Context<'cx>, + containing_item: &'a clean::Item, it: DefId, - what: AssocItemRender<'_>, -) { + what: AssocItemRender<'a>, +) -> impl fmt::Display + 'a + Captures<'cx> { let mut derefs = DefIdSet::default(); derefs.insert(it); - render_assoc_items_inner(w, cx, containing_item, it, what, &mut derefs) + display_fn(move |f| { + render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs); + Ok(()) + }) } fn render_assoc_items_inner( - w: &mut Buffer, + mut w: &mut dyn fmt::Write, cx: &mut Context<'_>, containing_item: &clean::Item, it: DefId, @@ -1147,7 +1154,7 @@ fn render_assoc_items_inner( let Some(v) = cache.impls.get(&it) else { return }; let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { - let mut tmp_buf = Buffer::empty_from(w); + let mut tmp_buf = Buffer::html(); let (render_mode, id) = match what { AssocItemRender::All => { write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations"); @@ -1171,7 +1178,7 @@ fn render_assoc_items_inner( (RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id)) } }; - let mut impls_buf = Buffer::empty_from(w); + let mut impls_buf = Buffer::html(); for i in &non_trait { render_impl( &mut impls_buf, @@ -1191,10 +1198,10 @@ fn render_assoc_items_inner( ); } if !impls_buf.is_empty() { - w.push_buffer(tmp_buf); - write!(w, "
", id); - w.push_buffer(impls_buf); - w.write_str("
"); + write!(w, "{}", tmp_buf.into_inner()).unwrap(); + write!(w, "
", id).unwrap(); + write!(w, "{}", impls_buf.into_inner()).unwrap(); + w.write_str("
").unwrap(); } } @@ -1204,7 +1211,7 @@ fn render_assoc_items_inner( if let Some(impl_) = deref_impl { let has_deref_mut = traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait()); - render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, derefs); + render_deref_methods(&mut w, cx, impl_, containing_item, has_deref_mut, derefs); } // If we were already one level into rendering deref methods, we don't want to render @@ -1223,7 +1230,7 @@ fn render_assoc_items_inner( } fn render_deref_methods( - w: &mut Buffer, + mut w: impl Write, cx: &mut Context<'_>, impl_: &Impl, container_item: &clean::Item, @@ -1255,10 +1262,10 @@ fn render_deref_methods( return; } } - render_assoc_items_inner(w, cx, container_item, did, what, derefs); + render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); } else if let Some(prim) = target.primitive_type() { if let Some(&did) = cache.primitive_locations.get(&prim) { - render_assoc_items_inner(w, cx, container_item, did, what, derefs); + render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); } } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index ea53f8d107dc..6bce57340040 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -202,7 +202,7 @@ fn should_hide_fields(n_fields: usize) -> bool { n_fields > 12 } -fn toggle_open(w: &mut Buffer, text: impl fmt::Display) { +fn toggle_open(mut w: impl fmt::Write, text: impl fmt::Display) { write!( w, "
\ @@ -210,11 +210,12 @@ fn toggle_open(w: &mut Buffer, text: impl fmt::Display) { Show {}\ ", text - ); + ) + .unwrap(); } -fn toggle_close(w: &mut Buffer) { - w.write_str("
"); +fn toggle_close(mut w: impl fmt::Write) { + w.write_str("").unwrap(); } fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) { @@ -580,7 +581,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone(); // Output the trait definition - wrap_item(w, |w| { + wrap_item(w, |mut w| { write!( w, "{attrs}{}{}{}trait {}{}{}", @@ -610,7 +611,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: if should_hide_fields(count_types) { toggle = true; toggle_open( - w, + &mut w, format_args!("{} associated items", count_types + count_consts + count_methods), ); } @@ -634,7 +635,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: if !toggle && should_hide_fields(count_types + count_consts) { toggle = true; toggle_open( - w, + &mut w, format_args!( "{} associated constant{} and {} method{}", count_consts, @@ -662,7 +663,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !toggle && should_hide_fields(count_methods) { toggle = true; - toggle_open(w, format_args!("{} methods", count_methods)); + toggle_open(&mut w, format_args!("{} methods", count_methods)); } if count_consts != 0 && count_methods != 0 { w.write_str("\n"); @@ -710,7 +711,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } } if toggle { - toggle_close(w); + toggle_close(&mut w); } w.write_str("}"); } @@ -847,7 +848,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } // If there are methods directly on this trait object, render them here. - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)); let cloned_shared = Rc::clone(&cx.shared); let cache = &cloned_shared.cache; @@ -1074,7 +1075,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: & // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) } fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) { @@ -1096,7 +1097,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) } fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) { @@ -1124,54 +1125,102 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_type_layout(w, cx, def_id); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); } fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) { - wrap_item(w, |w| { - write!(w, "{}", render_attributes_in_pre(it, "")); - render_union(w, it, Some(&s.generics), &s.fields, cx); - }); + #[derive(Template)] + #[template(path = "item_union.html")] + struct ItemUnion<'a, 'cx> { + cx: std::cell::RefCell<&'a mut Context<'cx>>, + it: &'a clean::Item, + s: &'a clean::Union, + } - write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); + impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { + fn render_assoc_items<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let def_id = self.it.item_id.expect_def_id(); + let mut cx = self.cx.borrow_mut(); + let v = render_assoc_items(*cx, self.it, def_id, AssocItemRender::All); + write!(f, "{v}") + }) + } + fn document_type_layout<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let def_id = self.it.item_id.expect_def_id(); + let cx = self.cx.borrow_mut(); + let v = document_type_layout(*cx, def_id); + write!(f, "{v}") + }) + } + fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let cx = self.cx.borrow_mut(); + let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx); + write!(f, "{v}") + }) + } + fn render_attributes_in_pre<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let v = render_attributes_in_pre(self.it, ""); + write!(f, "{v}") + }) + } + fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut cx = self.cx.borrow_mut(); + let v = document(*cx, self.it, None, HeadingOffset::H2); + write!(f, "{v}") + }) + } + fn document_field<'b>( + &'b self, + field: &'a clean::Item, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut cx = self.cx.borrow_mut(); + let v = document(*cx, field, Some(self.it), HeadingOffset::H3); + write!(f, "{v}") + }) + } + fn stability_field(&self, field: &clean::Item) -> Option { + let cx = self.cx.borrow(); + field.stability_class(cx.tcx()) + } + fn print_ty<'b>( + &'b self, + ty: &'a clean::Type, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let cx = self.cx.borrow(); + let v = ty.print(*cx); + write!(f, "{v}") + }) + } - let mut fields = s - .fields - .iter() - .filter_map(|f| match *f.kind { - clean::StructFieldItem(ref ty) => Some((f, ty)), - _ => None, - }) - .peekable(); - if fields.peek().is_some() { - write!( - w, - "

\ - Fields§\ -

" - ); - for (field, ty) in fields { - let name = field.name.expect("union field name"); - let id = format!("{}.{}", ItemType::StructField, name); - write!( - w, - "\ - §\ - {name}: {ty}\ - ", - shortty = ItemType::StructField, - ty = ty.print(cx), - ); - if let Some(stability_class) = field.stability_class(cx.tcx()) { - write!(w, ""); - } - write!(w, "{}", document(cx, field, Some(it), HeadingOffset::H3)); + fn fields_iter( + &self, + ) -> std::iter::Peekable> { + self.s + .fields + .iter() + .filter_map(|f| match *f.kind { + clean::StructFieldItem(ref ty) => Some((f, ty)), + _ => None, + }) + .peekable() } } - let def_id = it.item_id.expect_def_id(); - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_type_layout(w, cx, def_id); + + ItemUnion { cx: std::cell::RefCell::new(cx), it, s }.render_into(w).unwrap(); } fn print_tuple_struct_fields<'a, 'cx: 'a>( @@ -1196,7 +1245,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) { let tcx = cx.tcx(); let count_variants = e.variants().count(); - wrap_item(w, |w| { + wrap_item(w, |mut w| { write!( w, "{attrs}{}enum {}{}", @@ -1217,7 +1266,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str("{\n"); let toggle = should_hide_fields(count_variants); if toggle { - toggle_open(w, format_args!("{} variants", count_variants)); + toggle_open(&mut w, format_args!("{} variants", count_variants)); } for v in e.variants() { w.write_str(" "); @@ -1242,7 +1291,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str(" // some variants omitted\n"); } if toggle { - toggle_close(w); + toggle_close(&mut w); } w.write_str("}"); } @@ -1255,11 +1304,12 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w, "

\ Variants{}§\ -

", - document_non_exhaustive_header(it) + \ + {}\ +
", + document_non_exhaustive_header(it), + document_non_exhaustive(it) ); - document_non_exhaustive(w, it); - write!(w, "
"); for variant in e.variants() { let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap())); write!( @@ -1304,9 +1354,10 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: write!( w, "
\ -

{heading}

", +

{heading}

\ + {}", + document_non_exhaustive(variant) ); - document_non_exhaustive(w, variant); for field in fields { match *field.kind { clean::StrippedItem(box clean::StructFieldItem(_)) => {} @@ -1343,8 +1394,8 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: write!(w, "
"); } let def_id = it.item_id.expect_def_id(); - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_type_layout(w, cx, def_id); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); } fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) { @@ -1382,7 +1433,7 @@ fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { let def_id = it.item_id.expect_def_id(); write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); } else { // We handle the "reference" primitive type on its own because we only want to list // implementations on generic types. @@ -1463,11 +1514,12 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean w, "

\ {}{}§\ -

", + \ + {}", if s.ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, - document_non_exhaustive_header(it) + document_non_exhaustive_header(it), + document_non_exhaustive(it) ); - document_non_exhaustive(w, it); for (index, (field, ty)) in fields.enumerate() { let field_name = field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); @@ -1486,8 +1538,8 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean } } let def_id = it.item_id.expect_def_id(); - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_type_layout(w, cx, def_id); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); } fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { @@ -1519,7 +1571,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) } fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { @@ -1660,64 +1712,69 @@ fn render_implementor( ); } -fn render_union( - w: &mut Buffer, - it: &clean::Item, - g: Option<&clean::Generics>, - fields: &[clean::Item], - cx: &Context<'_>, -) { - let tcx = cx.tcx(); - write!( - w, - "{}union {}", - visibility_print_with_space(it.visibility(tcx), it.item_id, cx), - it.name.unwrap(), - ); +fn render_union<'a, 'cx: 'a>( + it: &'a clean::Item, + g: Option<&'a clean::Generics>, + fields: &'a [clean::Item], + cx: &'a Context<'cx>, +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(move |mut f| { + let tcx = cx.tcx(); + write!( + f, + "{}union {}", + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), + it.name.unwrap(), + )?; - let where_displayed = g - .map(|g| { - write!(w, "{}", g.print(cx)); - print_where_clause_and_check(w, g, cx) - }) - .unwrap_or(false); + let where_displayed = g + .map(|g| { + let mut buf = Buffer::html(); + write!(buf, "{}", g.print(cx)); + let where_displayed = print_where_clause_and_check(&mut buf, g, cx); + write!(f, "{buf}", buf = buf.into_inner()).unwrap(); + where_displayed + }) + .unwrap_or(false); - // If there wasn't a `where` clause, we add a whitespace. - if !where_displayed { - w.write_str(" "); - } - - write!(w, "{{\n"); - let count_fields = - fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); - let toggle = should_hide_fields(count_fields); - if toggle { - toggle_open(w, format_args!("{} fields", count_fields)); - } - - for field in fields { - if let clean::StructFieldItem(ref ty) = *field.kind { - write!( - w, - " {}{}: {},\n", - visibility_print_with_space(field.visibility(tcx), field.item_id, cx), - field.name.unwrap(), - ty.print(cx) - ); + // If there wasn't a `where` clause, we add a whitespace. + if !where_displayed { + f.write_str(" ")?; } - } - if it.has_stripped_entries().unwrap() { - write!(w, " /* private fields */\n"); - } - if toggle { - toggle_close(w); - } - w.write_str("}"); + write!(f, "{{\n")?; + let count_fields = + fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count(); + let toggle = should_hide_fields(count_fields); + if toggle { + toggle_open(&mut f, format_args!("{} fields", count_fields)); + } + + for field in fields { + if let clean::StructFieldItem(ref ty) = *field.kind { + write!( + f, + " {}{}: {},\n", + visibility_print_with_space(field.visibility(tcx), field.item_id, cx), + field.name.unwrap(), + ty.print(cx) + )?; + } + } + + if it.has_stripped_entries().unwrap() { + write!(f, " /* private fields */\n")?; + } + if toggle { + toggle_close(&mut f); + } + f.write_str("}").unwrap(); + Ok(()) + }) } fn render_struct( - w: &mut Buffer, + mut w: &mut Buffer, it: &clean::Item, g: Option<&clean::Generics>, ty: Option, @@ -1752,7 +1809,7 @@ fn render_struct( let has_visible_fields = count_fields > 0; let toggle = should_hide_fields(count_fields); if toggle { - toggle_open(w, format_args!("{} fields", count_fields)); + toggle_open(&mut w, format_args!("{} fields", count_fields)); } for field in fields { if let clean::StructFieldItem(ref ty) = *field.kind { @@ -1776,7 +1833,7 @@ fn render_struct( write!(w, " /* private fields */ "); } if toggle { - toggle_close(w); + toggle_close(&mut w); } w.write_str("}"); } @@ -1822,161 +1879,169 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str { if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" } } -fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { - if item.is_non_exhaustive() { - write!( - w, - "
\ - {}\ -
", - { - if item.is_struct() { - "This struct is marked as non-exhaustive" - } else if item.is_enum() { - "This enum is marked as non-exhaustive" - } else if item.is_variant() { - "This variant is marked as non-exhaustive" - } else { - "This type is marked as non-exhaustive" +fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a { + display_fn(|f| { + if item.is_non_exhaustive() { + write!( + f, + "
\ + {}\ +
", + { + if item.is_struct() { + "This struct is marked as non-exhaustive" + } else if item.is_enum() { + "This enum is marked as non-exhaustive" + } else if item.is_variant() { + "This variant is marked as non-exhaustive" + } else { + "This type is marked as non-exhaustive" + } } + )?; + + if item.is_struct() { + f.write_str( + "Non-exhaustive structs could have additional fields added in future. \ + Therefore, non-exhaustive structs cannot be constructed in external crates \ + using the traditional Struct { .. } syntax; cannot be \ + matched against without a wildcard ..; and \ + struct update syntax will not work.", + )?; + } else if item.is_enum() { + f.write_str( + "Non-exhaustive enums could have additional variants added in future. \ + Therefore, when matching against variants of non-exhaustive enums, an \ + extra wildcard arm must be added to account for any future variants.", + )?; + } else if item.is_variant() { + f.write_str( + "Non-exhaustive enum variants could have additional fields added in future. \ + Therefore, non-exhaustive enum variants cannot be constructed in external \ + crates and cannot be matched against.", + )?; + } else { + f.write_str( + "This type will require a wildcard arm in any match statements or constructors.", + )?; } - ); - if item.is_struct() { - w.write_str( - "Non-exhaustive structs could have additional fields added in future. \ - Therefore, non-exhaustive structs cannot be constructed in external crates \ - using the traditional Struct { .. } syntax; cannot be \ - matched against without a wildcard ..; and \ - struct update syntax will not work.", - ); - } else if item.is_enum() { - w.write_str( - "Non-exhaustive enums could have additional variants added in future. \ - Therefore, when matching against variants of non-exhaustive enums, an \ - extra wildcard arm must be added to account for any future variants.", - ); - } else if item.is_variant() { - w.write_str( - "Non-exhaustive enum variants could have additional fields added in future. \ - Therefore, non-exhaustive enum variants cannot be constructed in external \ - crates and cannot be matched against.", - ); - } else { - w.write_str( - "This type will require a wildcard arm in any match statements or constructors.", - ); + f.write_str("
")?; } - - w.write_str("
"); - } + Ok(()) + }) } -fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { - fn write_size_of_layout(w: &mut Buffer, layout: &LayoutS, tag_size: u64) { +fn document_type_layout<'a, 'cx: 'a>( + cx: &'a Context<'cx>, + ty_def_id: DefId, +) -> impl fmt::Display + 'a + Captures<'cx> { + fn write_size_of_layout(mut w: impl fmt::Write, layout: &LayoutS, tag_size: u64) { if layout.abi.is_unsized() { - write!(w, "(unsized)"); + write!(w, "(unsized)").unwrap(); } else { let size = layout.size.bytes() - tag_size; - write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" },); + write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" }).unwrap(); if layout.abi.is_uninhabited() { write!( w, " (uninhabited)" - ); + ).unwrap(); } } } - if !cx.shared.show_type_layout { - return; - } + display_fn(move |mut f| { + if !cx.shared.show_type_layout { + return Ok(()); + } - writeln!( - w, - "

\ - Layout§

" - ); - writeln!(w, "
"); + writeln!( + f, + "

\ + Layout§

" + )?; + writeln!(f, "
")?; - let tcx = cx.tcx(); - let param_env = tcx.param_env(ty_def_id); - let ty = tcx.type_of(ty_def_id).subst_identity(); - match tcx.layout_of(param_env.and(ty)) { - Ok(ty_layout) => { - writeln!( - w, - "

Note: Most layout information is \ - completely unstable and may even differ between compilations. \ - The only exception is types with certain repr(...) attributes. \ - Please see the Rust Reference’s \ - “Type Layout” \ - chapter for details on type layout guarantees.

" - ); - w.write_str("

Size: "); - write_size_of_layout(w, &ty_layout.layout.0, 0); - writeln!(w, "

"); - if let Variants::Multiple { variants, tag, tag_encoding, .. } = - &ty_layout.layout.variants() - { - if !variants.is_empty() { - w.write_str( - "

Size for each variant:

\ -
    ", - ); + let tcx = cx.tcx(); + let param_env = tcx.param_env(ty_def_id); + let ty = tcx.type_of(ty_def_id).subst_identity(); + match tcx.layout_of(param_env.and(ty)) { + Ok(ty_layout) => { + writeln!( + f, + "

    Note: Most layout information is \ + completely unstable and may even differ between compilations. \ + The only exception is types with certain repr(...) attributes. \ + Please see the Rust Reference’s \ + “Type Layout” \ + chapter for details on type layout guarantees.

    " + )?; + f.write_str("

    Size: ")?; + write_size_of_layout(&mut f, &ty_layout.layout.0, 0); + writeln!(f, "

    ")?; + if let Variants::Multiple { variants, tag, tag_encoding, .. } = + &ty_layout.layout.variants() + { + if !variants.is_empty() { + f.write_str( + "

    Size for each variant:

    \ +
      ", + )?; - let Adt(adt, _) = ty_layout.ty.kind() else { - span_bug!(tcx.def_span(ty_def_id), "not an adt") - }; + let Adt(adt, _) = ty_layout.ty.kind() else { + span_bug!(tcx.def_span(ty_def_id), "not an adt") + }; - let tag_size = if let TagEncoding::Niche { .. } = tag_encoding { - 0 - } else if let Primitive::Int(i, _) = tag.primitive() { - i.size().bytes() - } else { - span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int") - }; + let tag_size = if let TagEncoding::Niche { .. } = tag_encoding { + 0 + } else if let Primitive::Int(i, _) = tag.primitive() { + i.size().bytes() + } else { + span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int") + }; - for (index, layout) in variants.iter_enumerated() { - let name = adt.variant(index).name; - write!(w, "
    • {name}: "); - write_size_of_layout(w, layout, tag_size); - writeln!(w, "
    • "); + for (index, layout) in variants.iter_enumerated() { + let name = adt.variant(index).name; + write!(&mut f, "
    • {name}: ")?; + write_size_of_layout(&mut f, layout, tag_size); + writeln!(&mut f, "
    • ")?; + } + f.write_str("
    ")?; } - w.write_str("
"); } } + // This kind of layout error can occur with valid code, e.g. if you try to + // get the layout of a generic type such as `Vec`. + Err(LayoutError::Unknown(_)) => { + writeln!( + f, + "

Note: Unable to compute type layout, \ + possibly due to this type having generic parameters. \ + Layout can only be computed for concrete, fully-instantiated types.

" + )?; + } + // This kind of error probably can't happen with valid code, but we don't + // want to panic and prevent the docs from building, so we just let the + // user know that we couldn't compute the layout. + Err(LayoutError::SizeOverflow(_)) => { + writeln!( + f, + "

Note: Encountered an error during type layout; \ + the type was too big.

" + )?; + } + Err(LayoutError::NormalizationFailure(_, _)) => { + writeln!( + f, + "

Note: Encountered an error during type layout; \ + the type failed to be normalized.

" + )?; + } } - // This kind of layout error can occur with valid code, e.g. if you try to - // get the layout of a generic type such as `Vec`. - Err(LayoutError::Unknown(_)) => { - writeln!( - w, - "

Note: Unable to compute type layout, \ - possibly due to this type having generic parameters. \ - Layout can only be computed for concrete, fully-instantiated types.

" - ); - } - // This kind of error probably can't happen with valid code, but we don't - // want to panic and prevent the docs from building, so we just let the - // user know that we couldn't compute the layout. - Err(LayoutError::SizeOverflow(_)) => { - writeln!( - w, - "

Note: Encountered an error during type layout; \ - the type was too big.

" - ); - } - Err(LayoutError::NormalizationFailure(_, _)) => { - writeln!( - w, - "

Note: Encountered an error during type layout; \ - the type failed to be normalized.

" - ) - } - } - writeln!(w, "
"); + writeln!(f, "
") + }) } fn pluralize(count: usize) -> &'static str { diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html new file mode 100644 index 000000000000..a01457971c17 --- /dev/null +++ b/src/librustdoc/html/templates/item_union.html @@ -0,0 +1,23 @@ +

+    {{ self.render_attributes_in_pre() | safe }}
+    {{ self.render_union() | safe }}
+
+{{ self.document() | safe }} +{% if self.fields_iter().peek().is_some() %} +

+ Fields§ +

+ {% for (field, ty) in self.fields_iter() %} + {% let name = field.name.expect("union field name") %} + + § + {{ name }}: {{ self.print_ty(ty) | safe }} + + {% if let Some(stability_class) = self.stability_field(field) %} + + {% endif %} + {{ self.document_field(field) | safe }} + {% endfor %} +{% endif %} +{{ self.render_assoc_items() | safe }} +{{ self.document_type_layout() | safe }} From 906bdd3bdb5423794971786d3b0783206645b340 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 5 Apr 2023 17:13:00 +0200 Subject: [PATCH 129/267] Improve display of logo on very small screens --- src/librustdoc/html/static/css/rustdoc.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 726394d8348e..e86eaa65b75b 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -6,6 +6,10 @@ 3. Copy the filenames with updated suffixes from the directory. */ +:root { + --nav-sub-mobile-padding: 8px; +} + /* See FiraSans-LICENSE.txt for the Fira Sans license. */ @font-face { font-family: 'Fira Sans'; @@ -1726,7 +1730,7 @@ in main.js .source nav.sub { margin: 0; - padding: 8px; + padding: var(--nav-sub-mobile-padding); } } @@ -1783,6 +1787,7 @@ in main.js .sub-logo-container > img { height: 35px; width: 35px; + margin-bottom: var(--nav-sub-mobile-padding); } } From bb0969cae0d255f1e66879537e4b4dad70fce199 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sat, 11 Feb 2023 07:23:57 -0800 Subject: [PATCH 130/267] Use SipHash-1-3 instead of SipHash-2-4 for StableHasher --- compiler/rustc_data_structures/src/sip128.rs | 20 +- .../rustc_data_structures/src/sip128/tests.rs | 325 ++++-------------- 2 files changed, 75 insertions(+), 270 deletions(-) diff --git a/compiler/rustc_data_structures/src/sip128.rs b/compiler/rustc_data_structures/src/sip128.rs index 90793a97ed0d..d849fe0373f2 100644 --- a/compiler/rustc_data_structures/src/sip128.rs +++ b/compiler/rustc_data_structures/src/sip128.rs @@ -247,7 +247,7 @@ impl SipHasher128 { for i in 0..BUFFER_CAPACITY { let elem = self.buf.get_unchecked(i).assume_init().to_le(); self.state.v3 ^= elem; - Sip24Rounds::c_rounds(&mut self.state); + Sip13Rounds::c_rounds(&mut self.state); self.state.v0 ^= elem; } @@ -327,7 +327,7 @@ impl SipHasher128 { for i in 0..last { let elem = self.buf.get_unchecked(i).assume_init().to_le(); self.state.v3 ^= elem; - Sip24Rounds::c_rounds(&mut self.state); + Sip13Rounds::c_rounds(&mut self.state); self.state.v0 ^= elem; } @@ -340,7 +340,7 @@ impl SipHasher128 { for _ in 0..elems_left { let elem = (msg.as_ptr().add(processed) as *const u64).read_unaligned().to_le(); self.state.v3 ^= elem; - Sip24Rounds::c_rounds(&mut self.state); + Sip13Rounds::c_rounds(&mut self.state); self.state.v0 ^= elem; processed += ELEM_SIZE; } @@ -368,7 +368,7 @@ impl SipHasher128 { for i in 0..last { let elem = unsafe { self.buf.get_unchecked(i).assume_init().to_le() }; state.v3 ^= elem; - Sip24Rounds::c_rounds(&mut state); + Sip13Rounds::c_rounds(&mut state); state.v0 ^= elem; } @@ -392,15 +392,15 @@ impl SipHasher128 { let b: u64 = ((length as u64 & 0xff) << 56) | elem; state.v3 ^= b; - Sip24Rounds::c_rounds(&mut state); + Sip13Rounds::c_rounds(&mut state); state.v0 ^= b; state.v2 ^= 0xee; - Sip24Rounds::d_rounds(&mut state); + Sip13Rounds::d_rounds(&mut state); let _0 = state.v0 ^ state.v1 ^ state.v2 ^ state.v3; state.v1 ^= 0xdd; - Sip24Rounds::d_rounds(&mut state); + Sip13Rounds::d_rounds(&mut state); let _1 = state.v0 ^ state.v1 ^ state.v2 ^ state.v3; (_0, _1) @@ -477,13 +477,12 @@ impl Hasher for SipHasher128 { } #[derive(Debug, Clone, Default)] -struct Sip24Rounds; +struct Sip13Rounds; -impl Sip24Rounds { +impl Sip13Rounds { #[inline] fn c_rounds(state: &mut State) { compress!(state); - compress!(state); } #[inline] @@ -491,6 +490,5 @@ impl Sip24Rounds { compress!(state); compress!(state); compress!(state); - compress!(state); } } diff --git a/compiler/rustc_data_structures/src/sip128/tests.rs b/compiler/rustc_data_structures/src/sip128/tests.rs index 5fe967c4158f..cc6d3b0f4715 100644 --- a/compiler/rustc_data_structures/src/sip128/tests.rs +++ b/compiler/rustc_data_structures/src/sip128/tests.rs @@ -22,269 +22,76 @@ fn hash_with(mut st: SipHasher128, x: &T) -> (u64, u64) { fn hash(x: &T) -> (u64, u64) { hash_with(SipHasher128::new_with_keys(0, 0), x) } - +#[rustfmt::skip] const TEST_VECTOR: [[u8; 16]; 64] = [ - [ - 0xa3, 0x81, 0x7f, 0x04, 0xba, 0x25, 0xa8, 0xe6, 0x6d, 0xf6, 0x72, 0x14, 0xc7, 0x55, 0x02, - 0x93, - ], - [ - 0xda, 0x87, 0xc1, 0xd8, 0x6b, 0x99, 0xaf, 0x44, 0x34, 0x76, 0x59, 0x11, 0x9b, 0x22, 0xfc, - 0x45, - ], - [ - 0x81, 0x77, 0x22, 0x8d, 0xa4, 0xa4, 0x5d, 0xc7, 0xfc, 0xa3, 0x8b, 0xde, 0xf6, 0x0a, 0xff, - 0xe4, - ], - [ - 0x9c, 0x70, 0xb6, 0x0c, 0x52, 0x67, 0xa9, 0x4e, 0x5f, 0x33, 0xb6, 0xb0, 0x29, 0x85, 0xed, - 0x51, - ], - [ - 0xf8, 0x81, 0x64, 0xc1, 0x2d, 0x9c, 0x8f, 0xaf, 0x7d, 0x0f, 0x6e, 0x7c, 0x7b, 0xcd, 0x55, - 0x79, - ], - [ - 0x13, 0x68, 0x87, 0x59, 0x80, 0x77, 0x6f, 0x88, 0x54, 0x52, 0x7a, 0x07, 0x69, 0x0e, 0x96, - 0x27, - ], - [ - 0x14, 0xee, 0xca, 0x33, 0x8b, 0x20, 0x86, 0x13, 0x48, 0x5e, 0xa0, 0x30, 0x8f, 0xd7, 0xa1, - 0x5e, - ], - [ - 0xa1, 0xf1, 0xeb, 0xbe, 0xd8, 0xdb, 0xc1, 0x53, 0xc0, 0xb8, 0x4a, 0xa6, 0x1f, 0xf0, 0x82, - 0x39, - ], - [ - 0x3b, 0x62, 0xa9, 0xba, 0x62, 0x58, 0xf5, 0x61, 0x0f, 0x83, 0xe2, 0x64, 0xf3, 0x14, 0x97, - 0xb4, - ], - [ - 0x26, 0x44, 0x99, 0x06, 0x0a, 0xd9, 0xba, 0xab, 0xc4, 0x7f, 0x8b, 0x02, 0xbb, 0x6d, 0x71, - 0xed, - ], - [ - 0x00, 0x11, 0x0d, 0xc3, 0x78, 0x14, 0x69, 0x56, 0xc9, 0x54, 0x47, 0xd3, 0xf3, 0xd0, 0xfb, - 0xba, - ], - [ - 0x01, 0x51, 0xc5, 0x68, 0x38, 0x6b, 0x66, 0x77, 0xa2, 0xb4, 0xdc, 0x6f, 0x81, 0xe5, 0xdc, - 0x18, - ], - [ - 0xd6, 0x26, 0xb2, 0x66, 0x90, 0x5e, 0xf3, 0x58, 0x82, 0x63, 0x4d, 0xf6, 0x85, 0x32, 0xc1, - 0x25, - ], - [ - 0x98, 0x69, 0xe2, 0x47, 0xe9, 0xc0, 0x8b, 0x10, 0xd0, 0x29, 0x93, 0x4f, 0xc4, 0xb9, 0x52, - 0xf7, - ], - [ - 0x31, 0xfc, 0xef, 0xac, 0x66, 0xd7, 0xde, 0x9c, 0x7e, 0xc7, 0x48, 0x5f, 0xe4, 0x49, 0x49, - 0x02, - ], - [ - 0x54, 0x93, 0xe9, 0x99, 0x33, 0xb0, 0xa8, 0x11, 0x7e, 0x08, 0xec, 0x0f, 0x97, 0xcf, 0xc3, - 0xd9, - ], - [ - 0x6e, 0xe2, 0xa4, 0xca, 0x67, 0xb0, 0x54, 0xbb, 0xfd, 0x33, 0x15, 0xbf, 0x85, 0x23, 0x05, - 0x77, - ], - [ - 0x47, 0x3d, 0x06, 0xe8, 0x73, 0x8d, 0xb8, 0x98, 0x54, 0xc0, 0x66, 0xc4, 0x7a, 0xe4, 0x77, - 0x40, - ], - [ - 0xa4, 0x26, 0xe5, 0xe4, 0x23, 0xbf, 0x48, 0x85, 0x29, 0x4d, 0xa4, 0x81, 0xfe, 0xae, 0xf7, - 0x23, - ], - [ - 0x78, 0x01, 0x77, 0x31, 0xcf, 0x65, 0xfa, 0xb0, 0x74, 0xd5, 0x20, 0x89, 0x52, 0x51, 0x2e, - 0xb1, - ], - [ - 0x9e, 0x25, 0xfc, 0x83, 0x3f, 0x22, 0x90, 0x73, 0x3e, 0x93, 0x44, 0xa5, 0xe8, 0x38, 0x39, - 0xeb, - ], - [ - 0x56, 0x8e, 0x49, 0x5a, 0xbe, 0x52, 0x5a, 0x21, 0x8a, 0x22, 0x14, 0xcd, 0x3e, 0x07, 0x1d, - 0x12, - ], - [ - 0x4a, 0x29, 0xb5, 0x45, 0x52, 0xd1, 0x6b, 0x9a, 0x46, 0x9c, 0x10, 0x52, 0x8e, 0xff, 0x0a, - 0xae, - ], - [ - 0xc9, 0xd1, 0x84, 0xdd, 0xd5, 0xa9, 0xf5, 0xe0, 0xcf, 0x8c, 0xe2, 0x9a, 0x9a, 0xbf, 0x69, - 0x1c, - ], - [ - 0x2d, 0xb4, 0x79, 0xae, 0x78, 0xbd, 0x50, 0xd8, 0x88, 0x2a, 0x8a, 0x17, 0x8a, 0x61, 0x32, - 0xad, - ], - [ - 0x8e, 0xce, 0x5f, 0x04, 0x2d, 0x5e, 0x44, 0x7b, 0x50, 0x51, 0xb9, 0xea, 0xcb, 0x8d, 0x8f, - 0x6f, - ], - [ - 0x9c, 0x0b, 0x53, 0xb4, 0xb3, 0xc3, 0x07, 0xe8, 0x7e, 0xae, 0xe0, 0x86, 0x78, 0x14, 0x1f, - 0x66, - ], - [ - 0xab, 0xf2, 0x48, 0xaf, 0x69, 0xa6, 0xea, 0xe4, 0xbf, 0xd3, 0xeb, 0x2f, 0x12, 0x9e, 0xeb, - 0x94, - ], - [ - 0x06, 0x64, 0xda, 0x16, 0x68, 0x57, 0x4b, 0x88, 0xb9, 0x35, 0xf3, 0x02, 0x73, 0x58, 0xae, - 0xf4, - ], - [ - 0xaa, 0x4b, 0x9d, 0xc4, 0xbf, 0x33, 0x7d, 0xe9, 0x0c, 0xd4, 0xfd, 0x3c, 0x46, 0x7c, 0x6a, - 0xb7, - ], - [ - 0xea, 0x5c, 0x7f, 0x47, 0x1f, 0xaf, 0x6b, 0xde, 0x2b, 0x1a, 0xd7, 0xd4, 0x68, 0x6d, 0x22, - 0x87, - ], - [ - 0x29, 0x39, 0xb0, 0x18, 0x32, 0x23, 0xfa, 0xfc, 0x17, 0x23, 0xde, 0x4f, 0x52, 0xc4, 0x3d, - 0x35, - ], - [ - 0x7c, 0x39, 0x56, 0xca, 0x5e, 0xea, 0xfc, 0x3e, 0x36, 0x3e, 0x9d, 0x55, 0x65, 0x46, 0xeb, - 0x68, - ], - [ - 0x77, 0xc6, 0x07, 0x71, 0x46, 0xf0, 0x1c, 0x32, 0xb6, 0xb6, 0x9d, 0x5f, 0x4e, 0xa9, 0xff, - 0xcf, - ], - [ - 0x37, 0xa6, 0x98, 0x6c, 0xb8, 0x84, 0x7e, 0xdf, 0x09, 0x25, 0xf0, 0xf1, 0x30, 0x9b, 0x54, - 0xde, - ], - [ - 0xa7, 0x05, 0xf0, 0xe6, 0x9d, 0xa9, 0xa8, 0xf9, 0x07, 0x24, 0x1a, 0x2e, 0x92, 0x3c, 0x8c, - 0xc8, - ], - [ - 0x3d, 0xc4, 0x7d, 0x1f, 0x29, 0xc4, 0x48, 0x46, 0x1e, 0x9e, 0x76, 0xed, 0x90, 0x4f, 0x67, - 0x11, - ], - [ - 0x0d, 0x62, 0xbf, 0x01, 0xe6, 0xfc, 0x0e, 0x1a, 0x0d, 0x3c, 0x47, 0x51, 0xc5, 0xd3, 0x69, - 0x2b, - ], - [ - 0x8c, 0x03, 0x46, 0x8b, 0xca, 0x7c, 0x66, 0x9e, 0xe4, 0xfd, 0x5e, 0x08, 0x4b, 0xbe, 0xe7, - 0xb5, - ], - [ - 0x52, 0x8a, 0x5b, 0xb9, 0x3b, 0xaf, 0x2c, 0x9c, 0x44, 0x73, 0xcc, 0xe5, 0xd0, 0xd2, 0x2b, - 0xd9, - ], - [ - 0xdf, 0x6a, 0x30, 0x1e, 0x95, 0xc9, 0x5d, 0xad, 0x97, 0xae, 0x0c, 0xc8, 0xc6, 0x91, 0x3b, - 0xd8, - ], - [ - 0x80, 0x11, 0x89, 0x90, 0x2c, 0x85, 0x7f, 0x39, 0xe7, 0x35, 0x91, 0x28, 0x5e, 0x70, 0xb6, - 0xdb, - ], - [ - 0xe6, 0x17, 0x34, 0x6a, 0xc9, 0xc2, 0x31, 0xbb, 0x36, 0x50, 0xae, 0x34, 0xcc, 0xca, 0x0c, - 0x5b, - ], - [ - 0x27, 0xd9, 0x34, 0x37, 0xef, 0xb7, 0x21, 0xaa, 0x40, 0x18, 0x21, 0xdc, 0xec, 0x5a, 0xdf, - 0x89, - ], - [ - 0x89, 0x23, 0x7d, 0x9d, 0xed, 0x9c, 0x5e, 0x78, 0xd8, 0xb1, 0xc9, 0xb1, 0x66, 0xcc, 0x73, - 0x42, - ], - [ - 0x4a, 0x6d, 0x80, 0x91, 0xbf, 0x5e, 0x7d, 0x65, 0x11, 0x89, 0xfa, 0x94, 0xa2, 0x50, 0xb1, - 0x4c, - ], - [ - 0x0e, 0x33, 0xf9, 0x60, 0x55, 0xe7, 0xae, 0x89, 0x3f, 0xfc, 0x0e, 0x3d, 0xcf, 0x49, 0x29, - 0x02, - ], - [ - 0xe6, 0x1c, 0x43, 0x2b, 0x72, 0x0b, 0x19, 0xd1, 0x8e, 0xc8, 0xd8, 0x4b, 0xdc, 0x63, 0x15, - 0x1b, - ], - [ - 0xf7, 0xe5, 0xae, 0xf5, 0x49, 0xf7, 0x82, 0xcf, 0x37, 0x90, 0x55, 0xa6, 0x08, 0x26, 0x9b, - 0x16, - ], - [ - 0x43, 0x8d, 0x03, 0x0f, 0xd0, 0xb7, 0xa5, 0x4f, 0xa8, 0x37, 0xf2, 0xad, 0x20, 0x1a, 0x64, - 0x03, - ], - [ - 0xa5, 0x90, 0xd3, 0xee, 0x4f, 0xbf, 0x04, 0xe3, 0x24, 0x7e, 0x0d, 0x27, 0xf2, 0x86, 0x42, - 0x3f, - ], - [ - 0x5f, 0xe2, 0xc1, 0xa1, 0x72, 0xfe, 0x93, 0xc4, 0xb1, 0x5c, 0xd3, 0x7c, 0xae, 0xf9, 0xf5, - 0x38, - ], - [ - 0x2c, 0x97, 0x32, 0x5c, 0xbd, 0x06, 0xb3, 0x6e, 0xb2, 0x13, 0x3d, 0xd0, 0x8b, 0x3a, 0x01, - 0x7c, - ], - [ - 0x92, 0xc8, 0x14, 0x22, 0x7a, 0x6b, 0xca, 0x94, 0x9f, 0xf0, 0x65, 0x9f, 0x00, 0x2a, 0xd3, - 0x9e, - ], - [ - 0xdc, 0xe8, 0x50, 0x11, 0x0b, 0xd8, 0x32, 0x8c, 0xfb, 0xd5, 0x08, 0x41, 0xd6, 0x91, 0x1d, - 0x87, - ], - [ - 0x67, 0xf1, 0x49, 0x84, 0xc7, 0xda, 0x79, 0x12, 0x48, 0xe3, 0x2b, 0xb5, 0x92, 0x25, 0x83, - 0xda, - ], - [ - 0x19, 0x38, 0xf2, 0xcf, 0x72, 0xd5, 0x4e, 0xe9, 0x7e, 0x94, 0x16, 0x6f, 0xa9, 0x1d, 0x2a, - 0x36, - ], - [ - 0x74, 0x48, 0x1e, 0x96, 0x46, 0xed, 0x49, 0xfe, 0x0f, 0x62, 0x24, 0x30, 0x16, 0x04, 0x69, - 0x8e, - ], - [ - 0x57, 0xfc, 0xa5, 0xde, 0x98, 0xa9, 0xd6, 0xd8, 0x00, 0x64, 0x38, 0xd0, 0x58, 0x3d, 0x8a, - 0x1d, - ], - [ - 0x9f, 0xec, 0xde, 0x1c, 0xef, 0xdc, 0x1c, 0xbe, 0xd4, 0x76, 0x36, 0x74, 0xd9, 0x57, 0x53, - 0x59, - ], - [ - 0xe3, 0x04, 0x0c, 0x00, 0xeb, 0x28, 0xf1, 0x53, 0x66, 0xca, 0x73, 0xcb, 0xd8, 0x72, 0xe7, - 0x40, - ], - [ - 0x76, 0x97, 0x00, 0x9a, 0x6a, 0x83, 0x1d, 0xfe, 0xcc, 0xa9, 0x1c, 0x59, 0x93, 0x67, 0x0f, - 0x7a, - ], - [ - 0x58, 0x53, 0x54, 0x23, 0x21, 0xf5, 0x67, 0xa0, 0x05, 0xd5, 0x47, 0xa4, 0xf0, 0x47, 0x59, - 0xbd, - ], - [ - 0x51, 0x50, 0xd1, 0x77, 0x2f, 0x50, 0x83, 0x4a, 0x50, 0x3e, 0x06, 0x9a, 0x97, 0x3f, 0xbd, - 0x7c, - ], + [0xe7, 0x7e, 0xbc, 0xb2, 0x27, 0x88, 0xa5, 0xbe, 0xfd, 0x62, 0xdb, 0x6a, 0xdd, 0x30, 0x30, 0x01], + [0xfc, 0x6f, 0x37, 0x04, 0x60, 0xd3, 0xed, 0xa8, 0x5e, 0x05, 0x73, 0xcc, 0x2b, 0x2f, 0xf0, 0x63], + [0x75, 0x78, 0x7f, 0x09, 0x05, 0x69, 0x83, 0x9b, 0x85, 0x5b, 0xc9, 0x54, 0x8c, 0x6a, 0xea, 0x95], + [0x6b, 0xc5, 0xcc, 0xfa, 0x1e, 0xdc, 0xf7, 0x9f, 0x48, 0x23, 0x18, 0x77, 0x12, 0xeb, 0xd7, 0x43], + [0x0c, 0x78, 0x4e, 0x71, 0xac, 0x2b, 0x28, 0x5a, 0x9f, 0x8e, 0x92, 0xe7, 0x8f, 0xbf, 0x2c, 0x25], + [0xf3, 0x28, 0xdb, 0x89, 0x34, 0x5b, 0x62, 0x0c, 0x79, 0x52, 0x29, 0xa4, 0x26, 0x95, 0x84, 0x3e], + [0xdc, 0xd0, 0x3d, 0x29, 0xf7, 0x43, 0xe7, 0x10, 0x09, 0x51, 0xb0, 0xe8, 0x39, 0x85, 0xa6, 0xf8], + [0x10, 0x84, 0xb9, 0x23, 0xf2, 0xaa, 0xe0, 0xc3, 0xa6, 0x2f, 0x2e, 0xc8, 0x08, 0x48, 0xab, 0x77], + [0xaa, 0x12, 0xfe, 0xe1, 0xd5, 0xe3, 0xda, 0xb4, 0x72, 0x4f, 0x16, 0xab, 0x35, 0xf9, 0xc7, 0x99], + [0x81, 0xdd, 0xb8, 0x04, 0x2c, 0xf3, 0x39, 0x94, 0xf4, 0x72, 0x0e, 0x00, 0x94, 0x13, 0x7c, 0x42], + [0x4f, 0xaa, 0x54, 0x1d, 0x5d, 0x49, 0x8e, 0x89, 0xba, 0x0e, 0xa4, 0xc3, 0x87, 0xb2, 0x2f, 0xb4], + [0x72, 0x3b, 0x9a, 0xf3, 0x55, 0x44, 0x91, 0xdb, 0xb1, 0xd6, 0x63, 0x3d, 0xfc, 0x6e, 0x0c, 0x4e], + [0xe5, 0x3f, 0x92, 0x85, 0x9e, 0x48, 0x19, 0xa8, 0xdc, 0x06, 0x95, 0x73, 0x9f, 0xea, 0x8c, 0x65], + [0xb2, 0xf8, 0x58, 0xc7, 0xc9, 0xea, 0x80, 0x1d, 0x53, 0xd6, 0x03, 0x59, 0x6d, 0x65, 0x78, 0x44], + [0x87, 0xe7, 0x62, 0x68, 0xdb, 0xc9, 0x22, 0x72, 0x26, 0xb0, 0xca, 0x66, 0x5f, 0x64, 0xe3, 0x78], + [0xc1, 0x7e, 0x55, 0x05, 0xb2, 0xbd, 0x52, 0x6c, 0x29, 0x21, 0xcd, 0xec, 0x1e, 0x7e, 0x01, 0x09], + [0xd0, 0xa8, 0xd9, 0x57, 0x15, 0x51, 0x8e, 0xeb, 0xb5, 0x13, 0xb0, 0xf8, 0x3d, 0x9e, 0x17, 0x93], + [0x23, 0x41, 0x26, 0xf9, 0x3f, 0xbb, 0x66, 0x8d, 0x97, 0x51, 0x12, 0xe8, 0xfe, 0xbd, 0xf7, 0xec], + [0xef, 0x42, 0xf0, 0x3d, 0xb7, 0x8f, 0x70, 0x4d, 0x02, 0x3c, 0x44, 0x9f, 0x16, 0xb7, 0x09, 0x2b], + [0xab, 0xf7, 0x62, 0x38, 0xc2, 0x0a, 0xf1, 0x61, 0xb2, 0x31, 0x4b, 0x4d, 0x55, 0x26, 0xbc, 0xe9], + [0x3c, 0x2c, 0x2f, 0x11, 0xbb, 0x90, 0xcf, 0x0b, 0xe3, 0x35, 0xca, 0x9b, 0x2e, 0x91, 0xe9, 0xb7], + [0x2a, 0x7a, 0x68, 0x0f, 0x22, 0xa0, 0x2a, 0x92, 0xf4, 0x51, 0x49, 0xd2, 0x0f, 0xec, 0xe0, 0xef], + [0xc9, 0xa8, 0xd1, 0x30, 0x23, 0x1d, 0xd4, 0x3e, 0x42, 0xe6, 0x45, 0x69, 0x57, 0xf8, 0x37, 0x79], + [0x1d, 0x12, 0x7b, 0x84, 0x40, 0x5c, 0xea, 0xb9, 0x9f, 0xd8, 0x77, 0x5a, 0x9b, 0xe6, 0xc5, 0x59], + [0x9e, 0x4b, 0xf8, 0x37, 0xbc, 0xfd, 0x92, 0xca, 0xce, 0x09, 0xd2, 0x06, 0x1a, 0x84, 0xd0, 0x4a], + [0x39, 0x03, 0x1a, 0x96, 0x5d, 0x73, 0xb4, 0xaf, 0x5a, 0x27, 0x4d, 0x18, 0xf9, 0x73, 0xb1, 0xd2], + [0x7f, 0x4d, 0x0a, 0x12, 0x09, 0xd6, 0x7e, 0x4e, 0xd0, 0x6f, 0x75, 0x38, 0xe1, 0xcf, 0xad, 0x64], + [0xe6, 0x1e, 0xe2, 0x40, 0xfb, 0xdc, 0xce, 0x38, 0x96, 0x9f, 0x4c, 0xd2, 0x49, 0x27, 0xdd, 0x93], + [0x4c, 0x3b, 0xa2, 0xb3, 0x7b, 0x0f, 0xdd, 0x8c, 0xfa, 0x5e, 0x95, 0xc1, 0x89, 0xb2, 0x94, 0x14], + [0xe0, 0x6f, 0xd4, 0xca, 0x06, 0x6f, 0xec, 0xdd, 0x54, 0x06, 0x8a, 0x5a, 0xd8, 0x89, 0x6f, 0x86], + [0x5c, 0xa8, 0x4c, 0x34, 0x13, 0x9c, 0x65, 0x80, 0xa8, 0x8a, 0xf2, 0x49, 0x90, 0x72, 0x07, 0x06], + [0x42, 0xea, 0x96, 0x1c, 0x5b, 0x3c, 0x85, 0x8b, 0x17, 0xc3, 0xe5, 0x50, 0xdf, 0xa7, 0x90, 0x10], + [0x40, 0x6c, 0x44, 0xde, 0xe6, 0x78, 0x57, 0xb2, 0x94, 0x31, 0x60, 0xf3, 0x0c, 0x74, 0x17, 0xd3], + [0xc5, 0xf5, 0x7b, 0xae, 0x13, 0x20, 0xfc, 0xf4, 0xb4, 0xe8, 0x68, 0xe7, 0x1d, 0x56, 0xc6, 0x6b], + [0x04, 0xbf, 0x73, 0x7a, 0x5b, 0x67, 0x6b, 0xe7, 0xc3, 0xde, 0x05, 0x01, 0x7d, 0xf4, 0xbf, 0xf9], + [0x51, 0x63, 0xc9, 0xc0, 0x3f, 0x19, 0x07, 0xea, 0x10, 0x44, 0xed, 0x5c, 0x30, 0x72, 0x7b, 0x4f], + [0x37, 0xa1, 0x10, 0xf0, 0x02, 0x71, 0x8e, 0xda, 0xd2, 0x4b, 0x3f, 0x9e, 0xe4, 0x53, 0xf1, 0x40], + [0xb9, 0x87, 0x7e, 0x38, 0x1a, 0xed, 0xd3, 0xda, 0x08, 0xc3, 0x3e, 0x75, 0xff, 0x23, 0xac, 0x10], + [0x7c, 0x50, 0x04, 0x00, 0x5e, 0xc5, 0xda, 0x4c, 0x5a, 0xc9, 0x44, 0x0e, 0x5c, 0x72, 0x31, 0x93], + [0x81, 0xb8, 0x24, 0x37, 0x83, 0xdb, 0xc6, 0x46, 0xca, 0x9d, 0x0c, 0xd8, 0x2a, 0xbd, 0xb4, 0x6c], + [0x50, 0x57, 0x20, 0x54, 0x3e, 0xb9, 0xb4, 0x13, 0xd5, 0x0b, 0x3c, 0xfa, 0xd9, 0xee, 0xf9, 0x38], + [0x94, 0x5f, 0x59, 0x4d, 0xe7, 0x24, 0x11, 0xe4, 0xd3, 0x35, 0xbe, 0x87, 0x44, 0x56, 0xd8, 0xf3], + [0x37, 0x92, 0x3b, 0x3e, 0x37, 0x17, 0x77, 0xb2, 0x11, 0x70, 0xbf, 0x9d, 0x7e, 0x62, 0xf6, 0x02], + [0x3a, 0xd4, 0xe7, 0xc8, 0x57, 0x64, 0x96, 0x46, 0x11, 0xeb, 0x0a, 0x6c, 0x4d, 0x62, 0xde, 0x56], + [0xcd, 0x91, 0x39, 0x6c, 0x44, 0xaf, 0x4f, 0x51, 0x85, 0x57, 0x8d, 0x9d, 0xd9, 0x80, 0x3f, 0x0a], + [0xfe, 0x28, 0x15, 0x8e, 0x72, 0x7b, 0x86, 0x8f, 0x39, 0x03, 0xc9, 0xac, 0xda, 0x64, 0xa2, 0x58], + [0x40, 0xcc, 0x10, 0xb8, 0x28, 0x8c, 0xe5, 0xf0, 0xbc, 0x3a, 0xc0, 0xb6, 0x8a, 0x0e, 0xeb, 0xc8], + [0x6f, 0x14, 0x90, 0xf5, 0x40, 0x69, 0x9a, 0x3c, 0xd4, 0x97, 0x44, 0x20, 0xec, 0xc9, 0x27, 0x37], + [0xd5, 0x05, 0xf1, 0xb7, 0x5e, 0x1a, 0x84, 0xa6, 0x03, 0xc4, 0x35, 0x83, 0xb2, 0xed, 0x03, 0x08], + [0x49, 0x15, 0x73, 0xcf, 0xd7, 0x2b, 0xb4, 0x68, 0x2b, 0x7c, 0xa5, 0x88, 0x0e, 0x1c, 0x8d, 0x6f], + [0x3e, 0xd6, 0x9c, 0xfe, 0x45, 0xab, 0x40, 0x3f, 0x2f, 0xd2, 0xad, 0x95, 0x9b, 0xa2, 0x76, 0x66], + [0x8b, 0xe8, 0x39, 0xef, 0x1b, 0x20, 0xb5, 0x7c, 0x83, 0xba, 0x7e, 0xb6, 0xa8, 0xc2, 0x2b, 0x6a], + [0x14, 0x09, 0x18, 0x6a, 0xb4, 0x22, 0x31, 0xfe, 0xde, 0xe1, 0x81, 0x62, 0xcf, 0x1c, 0xb4, 0xca], + [0x2b, 0xf3, 0xcc, 0xc2, 0x4a, 0xb6, 0x72, 0xcf, 0x15, 0x1f, 0xb8, 0xd2, 0xf3, 0xf3, 0x06, 0x9b], + [0xb9, 0xb9, 0x3a, 0x28, 0x82, 0xd6, 0x02, 0x5c, 0xdb, 0x8c, 0x56, 0xfa, 0x13, 0xf7, 0x53, 0x7b], + [0xd9, 0x7c, 0xca, 0x36, 0x94, 0xfb, 0x20, 0x6d, 0xb8, 0xbd, 0x1f, 0x36, 0x50, 0xc3, 0x33, 0x22], + [0x94, 0xec, 0x2e, 0x19, 0xa4, 0x0b, 0xe4, 0x1a, 0xf3, 0x94, 0x0d, 0x6b, 0x30, 0xc4, 0x93, 0x84], + [0x4b, 0x41, 0x60, 0x3f, 0x20, 0x9a, 0x04, 0x5b, 0xe1, 0x40, 0xa3, 0x41, 0xa3, 0xdf, 0xfe, 0x10], + [0x23, 0xfb, 0xcb, 0x30, 0x9f, 0x1c, 0xf0, 0x94, 0x89, 0x07, 0x55, 0xab, 0x1b, 0x42, 0x65, 0x69], + [0xe7, 0xd9, 0xb6, 0x56, 0x90, 0x91, 0x8a, 0x2b, 0x23, 0x2f, 0x2f, 0x5c, 0x12, 0xc8, 0x30, 0x0e], + [0xad, 0xe8, 0x3c, 0xf7, 0xe7, 0xf3, 0x84, 0x7b, 0x36, 0xfa, 0x4b, 0x54, 0xb0, 0x0d, 0xce, 0x61], + [0x06, 0x10, 0xc5, 0xf2, 0xee, 0x57, 0x1c, 0x8a, 0xc8, 0x0c, 0xbf, 0xe5, 0x38, 0xbd, 0xf1, 0xc7], + [0x27, 0x1d, 0x5d, 0x00, 0xfb, 0xdb, 0x5d, 0x15, 0x5d, 0x9d, 0xce, 0xa9, 0x7c, 0xb4, 0x02, 0x18], + [0x4c, 0x58, 0x00, 0xe3, 0x4e, 0xfe, 0x42, 0x6f, 0x07, 0x9f, 0x6b, 0x0a, 0xa7, 0x52, 0x60, 0xad], ]; -// Test vector from reference implementation #[test] -fn test_siphash_2_4_test_vector() { +fn test_siphash_1_3_test_vector() { let k0 = 0x_07_06_05_04_03_02_01_00; let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08; From 9d314627aa617637c608bc343477e9a6e7268bb5 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sat, 11 Feb 2023 08:50:55 -0800 Subject: [PATCH 131/267] Fix a couple missed hash constants --- compiler/rustc_data_structures/src/stable_hasher/tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_data_structures/src/stable_hasher/tests.rs b/compiler/rustc_data_structures/src/stable_hasher/tests.rs index 724be5888ddb..a98b1bc36261 100644 --- a/compiler/rustc_data_structures/src/stable_hasher/tests.rs +++ b/compiler/rustc_data_structures/src/stable_hasher/tests.rs @@ -39,7 +39,7 @@ fn test_hash_integers() { test_isize.hash(&mut h); // This depends on the hashing algorithm. See note at top of file. - let expected = (1784307454142909076, 11471672289340283879); + let expected = (13997337031081104755, 6178945012502239489); assert_eq!(h.finalize(), expected); } @@ -53,7 +53,7 @@ fn test_hash_usize() { test_usize.hash(&mut h); // This depends on the hashing algorithm. See note at top of file. - let expected = (5798740672699530587, 11186240177685111648); + let expected = (12037165114281468837, 3094087741167521712); assert_eq!(h.finalize(), expected); } @@ -67,7 +67,7 @@ fn test_hash_isize() { test_isize.hash(&mut h); // This depends on the hashing algorithm. See note at top of file. - let expected = (2789913510339652884, 674280939192711005); + let expected = (3979067582695659080, 2322428596355037273); assert_eq!(h.finalize(), expected); } From 0db1f54f89a121de06d76d9a1a3444ec128a7199 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sat, 11 Feb 2023 08:51:04 -0800 Subject: [PATCH 132/267] Bless tests --- .../inline_closure.foo.Inline.after.mir | 2 +- ...e_closure_borrows_arg.foo.Inline.after.mir | 2 +- ...line_closure_captures.foo.Inline.after.mir | 2 +- .../inline_cycle_generic.main.Inline.diff | 9 ++-- .../inline/inline_generator.main.Inline.diff | 2 +- ...ine_scopes_parenting.main.Inline.after.mir | 2 +- .../mir-opt/issue_99325.main.built.after.mir | 4 +- ...main.SimplifyCfg-elaborate-drops.after.mir | 2 +- tests/ui/consts/miri_unleashed/tls.stderr | 4 +- ...rator-print-verbose-1.drop_tracking.stderr | 8 +-- ...r-print-verbose-1.drop_tracking_mir.stderr | 8 +-- ...or-print-verbose-1.no_drop_tracking.stderr | 8 +-- .../ty-outlives/impl-trait-captures.stderr | 6 +-- tests/ui/symbol-names/basic.legacy.stderr | 4 +- tests/ui/symbol-names/basic.v0.stderr | 2 +- tests/ui/symbol-names/foreign-types.stderr | 2 +- tests/ui/symbol-names/impl1.v0.stderr | 6 +-- .../ui/symbol-names/issue-60925.legacy.stderr | 4 +- tests/ui/symbol-names/issue-60925.v0.stderr | 2 +- tests/ui/symbol-names/issue-75326.v0.stderr | 2 +- tests/ui/symbol-names/trait-objects.v0.stderr | 6 +-- tests/ui/thir-print/thir-flat.stdout | 4 +- tests/ui/thir-print/thir-tree-match.stdout | 54 +++++++++---------- tests/ui/thir-print/thir-tree.stdout | 4 +- .../higher-ranked-fn-type.verbose.stderr | 4 +- 25 files changed, 75 insertions(+), 78 deletions(-) diff --git a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir index fff8d0171277..1d2f99cbe68e 100644 --- a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir @@ -23,7 +23,7 @@ fn foo(_1: T, _2: i32) -> i32 { StorageLive(_3); // scope 0 at $DIR/inline_closure.rs:+1:9: +1:10 _3 = [closure@foo::::{closure#0}]; // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24 // closure - // + def_id: DefId(0:6 ~ inline_closure[92ba]::foo::{closure#0}) + // + def_id: DefId(0:6 ~ inline_closure[8f32]::foo::{closure#0}) // + substs: [ // T, // i8, diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir index dab2043064f3..80274bb7e7ef 100644 --- a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir @@ -26,7 +26,7 @@ fn foo(_1: T, _2: &i32) -> i32 { StorageLive(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10 _3 = [closure@foo::::{closure#0}]; // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6 // closure - // + def_id: DefId(0:6 ~ inline_closure_borrows_arg[96e9]::foo::{closure#0}) + // + def_id: DefId(0:6 ~ inline_closure_borrows_arg[f89f]::foo::{closure#0}) // + substs: [ // T, // i8, diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index 84fd051e0a35..b36711f82f40 100644 --- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -32,7 +32,7 @@ fn foo(_1: T, _2: i32) -> (i32, T) { _5 = &_1; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 _3 = [closure@foo::::{closure#0}] { q: move _4, t: move _5 }; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 // closure - // + def_id: DefId(0:6 ~ inline_closure_captures[8bc0]::foo::{closure#0}) + // + def_id: DefId(0:6 ~ inline_closure_captures[63a5]::foo::{closure#0}) // + substs: [ // T, // i8, diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff index 52debab4dd1c..04de3e61e5ff 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff @@ -6,21 +6,18 @@ let _1: (); // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 + scope 1 (inlined ::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24 + scope 2 (inlined as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31 -+ scope 3 (inlined ::call) { // at $DIR/inline_cycle_generic.rs:31:9: 31:28 -+ scope 4 (inlined as Call>::call) { // at $DIR/inline_cycle_generic.rs:23:9: 23:31 -+ } -+ } + } + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 - _1 = ::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 -+ _1 = ::call() -> bb1; // scope 4 at $DIR/inline_cycle_generic.rs:31:9: 31:28 ++ _1 = ::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:31:9: 31:28 // mir::Constant - // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22 +- // + literal: Const { ty: fn() {::call}, val: Value() } + // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26 - // + literal: Const { ty: fn() {::call}, val: Value() } ++ // + literal: Const { ty: fn() {::call}, val: Value() } } bb1: { diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.diff b/tests/mir-opt/inline/inline_generator.main.Inline.diff index 01f5052b6528..c3ca2d7d42c2 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.diff @@ -44,7 +44,7 @@ - bb1: { + _4 = [generator@$DIR/inline_generator.rs:15:5: 15:8 (#0)]; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41 + // generator -+ // + def_id: DefId(0:7 ~ inline_generator[ea31]::g::{closure#0}) ++ // + def_id: DefId(0:7 ~ inline_generator[e37e]::g::{closure#0}) + // + substs: [ + // bool, + // i32, diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir index a98c294cacbe..1da3c8bb7977 100644 --- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir @@ -21,7 +21,7 @@ fn main() -> () { StorageLive(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10 _1 = [closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33 // closure - // + def_id: DefId(0:4 ~ issue_76997_inline_scopes_parenting[bc59]::main::{closure#0}) + // + def_id: DefId(0:4 ~ issue_76997_inline_scopes_parenting[5cd2]::main::{closure#0}) // + substs: [ // i8, // extern "rust-call" fn(((),)), diff --git a/tests/mir-opt/issue_99325.main.built.after.mir b/tests/mir-opt/issue_99325.main.built.after.mir index c08f03deeafa..2324f53566c1 100644 --- a/tests/mir-opt/issue_99325.main.built.after.mir +++ b/tests/mir-opt/issue_99325.main.built.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[22bb]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue_99325.rs:+0:15: +0:15 diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index d7b6d64b6b7b..2eb2a0980ce2 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -108,7 +108,7 @@ fn main() -> () { StorageLive(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6 _14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:+11:31: +14:6 // closure - // + def_id: DefId(0:14 ~ retag[4622]::main::{closure#0}) + // + def_id: DefId(0:14 ~ retag[7654]::main::{closure#0}) // + substs: [ // i8, // for<'a> extern "rust-call" fn((&'a i32,)) -> &'a i32, diff --git a/tests/ui/consts/miri_unleashed/tls.stderr b/tests/ui/consts/miri_unleashed/tls.stderr index 7aaeadd0403c..ec24527d6c0e 100644 --- a/tests/ui/consts/miri_unleashed/tls.stderr +++ b/tests/ui/consts/miri_unleashed/tls.stderr @@ -2,13 +2,13 @@ error[E0080]: could not evaluate static initializer --> $DIR/tls.rs:11:25 | LL | unsafe { let _val = A; } - | ^ cannot access thread local static (DefId(0:4 ~ tls[78b0]::A)) + | ^ cannot access thread local static (DefId(0:4 ~ tls[ca29]::A)) error[E0080]: could not evaluate static initializer --> $DIR/tls.rs:18:26 | LL | unsafe { let _val = &A; } - | ^ cannot access thread local static (DefId(0:4 ~ tls[78b0]::A)) + | ^ cannot access thread local static (DefId(0:4 ~ tls[ca29]::A)) warning: skipping const checks | diff --git a/tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr b/tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr index 7d0a201699b5..429b202f6038 100644 --- a/tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr +++ b/tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr @@ -10,7 +10,7 @@ note: generator is not `Send` as this value is used across a yield --> $DIR/generator-print-verbose-1.rs:38:9 | LL | let _non_send_gen = make_non_send_generator(); - | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send` + | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[7d1d]::make_non_send_generator::{opaque#0}), [])` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later LL | }; @@ -37,17 +37,17 @@ note: required because it's used within this generator | LL | || { | ^^ -note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [Arc>])` +note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[7d1d]::make_gen2::{opaque#0}), [Arc>])` --> $DIR/generator-print-verbose-1.rs:44:30 | LL | pub fn make_gen2(t: T) -> impl Generator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])` +note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])` --> $DIR/generator-print-verbose-1.rs:50:34 | LL | fn make_non_send_generator2() -> impl Generator>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()` + = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])`, `()` note: required because it's used within this generator --> $DIR/generator-print-verbose-1.rs:55:20 | diff --git a/tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr b/tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr index c045b1441c14..01a30fd2f4e9 100644 --- a/tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr +++ b/tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr @@ -10,7 +10,7 @@ note: generator is not `Send` as this value is used across a yield --> $DIR/generator-print-verbose-1.rs:38:9 | LL | let _non_send_gen = make_non_send_generator(); - | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send` + | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[7d1d]::make_non_send_generator::{opaque#0}), [])` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later note: required by a bound in `require_send` @@ -33,17 +33,17 @@ note: required because it's used within this generator | LL | || { | ^^ -note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [Arc>])` +note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[7d1d]::make_gen2::{opaque#0}), [Arc>])` --> $DIR/generator-print-verbose-1.rs:44:30 | LL | pub fn make_gen2(t: T) -> impl Generator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])` +note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])` --> $DIR/generator-print-verbose-1.rs:50:34 | LL | fn make_non_send_generator2() -> impl Generator>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])` + = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])` note: required because it's used within this generator --> $DIR/generator-print-verbose-1.rs:55:20 | diff --git a/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr b/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr index 7d0a201699b5..429b202f6038 100644 --- a/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr +++ b/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr @@ -10,7 +10,7 @@ note: generator is not `Send` as this value is used across a yield --> $DIR/generator-print-verbose-1.rs:38:9 | LL | let _non_send_gen = make_non_send_generator(); - | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send` + | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[7d1d]::make_non_send_generator::{opaque#0}), [])` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later LL | }; @@ -37,17 +37,17 @@ note: required because it's used within this generator | LL | || { | ^^ -note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [Arc>])` +note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[7d1d]::make_gen2::{opaque#0}), [Arc>])` --> $DIR/generator-print-verbose-1.rs:44:30 | LL | pub fn make_gen2(t: T) -> impl Generator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])` +note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])` --> $DIR/generator-print-verbose-1.rs:50:34 | LL | fn make_non_send_generator2() -> impl Generator>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()` + = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])`, `()` note: required because it's used within this generator --> $DIR/generator-print-verbose-1.rs:55:20 | diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index 7fcb68252cfd..59655cfcdae6 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,4 +1,4 @@ -error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds +error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { @@ -8,9 +8,9 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { LL | x | ^ | -help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound +help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound | -LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) { +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) { | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to previous error diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index fe490a6000d7..c1cbefac828d 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17he9f658e438f1cac0E) +error: symbol-name(_ZN5basic4main17h6fc0c8d27b1a289fE) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::he9f658e438f1cac0) +error: demangling(basic::main::h6fc0c8d27b1a289f) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/basic.v0.stderr b/tests/ui/symbol-names/basic.v0.stderr index 1f02781364eb..17c6d0ce704c 100644 --- a/tests/ui/symbol-names/basic.v0.stderr +++ b/tests/ui/symbol-names/basic.v0.stderr @@ -4,7 +4,7 @@ error: symbol-name(_RNvCsCRATE_HASH_5basic4main) LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic[b751b4a00e2291d9]::main) +error: demangling(basic[a90d658f4748b9d1]::main) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/foreign-types.stderr b/tests/ui/symbol-names/foreign-types.stderr index d6ee388ddf89..9c8633742b24 100644 --- a/tests/ui/symbol-names/foreign-types.stderr +++ b/tests/ui/symbol-names/foreign-types.stderr @@ -4,7 +4,7 @@ error: symbol-name(_RMCsCRATE_HASH_13foreign_typesINtB_5CheckNvB_11For LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(>) +error: demangling(>) --> $DIR/foreign-types.rs:13:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/impl1.v0.stderr b/tests/ui/symbol-names/impl1.v0.stderr index 33caad71f52f..a7cc5fc8ed21 100644 --- a/tests/ui/symbol-names/impl1.v0.stderr +++ b/tests/ui/symbol-names/impl1.v0.stderr @@ -4,7 +4,7 @@ error: symbol-name(_RNvMNtCsCRATE_HASH_5impl13fooNtB_3Foo3bar) LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(::bar) +error: demangling(::bar) --> $DIR/impl1.rs:14:9 | LL | #[rustc_symbol_name] @@ -28,7 +28,7 @@ error: symbol-name(_RNvMNtCsCRATE_HASH_5impl13barNtNtB_3foo3Foo3baz) LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(::baz) +error: demangling(::baz) --> $DIR/impl1.rs:32:9 | LL | #[rustc_symbol_name] @@ -52,7 +52,7 @@ error: symbol-name(_RNvXNCNvCsCRATE_HASH_5impl14mains_0ARDNtB_3Foop5AssocFG LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<[&dyn impl1[2c09c4f1c7c8e90c]::Foo extern "C" fn(&'a u8, ...)> + impl1[2c09c4f1c7c8e90c]::AutoTrait; 3usize] as impl1[2c09c4f1c7c8e90c]::main::{closure#1}::Bar>::method) +error: demangling(<[&dyn impl1[d5591eb39db23cbb]::Foo extern "C" fn(&'a u8, ...)> + impl1[d5591eb39db23cbb]::AutoTrait; 3usize] as impl1[d5591eb39db23cbb]::main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:62:13 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index 29b42f48d803..7dd68e6e3a8e 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h13209029be24b923E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hab58a402db4ebf3aE) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h13209029be24b923) +error: demangling(issue_60925::foo::Foo::foo::hab58a402db4ebf3a) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.v0.stderr b/tests/ui/symbol-names/issue-60925.v0.stderr index 408c957c6a14..77449becc84d 100644 --- a/tests/ui/symbol-names/issue-60925.v0.stderr +++ b/tests/ui/symbol-names/issue-60925.v0.stderr @@ -4,7 +4,7 @@ error: symbol-name(_RNvMNtCsCRATE_HASH_11issue_609253fooINtB_3FooNtNtB LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(>::foo) +error: demangling(>::foo) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-75326.v0.stderr b/tests/ui/symbol-names/issue-75326.v0.stderr index 3d7803a0c3b9..fb742f5e4490 100644 --- a/tests/ui/symbol-names/issue-75326.v0.stderr +++ b/tests/ui/symbol-names/issue-75326.v0.stderr @@ -4,7 +4,7 @@ error: symbol-name(_RNvXINICsCRATE_HASH_11issue_75326s_0pppEINtB_3FooppENtB LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling( as issue_75326[e8e253d78520f2a2]::Iterator2>::next) +error: demangling( as issue_75326[189ebc60e18860d7]::Iterator2>::next) --> $DIR/issue-75326.rs:41:5 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/trait-objects.v0.stderr b/tests/ui/symbol-names/trait-objects.v0.stderr index 47192ce5b838..84f2bce66be1 100644 --- a/tests/ui/symbol-names/trait-objects.v0.stderr +++ b/tests/ui/symbol-names/trait-objects.v0.stderr @@ -4,7 +4,7 @@ error: symbol-name(_RNvXCsCRATE_HASH_13trait_objectsRDG_INtNtNtCsCRATE_HASH_4cor LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[7260a56bea9f357b]::Bar>::method) +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[3c073c57f94bedc2]::Bar>::method) --> $DIR/trait-objects.rs:15:5 | LL | #[rustc_symbol_name] @@ -22,7 +22,7 @@ error: symbol-name(_RNvXs_CsCRATE_HASH_13trait_objectsRDG_INtNtNtCsCRATE_HASH_4c LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[7260a56bea9f357b]::Foo>::method) +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3c073c57f94bedc2]::Foo>::method) --> $DIR/trait-objects.rs:27:5 | LL | #[rustc_symbol_name] @@ -40,7 +40,7 @@ error: symbol-name(_RNvXs0_CsCRATE_HASH_13trait_objectsRDG_INtNtNtCsCRATE_HASH_4 LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[7260a56bea9f357b]::Baz>::method) +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3c073c57f94bedc2]::Baz>::method) --> $DIR/trait-objects.rs:39:5 | LL | #[rustc_symbol_name] diff --git a/tests/ui/thir-print/thir-flat.stdout b/tests/ui/thir-print/thir-flat.stdout index 910c0da27378..9d467f73d097 100644 --- a/tests/ui/thir-print/thir-flat.stdout +++ b/tests/ui/thir-print/thir-flat.stdout @@ -1,4 +1,4 @@ -DefId(0:3 ~ thir_flat[45a6]::main): +DefId(0:3 ~ thir_flat[7b97]::main): Thir { body_type: Fn( ([]; c_variadic: false)->(), @@ -30,7 +30,7 @@ Thir { kind: Scope { region_scope: Node(2), lint_level: Explicit( - HirId(DefId(0:3 ~ thir_flat[45a6]::main).2), + HirId(DefId(0:3 ~ thir_flat[7b97]::main).2), ), value: e0, }, diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout index d6174ec262a4..eea04c0951d3 100644 --- a/tests/ui/thir-print/thir-tree-match.stdout +++ b/tests/ui/thir-print/thir-tree-match.stdout @@ -1,10 +1,10 @@ -DefId(0:16 ~ thir_tree_match[3c9a]::has_match): +DefId(0:16 ~ thir_tree_match[fcf8]::has_match): params: [ Param { ty: Foo ty_span: Some($DIR/thir-tree-match.rs:15:19: 15:22 (#0)) self_kind: None - hir_id: Some(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).1)) + hir_id: Some(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).1)) param: Some( Pat: { ty: Foo @@ -14,7 +14,7 @@ params: [ mutability: Not name: "foo" mode: ByValue - var: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).2)) + var: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).2)) ty: Foo is_primary: true subpattern: None @@ -41,7 +41,7 @@ body: kind: Scope { region_scope: Node(26) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).26)) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26)) value: Expr { ty: bool @@ -63,7 +63,7 @@ body: kind: Scope { region_scope: Node(3) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).3)) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).3)) value: Expr { ty: bool @@ -79,7 +79,7 @@ body: kind: Scope { region_scope: Node(4) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).4)) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).4)) value: Expr { ty: Foo @@ -87,7 +87,7 @@ body: span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) kind: VarRef { - id: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).2)) + id: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).2)) } } } @@ -102,10 +102,10 @@ body: Variant { adt_def: AdtDef { - did: DefId(0:10 ~ thir_tree_match[3c9a]::Foo) - variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[3c9a]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[3c9a]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[3c9a]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[3c9a])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[3c9a]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[3c9a]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) + variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 11573694388057581 } + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 } substs: [] variant_index: 0 subpatterns: [ @@ -116,10 +116,10 @@ body: Variant { adt_def: AdtDef { - did: DefId(0:3 ~ thir_tree_match[3c9a]::Bar) - variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[3c9a]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[3c9a]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[3c9a]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[3c9a]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[3c9a]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[3c9a]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], flags: NO_VARIANT_FLAGS }] + did: DefId(0:3 ~ thir_tree_match[fcf8]::Bar) + variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[fcf8]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[fcf8]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[fcf8]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[fcf8]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[fcf8]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[fcf8]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], flags: NO_VARIANT_FLAGS }] flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3125160937860410723 } + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 10333377570083945360 } substs: [] variant_index: 0 subpatterns: [] @@ -148,7 +148,7 @@ body: kind: Scope { region_scope: Node(13) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).13)) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13)) value: Expr { ty: bool @@ -162,7 +162,7 @@ body: } } } - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).12)) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).12)) scope: Node(12) span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0) } @@ -175,10 +175,10 @@ body: Variant { adt_def: AdtDef { - did: DefId(0:10 ~ thir_tree_match[3c9a]::Foo) - variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[3c9a]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[3c9a]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[3c9a]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[3c9a])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[3c9a]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[3c9a]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) + variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 11573694388057581 } + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 } substs: [] variant_index: 0 subpatterns: [ @@ -211,7 +211,7 @@ body: kind: Scope { region_scope: Node(19) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).19)) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19)) value: Expr { ty: bool @@ -225,7 +225,7 @@ body: } } } - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).18)) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).18)) scope: Node(18) span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0) } @@ -238,10 +238,10 @@ body: Variant { adt_def: AdtDef { - did: DefId(0:10 ~ thir_tree_match[3c9a]::Foo) - variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[3c9a]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[3c9a]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[3c9a]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[3c9a])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[3c9a]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[3c9a]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) + variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 11573694388057581 } + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 } substs: [] variant_index: 1 subpatterns: [] @@ -266,7 +266,7 @@ body: kind: Scope { region_scope: Node(24) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).24)) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24)) value: Expr { ty: bool @@ -280,7 +280,7 @@ body: } } } - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).23)) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).23)) scope: Node(23) span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0) } @@ -297,7 +297,7 @@ body: } -DefId(0:17 ~ thir_tree_match[3c9a]::main): +DefId(0:17 ~ thir_tree_match[fcf8]::main): params: [ ] body: @@ -317,7 +317,7 @@ body: kind: Scope { region_scope: Node(2) - lint_level: Explicit(HirId(DefId(0:17 ~ thir_tree_match[3c9a]::main).2)) + lint_level: Explicit(HirId(DefId(0:17 ~ thir_tree_match[fcf8]::main).2)) value: Expr { ty: () diff --git a/tests/ui/thir-print/thir-tree.stdout b/tests/ui/thir-print/thir-tree.stdout index 0a35d9fb78ca..1b478dbef993 100644 --- a/tests/ui/thir-print/thir-tree.stdout +++ b/tests/ui/thir-print/thir-tree.stdout @@ -1,4 +1,4 @@ -DefId(0:3 ~ thir_tree[8f1d]::main): +DefId(0:3 ~ thir_tree[7aaa]::main): params: [ ] body: @@ -18,7 +18,7 @@ body: kind: Scope { region_scope: Node(2) - lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree[8f1d]::main).2)) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree[7aaa]::main).2)) value: Expr { ty: () diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr index f4c7acd5c589..ce409f627be2 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `for fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ()): Foo` is not satisfied +error[E0277]: the trait bound `for fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ()): Foo` is not satisfied --> $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ())` + | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` | note: required by a bound in `called` --> $DIR/higher-ranked-fn-type.rs:12:25 From 36ca32c1ed817f4621b89409599b0f4c37914685 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sat, 11 Feb 2023 09:47:44 -0800 Subject: [PATCH 133/267] Fix a codegen test with some hard-coded hashes --- tests/codegen/virtual-function-elimination.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/codegen/virtual-function-elimination.rs b/tests/codegen/virtual-function-elimination.rs index 30e5cd0584d2..f22176a024fc 100644 --- a/tests/codegen/virtual-function-elimination.rs +++ b/tests/codegen/virtual-function-elimination.rs @@ -82,7 +82,7 @@ fn taking_u(u: &dyn U) -> i32 { } pub fn taking_v(v: &dyn V) -> i32 { - // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtCsfRpWlKdQPZn_28virtual_function_elimination1V") + // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtCs64ITQYi9761_28virtual_function_elimination1V") v.public_function() } @@ -97,5 +97,5 @@ pub fn main() { // CHECK: ![[TYPE0]] = !{i64 0, !"[[MANGLED_TYPE0]]"} // CHECK: ![[VCALL_VIS0]] = !{i64 2} // CHECK: ![[TYPE1]] = !{i64 0, !"[[MANGLED_TYPE1]]"} -// CHECK: ![[TYPE2]] = !{i64 0, !"NtCsfRpWlKdQPZn_28virtual_function_elimination1V"} +// CHECK: ![[TYPE2]] = !{i64 0, !"NtCs64ITQYi9761_28virtual_function_elimination1V"} // CHECK: ![[VCALL_VIS2]] = !{i64 1} From 476737e03c820d9cab7ddbd26de843e833c7a3c8 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sat, 11 Feb 2023 10:41:21 -0800 Subject: [PATCH 134/267] Fix an assembly test with a hard-coded hash --- tests/assembly/asm/global_asm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/assembly/asm/global_asm.rs b/tests/assembly/asm/global_asm.rs index 0b361a7ed963..36f017cf9d60 100644 --- a/tests/assembly/asm/global_asm.rs +++ b/tests/assembly/asm/global_asm.rs @@ -25,9 +25,9 @@ global_asm!("movl ${}, %ecx", const 5, options(att_syntax)); global_asm!("call {}", sym my_func); // CHECK: lea rax, [rip + MY_STATIC] global_asm!("lea rax, [rip + {}]", sym MY_STATIC); -// CHECK: call _RNvCsiubXh4Yz005_10global_asm6foobar +// CHECK: call _RNvCsddMtV7nAi4C_10global_asm6foobar global_asm!("call {}", sym foobar); -// CHECK: _RNvCsiubXh4Yz005_10global_asm6foobar: +// CHECK: _RNvCsddMtV7nAi4C_10global_asm6foobar: fn foobar() { loop {} } From 46fad955c0a10e7d3308fc797628a3e580ac879a Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sun, 5 Mar 2023 14:29:57 -0800 Subject: [PATCH 135/267] Fix a debuginfo test with a hard-coded hash --- tests/debuginfo/function-names.rs | 4 ++-- tests/ui/nll/ty-outlives/impl-trait-captures.stderr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/debuginfo/function-names.rs b/tests/debuginfo/function-names.rs index 2227de3b3776..ca42d1e351f4 100644 --- a/tests/debuginfo/function-names.rs +++ b/tests/debuginfo/function-names.rs @@ -37,7 +37,7 @@ // Const generic parameter // gdb-command:info functions -q function_names::const_generic_fn.* // gdb-check:[...]static fn function_names::const_generic_fn_bool(); -// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#6348c650c7b26618}>(); +// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#ad91263f6d2dd96e}>(); // gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>(); // gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>(); @@ -78,7 +78,7 @@ // cdb-check:[...] a!function_names::const_generic_fn_bool (void) // cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void) // cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void) -// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) +// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index 59655cfcdae6..da4b9595c0ee 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -4,7 +4,7 @@ error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::fo LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { | -- ------------ opaque type defined here | | - | hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here + | hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here LL | x | ^ | From 931fd8539e5234c3db686664f5f2fad69c540808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 3 Apr 2023 07:29:19 +0000 Subject: [PATCH 136/267] Fix codegen tests with hard-coded hashes --- tests/codegen/consts.rs | 2 +- tests/codegen/remap_path_prefix/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/codegen/consts.rs b/tests/codegen/consts.rs index 8a135039c066..fc2badc417c2 100644 --- a/tests/codegen/consts.rs +++ b/tests/codegen/consts.rs @@ -9,7 +9,7 @@ // CHECK: @STATIC = {{.*}}, align 4 // This checks the constants from inline_enum_const -// CHECK: @alloc_701ed935fbda2002838d0a2cbbc171e5 = {{.*}}, align 2 +// CHECK: @alloc_af1f8e8e6f4b341431a1d405e652df2d = {{.*}}, align 2 // This checks the constants from {low,high}_align_const, they share the same // constant, but the alignment differs, so the higher one should be used diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs index 85523d053b59..f1e1dd69b969 100644 --- a/tests/codegen/remap_path_prefix/main.rs +++ b/tests/codegen/remap_path_prefix/main.rs @@ -12,7 +12,7 @@ mod aux_mod; include!("aux_mod.rs"); // Here we check that the expansion of the file!() macro is mapped. -// CHECK: @alloc_af9d0c7bc6ca3c31bb051d2862714536 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }> +// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }> pub static FILE_PATH: &'static str = file!(); fn main() { From dc04b085f4cfb565e53af794f862b4d2469e7ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 3 Apr 2023 09:15:05 +0000 Subject: [PATCH 137/267] Bless rustdoc test with swapped ids The ids for the multiple `Item` associated type elements are swapped between the first and second impl. --- tests/rustdoc/issue-25001.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/rustdoc/issue-25001.rs b/tests/rustdoc/issue-25001.rs index c97b35adaf22..268fae59496a 100644 --- a/tests/rustdoc/issue-25001.rs +++ b/tests/rustdoc/issue-25001.rs @@ -21,14 +21,14 @@ impl Foo { } impl Bar for Foo { - // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' 'type Item = T' + // @has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' 'type Item = T' type Item=T; // @has - '//*[@id="method.quux"]//h4[@class="code-header"]' 'fn quux(self)' fn quux(self) {} } impl<'a, T> Bar for &'a Foo { - // @has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' "type Item = &'a T" + // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item = &'a T" type Item=&'a T; // @has - '//*[@id="method.quux-1"]//h4[@class="code-header"]' 'fn quux(self)' From 4e235a7fa94867f1184a04c3befb9ddd1f0a9281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 3 Apr 2023 09:18:31 +0000 Subject: [PATCH 138/267] Bless rustdoc-ui test with new errors order The order in which the multiple errors for the ambiguous intra doc links are printed is different. --- .../issue-108653-associated-items.stderr | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.stderr index 084aefc97c83..ed89fa8391d6 100644 --- a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.stderr +++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items.stderr @@ -33,21 +33,6 @@ help: to link to the associated type, prefix with `type@` LL | /// [`type@Self::IDENT2`] | +++++ -error: `Self::IDENT2` is both an associated constant and an associated type - --> $DIR/issue-108653-associated-items.rs:30:7 - | -LL | /// [`Self::IDENT2`] - | ^^^^^^^^^^^^ ambiguous link - | -help: to link to the associated constant, prefix with `const@` - | -LL | /// [`const@Self::IDENT2`] - | ++++++ -help: to link to the associated type, prefix with `type@` - | -LL | /// [`type@Self::IDENT2`] - | +++++ - error: `Self::IDENT` is both an associated function and a variant --> $DIR/issue-108653-associated-items.rs:16:7 | @@ -63,5 +48,20 @@ help: to link to the variant, prefix with `type@` LL | /// [`type@Self::IDENT`] | +++++ +error: `Self::IDENT2` is both an associated constant and an associated type + --> $DIR/issue-108653-associated-items.rs:30:7 + | +LL | /// [`Self::IDENT2`] + | ^^^^^^^^^^^^ ambiguous link + | +help: to link to the associated constant, prefix with `const@` + | +LL | /// [`const@Self::IDENT2`] + | ++++++ +help: to link to the associated type, prefix with `type@` + | +LL | /// [`type@Self::IDENT2`] + | +++++ + error: aborting due to 4 previous errors From 46a3d28e8840f8f7e400e661fc6c544697ad50a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 4 Apr 2023 17:41:55 +0000 Subject: [PATCH 139/267] Fix function order in an msvc debuginfo test The function names with const generic parameters are printed in a different order. --- tests/debuginfo/function-names.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/debuginfo/function-names.rs b/tests/debuginfo/function-names.rs index ca42d1e351f4..d9aa03fee624 100644 --- a/tests/debuginfo/function-names.rs +++ b/tests/debuginfo/function-names.rs @@ -76,9 +76,9 @@ // Const generic parameter // cdb-command:x a!function_names::const_generic_fn* // cdb-check:[...] a!function_names::const_generic_fn_bool (void) +// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) // cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void) // cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void) -// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] From 48c16411c31d27772cb9c05a9914c2b9a26b5df5 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 5 Apr 2023 16:04:19 +0000 Subject: [PATCH 140/267] nit picks from review --- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index bb1063538b41..b02eae19fce1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -21,7 +21,7 @@ use rustc_hir_analysis::astconv::AstConv; use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt; use rustc_hir_analysis::check::potentially_plural_count; use rustc_hir_analysis::structured_errors::StructuredDiagnostic; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::vec::IndexVec; use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::TypeTrace; @@ -963,14 +963,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map_or(true, |next_error| !matches!(next_error, Error::Extra(_))) { let next = provided_arg_tys - .get(arg_idx.plus(1)) + .get(arg_idx + 1) .map(|&(_, sp)| sp) .unwrap_or_else(|| { // Subtract one to move before `)` - call_expr - .span - .shrink_to_hi() - .with_lo(call_expr.span.hi() - BytePos(1)) + call_expr.span.with_lo(call_expr.span.hi() - BytePos(1)) }); // Include next comma From 504c4c40e9716fb47346d6e8a27389467763552a Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 5 Apr 2023 18:54:15 +0200 Subject: [PATCH 141/267] Add context to phantom comment --- compiler/rustc_data_structures/src/owned_slice.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs index dce209adfaa8..146f06a1c69e 100644 --- a/compiler/rustc_data_structures/src/owned_slice.rs +++ b/compiler/rustc_data_structures/src/owned_slice.rs @@ -26,10 +26,10 @@ pub struct OwnedSlice { // | touch the owner — otherwise the owner | // | could invalidate out `bytes` pointer | // | | - // | so be quite | + // | so be quiet | // +----+ +-------------------------------+ // \/ - // ⊂(´・◡・⊂ )∘˚˳° + // ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770) #[expect(dead_code)] owner: Box, } From b904ce94a23744032f930841b6fecb6ac2620cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 5 Apr 2023 06:33:52 +0200 Subject: [PATCH 142/267] account for self type when looking for source of unsolved ty var --- .../infer/error_reporting/need_type_info.rs | 5 +++- .../inference/need_type_info/concrete-impl.rs | 3 +++ .../need_type_info/concrete-impl.stderr | 9 ++++--- .../inference/need_type_info/issue-109905.rs | 25 +++++++++++++++++++ .../need_type_info/issue-109905.stderr | 15 +++++++++++ 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 tests/ui/inference/need_type_info/issue-109905.rs create mode 100644 tests/ui/inference/need_type_info/issue-109905.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index bde16fad8216..d7b900ca02d3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -1191,11 +1191,14 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { have_turbofish, } = args; let generics = tcx.generics_of(generics_def_id); - if let Some(argument_index) = generics + if let Some(mut argument_index) = generics .own_substs(substs) .iter() .position(|&arg| self.generic_arg_contains_target(arg)) { + if generics.parent.is_none() && generics.has_self { + argument_index += 1; + } let substs = self.infcx.resolve_vars_if_possible(substs); let generic_args = &generics.own_substs_no_defaults(tcx, substs) [generics.own_counts().lifetimes..]; diff --git a/tests/ui/inference/need_type_info/concrete-impl.rs b/tests/ui/inference/need_type_info/concrete-impl.rs index 72e0e74f3234..fc79e6201bdb 100644 --- a/tests/ui/inference/need_type_info/concrete-impl.rs +++ b/tests/ui/inference/need_type_info/concrete-impl.rs @@ -7,10 +7,13 @@ struct Two; struct Struct; impl Ambiguous for Struct {} +//~^ NOTE multiple `impl`s satisfying `Struct: Ambiguous<_>` found impl Ambiguous for Struct {} fn main() { >::method(); //~^ ERROR type annotations needed + //~| NOTE cannot infer type of the type parameter `A` //~| ERROR type annotations needed + //~| NOTE infer type of the type parameter `A` } diff --git a/tests/ui/inference/need_type_info/concrete-impl.stderr b/tests/ui/inference/need_type_info/concrete-impl.stderr index aa32969950d6..74c3f6cd5cfa 100644 --- a/tests/ui/inference/need_type_info/concrete-impl.stderr +++ b/tests/ui/inference/need_type_info/concrete-impl.stderr @@ -1,20 +1,21 @@ error[E0282]: type annotations needed - --> $DIR/concrete-impl.rs:13:5 + --> $DIR/concrete-impl.rs:14:5 | LL | >::method(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous` error[E0283]: type annotations needed - --> $DIR/concrete-impl.rs:13:5 + --> $DIR/concrete-impl.rs:14:5 | LL | >::method(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous` | note: multiple `impl`s satisfying `Struct: Ambiguous<_>` found --> $DIR/concrete-impl.rs:9:1 | LL | impl Ambiguous for Struct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | impl Ambiguous for Struct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/inference/need_type_info/issue-109905.rs b/tests/ui/inference/need_type_info/issue-109905.rs new file mode 100644 index 000000000000..99d10a5eae04 --- /dev/null +++ b/tests/ui/inference/need_type_info/issue-109905.rs @@ -0,0 +1,25 @@ +// Test that we show the correct type parameter that couldn't be inferred and that we don't +// end up stating nonsense like "type parameter `'a`" which we used to do. + +trait Trait<'a, T> { + fn m(self); +} + +impl<'a, A> Trait<'a, A> for () { + fn m(self) {} +} + +fn qualified() { + <() as Trait<'static, _>>::m(()); + //~^ ERROR type annotations needed + //~| NOTE cannot infer type of the type parameter `T` + +} + +fn unqualified() { + Trait::<'static, _>::m(()); + //~^ ERROR type annotations needed + //~| NOTE cannot infer type of the type parameter `T` +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/issue-109905.stderr b/tests/ui/inference/need_type_info/issue-109905.stderr new file mode 100644 index 000000000000..fcdd50f14226 --- /dev/null +++ b/tests/ui/inference/need_type_info/issue-109905.stderr @@ -0,0 +1,15 @@ +error[E0282]: type annotations needed + --> $DIR/issue-109905.rs:13:5 + | +LL | <() as Trait<'static, _>>::m(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait` + +error[E0282]: type annotations needed + --> $DIR/issue-109905.rs:20:5 + | +LL | Trait::<'static, _>::m(()); + | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. From 279f35ce50a7d8b0232a9fd994598ad786470d3f Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Wed, 5 Apr 2023 20:58:21 +0200 Subject: [PATCH 143/267] Derive String's PartialEq implementation --- library/alloc/src/string.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index c7e7ed3e95e0..c1cd3c74ab67 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -359,7 +359,7 @@ use crate::vec::Vec; /// [Deref]: core::ops::Deref "ops::Deref" /// [`Deref`]: core::ops::Deref "ops::Deref" /// [`as_str()`]: String::as_str -#[derive(PartialOrd, Eq, Ord)] +#[derive(PartialEq, PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), lang = "String")] pub struct String { @@ -2207,14 +2207,6 @@ impl<'a, 'b> Pattern<'a> for &'b String { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for String { - #[inline] - fn eq(&self, other: &String) -> bool { - PartialEq::eq(&self[..], &other[..]) - } -} - macro_rules! impl_eq { ($lhs:ty, $rhs: ty) => { #[stable(feature = "rust1", since = "1.0.0")] From 35e622d2185ff094f8fbe528f24e8900b9369efb Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 30 Mar 2023 18:01:42 +0000 Subject: [PATCH 144/267] Do not keep extra references to scopes and decls. --- .../src/const_prop_lint.rs | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 176027b3b93e..63cd51af0ce0 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -9,7 +9,6 @@ use rustc_const_eval::interpret::{ }; use rustc_hir::def::DefKind; use rustc_hir::HirId; -use rustc_index::vec::IndexSlice; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; @@ -130,8 +129,6 @@ struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, - source_scopes: &'mir IndexSlice>, - local_decls: &'mir IndexSlice>, // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store // the last known `SourceInfo` here and just keep revisiting it. source_info: Option, @@ -209,14 +206,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ) .expect("failed to push initial stack frame"); - ConstPropagator { - ecx, - tcx, - param_env, - source_scopes: &dummy_body.source_scopes, - local_decls: &dummy_body.local_decls, - source_info: None, - } + ConstPropagator { ecx, tcx, param_env, source_info: None } + } + + fn body(&self) -> &'mir Body<'tcx> { + self.ecx.frame().body + } + + fn local_decls(&self) -> &'mir LocalDecls<'tcx> { + &self.body().local_decls } fn get_const(&self, place: Place<'tcx>) -> Option> { @@ -251,7 +249,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } fn lint_root(&self, source_info: SourceInfo) -> Option { - source_info.scope.lint_root(self.source_scopes) + source_info.scope.lint_root(&self.body().source_scopes) } fn use_ecx(&mut self, source_info: SourceInfo, f: F) -> Option @@ -368,7 +366,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let r = r.clone()?; // We need the type of the LHS. We cannot use `place_layout` as that is the type // of the result, which for checked binops is not the same! - let left_ty = left.ty(self.local_decls, self.tcx); + let left_ty = left.ty(self.local_decls(), self.tcx); let left_size = self.ecx.layout_of(left_ty).ok()?.size; let right_size = r.layout.size; let r_bits = r.to_scalar().to_bits(right_size).ok(); @@ -481,10 +479,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if rvalue.needs_subst() { return None; } - if !rvalue - .ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx) - .is_sized(*self.ecx.tcx, self.param_env) - { + if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.param_env) { // the interpreter doesn't support unsized locals (only unsized arguments), // but rustc does (in a kinda broken way), so we have to skip them here return None; @@ -498,7 +493,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { assert!( self.get_const(local.into()).is_none() || self - .layout_of(self.local_decls[local].ty) + .layout_of(self.local_decls()[local].ty) .map_or(true, |layout| layout.is_zst()), "failed to remove values for `{local:?}`, value={:?}", self.get_const(local.into()), From b833fcae90b42a9b55224288d5ec9cfd86835d0d Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 30 Mar 2023 18:08:09 +0000 Subject: [PATCH 145/267] Manipulate Location instead of SourceInfo. --- .../src/const_prop_lint.rs | 86 ++++++++----------- 1 file changed, 36 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 63cd51af0ce0..47bcba0f2500 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -1,7 +1,7 @@ //! Propagates constants for early reporting of statically known //! assertion failures -use either::{Left, Right}; +use either::Left; use rustc_const_eval::interpret::Immediate; use rustc_const_eval::interpret::{ @@ -129,9 +129,6 @@ struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, - // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store - // the last known `SourceInfo` here and just keep revisiting it. - source_info: Option, } impl<'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'_, 'tcx> { @@ -206,7 +203,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ) .expect("failed to push initial stack frame"); - ConstPropagator { ecx, tcx, param_env, source_info: None } + ConstPropagator { ecx, tcx, param_env } } fn body(&self) -> &'mir Body<'tcx> { @@ -252,12 +249,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source_info.scope.lint_root(&self.body().source_scopes) } - fn use_ecx(&mut self, source_info: SourceInfo, f: F) -> Option + fn use_ecx(&mut self, location: Location, f: F) -> Option where F: FnOnce(&mut Self) -> InterpResult<'tcx, T>, { // Overwrite the PC -- whatever the interpreter does to it does not make any sense anyway. - self.ecx.frame_mut().loc = Right(source_info.span); + self.ecx.frame_mut().loc = Left(location); match f(self) { Ok(val) => Some(val), Err(error) => { @@ -276,7 +273,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } /// Returns the value, if any, of evaluating `c`. - fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option> { + fn eval_constant(&mut self, c: &Constant<'tcx>, location: Location) -> Option> { // FIXME we need to revisit this for #67176 if c.needs_subst() { return None; @@ -290,45 +287,41 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // manually normalized. let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.literal).ok()?; - self.use_ecx(source_info, |this| this.ecx.eval_mir_constant(&val, Some(c.span), None)) + self.use_ecx(location, |this| this.ecx.eval_mir_constant(&val, Some(c.span), None)) } /// Returns the value, if any, of evaluating `place`. - fn eval_place(&mut self, place: Place<'tcx>, source_info: SourceInfo) -> Option> { + fn eval_place(&mut self, place: Place<'tcx>, location: Location) -> Option> { trace!("eval_place(place={:?})", place); - self.use_ecx(source_info, |this| this.ecx.eval_place_to_op(place, None)) + self.use_ecx(location, |this| this.ecx.eval_place_to_op(place, None)) } /// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant` /// or `eval_place`, depending on the variant of `Operand` used. - fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option> { + fn eval_operand(&mut self, op: &Operand<'tcx>, location: Location) -> Option> { match *op { - Operand::Constant(ref c) => self.eval_constant(c, source_info), - Operand::Move(place) | Operand::Copy(place) => self.eval_place(place, source_info), + Operand::Constant(ref c) => self.eval_constant(c, location), + Operand::Move(place) | Operand::Copy(place) => self.eval_place(place, location), } } fn report_assert_as_lint( &self, lint: &'static lint::Lint, - source_info: SourceInfo, + location: Location, message: &'static str, panic: AssertKind, ) { - if let Some(lint_root) = self.lint_root(source_info) { + let source_info = self.body().source_info(location); + if let Some(lint_root) = self.lint_root(*source_info) { self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, message, |lint| { lint.span_label(source_info.span, format!("{:?}", panic)) }); } } - fn check_unary_op( - &mut self, - op: UnOp, - arg: &Operand<'tcx>, - source_info: SourceInfo, - ) -> Option<()> { - if let (val, true) = self.use_ecx(source_info, |this| { + fn check_unary_op(&mut self, op: UnOp, arg: &Operand<'tcx>, location: Location) -> Option<()> { + if let (val, true) = self.use_ecx(location, |this| { let val = this.ecx.read_immediate(&this.ecx.eval_operand(arg, None)?)?; let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, &val)?; Ok((val, overflow)) @@ -338,7 +331,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); self.report_assert_as_lint( lint::builtin::ARITHMETIC_OVERFLOW, - source_info, + location, "this arithmetic operation will overflow", AssertKind::OverflowNeg(val.to_const_int()), ); @@ -353,14 +346,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { op: BinOp, left: &Operand<'tcx>, right: &Operand<'tcx>, - source_info: SourceInfo, + location: Location, ) -> Option<()> { - let r = self.use_ecx(source_info, |this| { + let r = self.use_ecx(location, |this| { this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?) }); - let l = self.use_ecx(source_info, |this| { - this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?) - }); + let l = self + .use_ecx(location, |this| this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?)); // Check for exceeding shifts *even if* we cannot evaluate the LHS. if matches!(op, BinOp::Shr | BinOp::Shl) { let r = r.clone()?; @@ -371,10 +363,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let right_size = r.layout.size; let r_bits = r.to_scalar().to_bits(right_size).ok(); if r_bits.map_or(false, |b| b >= left_size.bits() as u128) { - debug!("check_binary_op: reporting assert for {:?}", source_info); + debug!("check_binary_op: reporting assert for {:?}", location); self.report_assert_as_lint( lint::builtin::ARITHMETIC_OVERFLOW, - source_info, + location, "this arithmetic operation will overflow", AssertKind::Overflow( op, @@ -396,13 +388,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if let (Some(l), Some(r)) = (l, r) { // The remaining operators are handled through `overflowing_binary_op`. - if self.use_ecx(source_info, |this| { + if self.use_ecx(location, |this| { let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, &l, &r)?; Ok(overflow) })? { self.report_assert_as_lint( lint::builtin::ARITHMETIC_OVERFLOW, - source_info, + location, "this arithmetic operation will overflow", AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()), ); @@ -412,7 +404,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Some(()) } - fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>, source_info: SourceInfo) -> Option<()> { + fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) -> Option<()> { // Perform any special handling for specific Rvalue types. // Generally, checks here fall into one of two categories: // 1. Additional checking to provide useful lints to the user @@ -427,11 +419,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // lint. Rvalue::UnaryOp(op, arg) => { trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg); - self.check_unary_op(*op, arg, source_info)?; + self.check_unary_op(*op, arg, location)?; } Rvalue::BinaryOp(op, box (left, right)) => { trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); - self.check_binary_op(*op, left, right, source_info)?; + self.check_binary_op(*op, left, right, location)?; } Rvalue::CheckedBinaryOp(op, box (left, right)) => { trace!( @@ -440,7 +432,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { left, right ); - self.check_binary_op(*op, left, right, source_info)?; + self.check_binary_op(*op, left, right, location)?; } // Do not try creating references (#67862) @@ -516,14 +508,13 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { trace!("visit_constant: {:?}", constant); self.super_constant(constant, location); - self.eval_constant(constant, self.source_info.unwrap()); + self.eval_constant(constant, location); } fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { self.super_assign(place, rvalue, location); - let source_info = self.source_info.unwrap(); - let Some(()) = self.check_rvalue(rvalue, source_info) else { return }; + let Some(()) = self.check_rvalue(rvalue, location) else { return }; match self.ecx.machine.can_const_prop[place.local] { // Do nothing if the place is indirect. @@ -531,7 +522,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { ConstPropMode::NoPropagation => self.ensure_not_propagated(place.local), ConstPropMode::OnlyInsideOwnBlock | ConstPropMode::FullConstProp => { if self - .use_ecx(source_info, |this| this.ecx.eval_rvalue_into_place(rvalue, *place)) + .use_ecx(location, |this| this.ecx.eval_rvalue_into_place(rvalue, *place)) .is_none() { // Const prop failed, so erase the destination, ensuring that whatever happens @@ -557,8 +548,6 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { trace!("visit_statement: {:?}", statement); - let source_info = statement.source_info; - self.source_info = Some(source_info); // We want to evaluate operands before any change to the assigned-to value, // so we recurse first. @@ -571,8 +560,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { _ if place.is_indirect() => {} ConstPropMode::NoPropagation => self.ensure_not_propagated(place.local), ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => { - if self.use_ecx(source_info, |this| this.ecx.statement(statement)).is_some() - { + if self.use_ecx(location, |this| this.ecx.statement(statement)).is_some() { trace!("propped discriminant into {:?}", place); } else { Self::remove_const(&mut self.ecx, place.local); @@ -594,12 +582,10 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { } fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - let source_info = terminator.source_info; - self.source_info = Some(source_info); self.super_terminator(terminator, location); match &terminator.kind { TerminatorKind::Assert { expected, ref msg, ref cond, .. } => { - if let Some(ref value) = self.eval_operand(&cond, source_info) { + if let Some(ref value) = self.eval_operand(&cond, location) { trace!("assertion on {:?} should be {:?}", value, expected); let expected = Scalar::from_bool(*expected); let Ok(value_const) = self.ecx.read_scalar(&value) else { @@ -623,7 +609,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { let mut eval_to_int = |op| { // This can be `None` if the lhs wasn't const propagated and we just // triggered the assert on the value of the rhs. - self.eval_operand(op, source_info) + self.eval_operand(op, location) .and_then(|op| self.ecx.read_immediate(&op).ok()) .map_or(DbgVal::Underscore, |op| DbgVal::Val(op.to_const_int())) }; @@ -664,7 +650,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { if let Some(msg) = msg { self.report_assert_as_lint( lint::builtin::UNCONDITIONAL_PANIC, - source_info, + location, "this operation will panic at runtime", msg, ); From f8cfafcceb3b4418a4e29f98a6d2b09975171872 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 30 Mar 2023 18:19:20 +0000 Subject: [PATCH 146/267] Extract check_assertion. --- .../src/const_prop_lint.rs | 143 +++++++++--------- 1 file changed, 71 insertions(+), 72 deletions(-) diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 47bcba0f2500..c8ed30cdcf30 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -480,6 +480,76 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Some(()) } + fn check_assertion( + &mut self, + expected: bool, + msg: &AssertKind>, + cond: &Operand<'tcx>, + location: Location, + ) -> Option { + let ref value = self.eval_operand(&cond, location)?; + trace!("assertion on {:?} should be {:?}", value, expected); + + let expected = Scalar::from_bool(expected); + let value_const = self.use_ecx(location, |this| this.ecx.read_scalar(&value))?; + + if expected != value_const { + // Poison all places this operand references so that further code + // doesn't use the invalid value + match cond { + Operand::Move(ref place) | Operand::Copy(ref place) => { + Self::remove_const(&mut self.ecx, place.local); + } + Operand::Constant(_) => {} + } + enum DbgVal { + Val(T), + Underscore, + } + impl std::fmt::Debug for DbgVal { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Val(val) => val.fmt(fmt), + Self::Underscore => fmt.write_str("_"), + } + } + } + let mut eval_to_int = |op| { + // This can be `None` if the lhs wasn't const propagated and we just + // triggered the assert on the value of the rhs. + self.eval_operand(op, location) + .and_then(|op| self.ecx.read_immediate(&op).ok()) + .map_or(DbgVal::Underscore, |op| DbgVal::Val(op.to_const_int())) + }; + let msg = match msg { + AssertKind::DivisionByZero(op) => AssertKind::DivisionByZero(eval_to_int(op)), + AssertKind::RemainderByZero(op) => AssertKind::RemainderByZero(eval_to_int(op)), + AssertKind::Overflow(bin_op @ (BinOp::Div | BinOp::Rem), op1, op2) => { + // Division overflow is *UB* in the MIR, and different than the + // other overflow checks. + AssertKind::Overflow(*bin_op, eval_to_int(op1), eval_to_int(op2)) + } + AssertKind::BoundsCheck { ref len, ref index } => { + let len = eval_to_int(len); + let index = eval_to_int(index); + AssertKind::BoundsCheck { len, index } + } + // Remaining overflow errors are already covered by checks on the binary operators. + AssertKind::Overflow(..) | AssertKind::OverflowNeg(_) => return None, + // Need proper const propagator for these. + _ => return None, + }; + self.report_assert_as_lint( + lint::builtin::UNCONDITIONAL_PANIC, + location, + "this operation will panic at runtime", + msg, + ); + } + + None + } + fn ensure_not_propagated(&self, local: Local) { if cfg!(debug_assertions) { assert!( @@ -585,78 +655,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { self.super_terminator(terminator, location); match &terminator.kind { TerminatorKind::Assert { expected, ref msg, ref cond, .. } => { - if let Some(ref value) = self.eval_operand(&cond, location) { - trace!("assertion on {:?} should be {:?}", value, expected); - let expected = Scalar::from_bool(*expected); - let Ok(value_const) = self.ecx.read_scalar(&value) else { - // FIXME should be used use_ecx rather than a local match... but we have - // quite a few of these read_scalar/read_immediate that need fixing. - return - }; - if expected != value_const { - enum DbgVal { - Val(T), - Underscore, - } - impl std::fmt::Debug for DbgVal { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Val(val) => val.fmt(fmt), - Self::Underscore => fmt.write_str("_"), - } - } - } - let mut eval_to_int = |op| { - // This can be `None` if the lhs wasn't const propagated and we just - // triggered the assert on the value of the rhs. - self.eval_operand(op, location) - .and_then(|op| self.ecx.read_immediate(&op).ok()) - .map_or(DbgVal::Underscore, |op| DbgVal::Val(op.to_const_int())) - }; - let msg = match msg { - AssertKind::DivisionByZero(op) => { - Some(AssertKind::DivisionByZero(eval_to_int(op))) - } - AssertKind::RemainderByZero(op) => { - Some(AssertKind::RemainderByZero(eval_to_int(op))) - } - AssertKind::Overflow(bin_op @ (BinOp::Div | BinOp::Rem), op1, op2) => { - // Division overflow is *UB* in the MIR, and different than the - // other overflow checks. - Some(AssertKind::Overflow( - *bin_op, - eval_to_int(op1), - eval_to_int(op2), - )) - } - AssertKind::BoundsCheck { ref len, ref index } => { - let len = eval_to_int(len); - let index = eval_to_int(index); - Some(AssertKind::BoundsCheck { len, index }) - } - // Remaining overflow errors are already covered by checks on the binary operators. - AssertKind::Overflow(..) | AssertKind::OverflowNeg(_) => None, - // Need proper const propagator for these. - _ => None, - }; - // Poison all places this operand references so that further code - // doesn't use the invalid value - match cond { - Operand::Move(ref place) | Operand::Copy(ref place) => { - Self::remove_const(&mut self.ecx, place.local); - } - Operand::Constant(_) => {} - } - if let Some(msg) = msg { - self.report_assert_as_lint( - lint::builtin::UNCONDITIONAL_PANIC, - location, - "this operation will panic at runtime", - msg, - ); - } - } - } + self.check_assertion(*expected, msg, cond, location); } // None of these have Operands to const-propagate. TerminatorKind::Goto { .. } From 7d47a910eba199e321a908cec62ee35bc41535e1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 30 Mar 2023 18:40:47 +0000 Subject: [PATCH 147/267] Only visit reachable blocks in ConstProp lint. --- .../src/const_prop_lint.rs | 40 +++++++++++++++---- tests/ui/const_prop/unreachable-bounds.rs | 6 +++ tests/ui/const_prop/unreachable-overflow.rs | 10 +++++ 3 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 tests/ui/const_prop/unreachable-bounds.rs create mode 100644 tests/ui/const_prop/unreachable-overflow.rs diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index c8ed30cdcf30..99bdb831c750 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -9,6 +9,7 @@ use rustc_const_eval::interpret::{ }; use rustc_hir::def::DefKind; use rustc_hir::HirId; +use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; @@ -129,6 +130,8 @@ struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, + worklist: Vec, + visited_blocks: BitSet, } impl<'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'_, 'tcx> { @@ -203,7 +206,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ) .expect("failed to push initial stack frame"); - ConstPropagator { ecx, tcx, param_env } + ConstPropagator { + ecx, + tcx, + param_env, + worklist: vec![START_BLOCK], + visited_blocks: BitSet::new_empty(body.basic_blocks.len()), + } } fn body(&self) -> &'mir Body<'tcx> { @@ -496,12 +505,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if expected != value_const { // Poison all places this operand references so that further code // doesn't use the invalid value - match cond { - Operand::Move(ref place) | Operand::Copy(ref place) => { - Self::remove_const(&mut self.ecx, place.local); - } - Operand::Constant(_) => {} + if let Some(place) = cond.place() { + Self::remove_const(&mut self.ecx, place.local); } + enum DbgVal { Val(T), Underscore, @@ -566,7 +573,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { fn visit_body(&mut self, body: &Body<'tcx>) { - for (bb, data) in body.basic_blocks.iter_enumerated() { + while let Some(bb) = self.worklist.pop() { + if !self.visited_blocks.insert(bb) { + continue; + } + + let data = &body.basic_blocks[bb]; self.visit_basic_block_data(bb, data); } } @@ -657,6 +669,17 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { TerminatorKind::Assert { expected, ref msg, ref cond, .. } => { self.check_assertion(*expected, msg, cond, location); } + TerminatorKind::SwitchInt { ref discr, ref targets } => { + if let Some(ref value) = self.eval_operand(&discr, location) + && let Some(value_const) = self.use_ecx(location, |this| this.ecx.read_scalar(&value)) + && let Ok(constant) = value_const.try_to_int() + && let Ok(constant) = constant.to_bits(constant.size()) + { + let target = targets.target_for_value(constant); + self.worklist.push(target); + return; + } + } // None of these have Operands to const-propagate. TerminatorKind::Goto { .. } | TerminatorKind::Resume @@ -668,10 +691,11 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::SwitchInt { .. } | TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => {} } + + self.worklist.extend(terminator.successors()); } fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) { diff --git a/tests/ui/const_prop/unreachable-bounds.rs b/tests/ui/const_prop/unreachable-bounds.rs new file mode 100644 index 000000000000..8cf98e154eaa --- /dev/null +++ b/tests/ui/const_prop/unreachable-bounds.rs @@ -0,0 +1,6 @@ +// Use `build-pass` to ensure const-prop lint runs. +// build-pass + +fn main() { + [()][if false { 1 } else { return }] +} diff --git a/tests/ui/const_prop/unreachable-overflow.rs b/tests/ui/const_prop/unreachable-overflow.rs new file mode 100644 index 000000000000..2875135424d2 --- /dev/null +++ b/tests/ui/const_prop/unreachable-overflow.rs @@ -0,0 +1,10 @@ +// Use `build-pass` to ensure const-prop lint runs. +// build-pass + +fn main() { + let x = 2u32; + let y = 3u32; + if y <= x { + dbg!(x - y); + } +} From 98255cc2424b8ad3de462dc4241e14e23b1aa5c5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 4 Apr 2023 17:14:53 +0000 Subject: [PATCH 148/267] Comment logic around worklist. --- compiler/rustc_mir_transform/src/const_prop_lint.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 99bdb831c750..942ccd5a9d19 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -675,10 +675,13 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { && let Ok(constant) = value_const.try_to_int() && let Ok(constant) = constant.to_bits(constant.size()) { + // We managed to evaluate the discriminant, so we know we only need to visit + // one target. let target = targets.target_for_value(constant); self.worklist.push(target); return; } + // We failed to evaluate the discriminant, fallback to visiting all successors. } // None of these have Operands to const-propagate. TerminatorKind::Goto { .. } From 8f5404d0d79f7cef9445b531aae5394fe3b22f29 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 5 Apr 2023 17:13:12 +0200 Subject: [PATCH 149/267] Update GUI tests for logo display on very small screens --- tests/rustdoc-gui/huge-logo.goml | 4 +++- tests/rustdoc-gui/source-code-page.goml | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/rustdoc-gui/huge-logo.goml b/tests/rustdoc-gui/huge-logo.goml index 01f06771c15a..69459bd3e23b 100644 --- a/tests/rustdoc-gui/huge-logo.goml +++ b/tests/rustdoc-gui/huge-logo.goml @@ -18,4 +18,6 @@ size: (1280, 1024) assert-property: (".sub-logo-container", {"offsetWidth": "60", "offsetHeight": 60}) size: (400, 600) -assert-property: (".sub-logo-container", {"offsetWidth": "35", "offsetHeight": 35}) +// 43 because 35px + 8px of margin +assert-css: (".sub-logo-container > img", {"margin-bottom": "8px"}) +assert-property: (".sub-logo-container", {"offsetWidth": "35", "offsetHeight": 43}) diff --git a/tests/rustdoc-gui/source-code-page.goml b/tests/rustdoc-gui/source-code-page.goml index 7c35119e6959..ea6ff12328ca 100644 --- a/tests/rustdoc-gui/source-code-page.goml +++ b/tests/rustdoc-gui/source-code-page.goml @@ -216,3 +216,8 @@ call-function: ("check-sidebar-dir-entry", { "x": 0, "y": |source_sidebar_title_y| + |source_sidebar_title_height| + 6, }) + +// Now we check that the logo has a bottom margin so it's not stuck to the search input. +assert-css: (".sub-logo-container > img", {"margin-bottom": "8px"}) +store-property: (logo_height, ".sub-logo-container", "clientHeight") +assert-position: (".search-form", {"y": |logo_height| + 8}) From e9daab25deb3bcfb98716ccd45d02674e0556275 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 5 Apr 2023 09:11:10 -0700 Subject: [PATCH 150/267] rustdoc: avoid including line numbers in Google SERP snippets --- src/librustdoc/html/static/css/rustdoc.css | 14 +++++++------- src/librustdoc/html/templates/source.html | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 726394d8348e..27169c60b1f1 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -348,7 +348,7 @@ pre.item-decl { .source .content pre { padding: 20px; } -.rustdoc.source .example-wrap > pre.src-line-numbers { +.rustdoc.source .example-wrap pre.src-line-numbers { padding: 20px 0 20px 4px; } @@ -533,17 +533,17 @@ ul.block, .block li { margin-bottom: 0px; } -.rustdoc .example-wrap > pre { +.rustdoc .example-wrap pre { margin: 0; flex-grow: 1; } -.rustdoc:not(.source) .example-wrap > pre { +.rustdoc:not(.source) .example-wrap pre { overflow: auto hidden; } -.rustdoc .example-wrap > pre.example-line-numbers, -.rustdoc .example-wrap > pre.src-line-numbers { +.rustdoc .example-wrap pre.example-line-numbers, +.rustdoc .example-wrap pre.src-line-numbers { flex-grow: 0; min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */ overflow: initial; @@ -554,7 +554,7 @@ ul.block, .block li { color: var(--src-line-numbers-span-color); } -.rustdoc .example-wrap > pre.src-line-numbers { +.rustdoc .example-wrap pre.src-line-numbers { padding: 14px 0; } .src-line-numbers a, .src-line-numbers span { @@ -702,7 +702,7 @@ h2.small-section-header > .anchor { } .main-heading a:hover, -.example-wrap > .rust a:hover, +.example-wrap .rust a:hover, .all-items a:hover, .docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, .docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, diff --git a/src/librustdoc/html/templates/source.html b/src/librustdoc/html/templates/source.html index a224ff12f448..42d01277db2c 100644 --- a/src/librustdoc/html/templates/source.html +++ b/src/librustdoc/html/templates/source.html @@ -1,5 +1,7 @@ {# #}
 {# #}
         
             {% if needs_expansion %}

From 4fc3c6b07a5aff0bb3da87496daf825b128d6e08 Mon Sep 17 00:00:00 2001
From: yukang 
Date: Thu, 6 Apr 2023 06:51:49 +0800
Subject: [PATCH 151/267] add comment

---
 compiler/rustc_span/src/edit_distance.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs
index 19c4aae97efe..9fe9e3a7a5fd 100644
--- a/compiler/rustc_span/src/edit_distance.rs
+++ b/compiler/rustc_span/src/edit_distance.rs
@@ -218,6 +218,9 @@ fn find_best_match_for_name_impl(
         }
     }
 
+    // We have a tie among several candidates, try to select the best among them ignoring substrings.
+    // For example, the candidates list `force_capture`, `capture`, and user inputed `forced_capture`,
+    // we select `force_capture` with a extra round of edit distance calculation.
     if next_candidates.len() > 1 {
         debug_assert!(use_substring_score);
         best = find_best_match_for_name_impl(

From 9169107c1cf15bc955bb15a06d83a1ebf011e9eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=AE=A1=E5=94=AF=E5=AE=87?= 
Date: Thu, 6 Apr 2023 11:48:16 +0800
Subject: [PATCH 152/267] Remove an unnecessary `mut` in
 `BufWriter::into_parts`.

`ptr::read` takes `*const T` so `&mut` is not necessary.
---
 library/std/src/io/buffered/bufwriter.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 6acb937e7847..14c455d4fa3c 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -339,7 +339,7 @@ impl BufWriter {
         let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
 
         // SAFETY: forget(self) prevents double dropping inner
-        let inner = unsafe { ptr::read(&mut self.inner) };
+        let inner = unsafe { ptr::read(&self.inner) };
         mem::forget(self);
 
         (inner, buf)

From af74ef89934ad30b24132b464b6b4cf7cb0e1381 Mon Sep 17 00:00:00 2001
From: Deadbeef 
Date: Mon, 27 Mar 2023 13:44:06 +0000
Subject: [PATCH 153/267] migrate rustc_macros to syn 2.0

---
 Cargo.lock                                    |  24 ++-
 compiler/rustc_macros/Cargo.toml              |   4 +-
 .../src/diagnostics/diagnostic_builder.rs     | 154 ++++++---------
 .../rustc_macros/src/diagnostics/error.rs     |  55 +-----
 .../src/diagnostics/subdiagnostic.rs          |  76 ++++---
 .../rustc_macros/src/diagnostics/utils.rs     | 186 +++++++++---------
 compiler/rustc_macros/src/hash_stable.rs      |  45 ++---
 compiler/rustc_macros/src/newtype.rs          |  10 +-
 compiler/rustc_macros/src/query.rs            |   8 +-
 compiler/rustc_macros/src/type_foldable.rs    |  27 ++-
 compiler/rustc_macros/src/type_visitable.rs   |  30 +--
 11 files changed, 275 insertions(+), 344 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index d9e9ef9fb0ff..be8afa930c6e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -632,7 +632,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "syn 1.0.102",
- "synstructure",
+ "synstructure 0.12.6",
 ]
 
 [[package]]
@@ -4994,8 +4994,8 @@ dependencies = [
  "fluent-syntax",
  "proc-macro2",
  "quote",
- "syn 1.0.102",
- "synstructure",
+ "syn 2.0.8",
+ "synstructure 0.13.0",
  "unic-langid",
 ]
 
@@ -6131,6 +6131,18 @@ dependencies = [
  "unicode-xid",
 ]
 
+[[package]]
+name = "synstructure"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.8",
+ "unicode-xid",
+]
+
 [[package]]
 name = "tar"
 version = "0.4.38"
@@ -7154,7 +7166,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "syn 1.0.102",
- "synstructure",
+ "synstructure 0.12.6",
 ]
 
 [[package]]
@@ -7175,7 +7187,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "syn 1.0.102",
- "synstructure",
+ "synstructure 0.12.6",
 ]
 
 [[package]]
@@ -7204,5 +7216,5 @@ dependencies = [
  "proc-macro2",
  "quote",
  "syn 1.0.102",
- "synstructure",
+ "synstructure 0.12.6",
 ]
diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml
index 547c8debb505..745983e7e869 100644
--- a/compiler/rustc_macros/Cargo.toml
+++ b/compiler/rustc_macros/Cargo.toml
@@ -10,8 +10,8 @@ proc-macro = true
 annotate-snippets = "0.9"
 fluent-bundle = "0.15.2"
 fluent-syntax = "0.11"
-synstructure = "0.12.1"
-syn = { version = "1", features = ["full"] }
+synstructure = "0.13.0"
+syn = { version = "2", features = ["full"] }
 proc-macro2 = "1"
 quote = "1"
 unic-langid = { version = "0.9.0", features = ["macros"] }
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 7fbe3bc2888c..fb75d87f8d2e 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -1,8 +1,7 @@
 #![deny(unused_must_use)]
 
 use crate::diagnostics::error::{
-    invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
-    DiagnosticDeriveError,
+    span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
 };
 use crate::diagnostics::utils::{
     build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
@@ -11,9 +10,8 @@ use crate::diagnostics::utils::{
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote};
-use syn::{
-    parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type,
-};
+use syn::Token;
+use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
 use synstructure::{BindingInfo, Structure, VariantInfo};
 
 /// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
@@ -77,7 +75,7 @@ impl DiagnosticDeriveBuilder {
         match ast.data {
             syn::Data::Struct(..) | syn::Data::Enum(..) => (),
             syn::Data::Union(..) => {
-                span_err(span, "diagnostic derives can only be used on structs and enums");
+                span_err(span, "diagnostic derives can only be used on structs and enums").emit();
             }
         }
 
@@ -160,8 +158,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
         };
 
         if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
-            let meta = attr.parse_meta()?;
-            throw_invalid_attr!(attr, &meta, |diag| diag
+            throw_invalid_attr!(attr, |diag| diag
                 .help("consider creating a `Subdiagnostic` instead"));
         }
 
@@ -191,71 +188,39 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
             return Ok(quote! {});
         }
 
-        let name = attr.path.segments.last().unwrap().ident.to_string();
+        let name = attr.path().segments.last().unwrap().ident.to_string();
         let name = name.as_str();
-        let meta = attr.parse_meta()?;
+
+        let mut first = true;
 
         if name == "diag" {
-            let Meta::List(MetaList { ref nested, .. }) = meta else {
-                throw_invalid_attr!(
-                    attr,
-                    &meta
-                );
-            };
-
-            let mut nested_iter = nested.into_iter().peekable();
-
-            match nested_iter.peek() {
-                Some(NestedMeta::Meta(Meta::Path(slug))) => {
-                    self.slug.set_once(slug.clone(), slug.span().unwrap());
-                    nested_iter.next();
-                }
-                Some(NestedMeta::Meta(Meta::NameValue { .. })) => {}
-                Some(nested_attr) => throw_invalid_nested_attr!(attr, nested_attr, |diag| diag
-                    .help("a diagnostic slug is required as the first argument")),
-                None => throw_invalid_attr!(attr, &meta, |diag| diag
-                    .help("a diagnostic slug is required as the first argument")),
-            };
-
-            // Remaining attributes are optional, only `code = ".."` at the moment.
             let mut tokens = TokenStream::new();
-            for nested_attr in nested_iter {
-                let (value, path) = match nested_attr {
-                    NestedMeta::Meta(Meta::NameValue(MetaNameValue {
-                        lit: syn::Lit::Str(value),
-                        path,
-                        ..
-                    })) => (value, path),
-                    NestedMeta::Meta(Meta::Path(_)) => {
-                        invalid_nested_attr(attr, nested_attr)
-                            .help("diagnostic slug must be the first argument")
-                            .emit();
-                        continue;
-                    }
-                    _ => {
-                        invalid_nested_attr(attr, nested_attr).emit();
-                        continue;
-                    }
+            attr.parse_nested_meta(|nested| {
+                let path = &nested.path;
+
+                if first && (nested.input.is_empty() || nested.input.peek(Token![,])) {
+                    self.slug.set_once(path.clone(), path.span().unwrap());
+                    first = false;
+                    return Ok(())
+                }
+
+                first = false;
+
+                let Ok(nested) = nested.value() else {
+                    span_err(nested.input.span().unwrap(), "diagnostic slug must be the first argument").emit();
+                    return Ok(())
                 };
 
-                let nested_name = path.segments.last().unwrap().ident.to_string();
-                // Struct attributes are only allowed to be applied once, and the diagnostic
-                // changes will be set in the initialisation code.
-                let span = value.span().unwrap();
-                match nested_name.as_str() {
-                    "code" => {
-                        self.code.set_once((), span);
+                if path.is_ident("code") {
+                    self.code.set_once((), path.span().unwrap());
 
-                        let code = value.value();
-                        tokens.extend(quote! {
-                            #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
-                        });
-                    }
-                    _ => invalid_nested_attr(attr, nested_attr)
-                        .help("only `code` is a valid nested attributes following the slug")
-                        .emit(),
+                    let code = nested.parse::()?;
+                    tokens.extend(quote! {
+                        #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
+                    });
                 }
-            }
+                Ok(())
+            })?;
             return Ok(tokens);
         }
 
@@ -270,7 +235,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                 Ok(self.add_subdiagnostic(&fn_ident, slug))
             }
             SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => {
-                throw_invalid_attr!(attr, &meta, |diag| diag
+                throw_invalid_attr!(attr, |diag| diag
                     .help("`#[label]` and `#[suggestion]` can only be applied to fields"));
             }
             SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
@@ -309,7 +274,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                     return quote! {};
                 }
 
-                let name = attr.path.segments.last().unwrap().ident.to_string();
+                let name = attr.path().segments.last().unwrap().ident.to_string();
                 let needs_clone =
                     name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
                 let (binding, needs_destructure) = if needs_clone {
@@ -343,11 +308,10 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
         binding: TokenStream,
     ) -> Result {
         let diag = &self.parent.diag;
-        let meta = attr.parse_meta()?;
 
-        let ident = &attr.path.segments.last().unwrap().ident;
+        let ident = &attr.path().segments.last().unwrap().ident;
         let name = ident.to_string();
-        match (&meta, name.as_str()) {
+        match (&attr.meta, name.as_str()) {
             // Don't need to do anything - by virtue of the attribute existing, the
             // `set_arg` call will not be generated.
             (Meta::Path(_), "skip_arg") => return Ok(quote! {}),
@@ -361,7 +325,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                         });
                     }
                     DiagnosticDeriveKind::LintDiagnostic => {
-                        throw_invalid_attr!(attr, &meta, |diag| {
+                        throw_invalid_attr!(attr, |diag| {
                             diag.help("the `primary_span` field attribute is not valid for lint diagnostics")
                         })
                     }
@@ -378,26 +342,34 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                     return Ok(quote! { #diag.subdiagnostic(#binding); });
                 }
             }
-            (Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
-                if nested.len() == 1
-                    && let Some(NestedMeta::Meta(Meta::Path(path))) = nested.first()
-                    && path.is_ident("eager") {
-                        let handler = match &self.parent.kind {
-                            DiagnosticDeriveKind::Diagnostic { handler } => handler,
-                            DiagnosticDeriveKind::LintDiagnostic => {
-                                throw_invalid_attr!(attr, &meta, |diag| {
-                                    diag.help("eager subdiagnostics are not supported on lints")
-                                })
-                            }
-                        };
-                        return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
-                } else {
-                    throw_invalid_attr!(attr, &meta, |diag| {
-                        diag.help(
-                            "`eager` is the only supported nested attribute for `subdiagnostic`",
-                        )
-                    })
+            (Meta::List(meta_list), "subdiagnostic") => {
+                let err = || {
+                    span_err(
+                        meta_list.span().unwrap(),
+                        "`eager` is the only supported nested attribute for `subdiagnostic`",
+                    )
+                    .emit();
+                };
+
+                let Ok(p): Result = meta_list.parse_args() else {
+                    err();
+                    return Ok(quote! {});
+                };
+
+                if !p.is_ident("eager") {
+                    err();
+                    return Ok(quote! {});
                 }
+
+                let handler = match &self.parent.kind {
+                    DiagnosticDeriveKind::Diagnostic { handler } => handler,
+                    DiagnosticDeriveKind::LintDiagnostic => {
+                        throw_invalid_attr!(attr, |diag| {
+                            diag.help("eager subdiagnostics are not supported on lints")
+                        })
+                    }
+                };
+                return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
             }
             _ => (),
         }
@@ -432,7 +404,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                 code_init,
             } => {
                 if let FieldInnerTy::Vec(_) = info.ty {
-                    throw_invalid_attr!(attr, &meta, |diag| {
+                    throw_invalid_attr!(attr, |diag| {
                         diag
                         .note("`#[suggestion(...)]` applied to `Vec` field is ambiguous")
                         .help("to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`")
diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs
index 2d62d5931638..b37dc826d288 100644
--- a/compiler/rustc_macros/src/diagnostics/error.rs
+++ b/compiler/rustc_macros/src/diagnostics/error.rs
@@ -1,7 +1,7 @@
 use proc_macro::{Diagnostic, Level, MultiSpan};
 use proc_macro2::TokenStream;
 use quote::quote;
-use syn::{spanned::Spanned, Attribute, Error as SynError, Meta, NestedMeta};
+use syn::{spanned::Spanned, Attribute, Error as SynError, Meta};
 
 #[derive(Debug)]
 pub(crate) enum DiagnosticDeriveError {
@@ -53,6 +53,7 @@ fn path_to_string(path: &syn::Path) -> String {
 }
 
 /// Returns an error diagnostic on span `span` with msg `msg`.
+#[must_use]
 pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic {
     Diagnostic::spanned(span, Level::Error, msg)
 }
@@ -72,10 +73,10 @@ macro_rules! throw_span_err {
 pub(crate) use throw_span_err;
 
 /// Returns an error diagnostic for an invalid attribute.
-pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
+pub(crate) fn invalid_attr(attr: &Attribute) -> Diagnostic {
     let span = attr.span().unwrap();
-    let path = path_to_string(&attr.path);
-    match meta {
+    let path = path_to_string(attr.path());
+    match attr.meta {
         Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")),
         Meta::NameValue(_) => {
             span_err(span, &format!("`#[{path} = ...]` is not a valid attribute"))
@@ -89,51 +90,11 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
 ///
 /// For methods that return a `Result<_, DiagnosticDeriveError>`:
 macro_rules! throw_invalid_attr {
-    ($attr:expr, $meta:expr) => {{ throw_invalid_attr!($attr, $meta, |diag| diag) }};
-    ($attr:expr, $meta:expr, $f:expr) => {{
-        let diag = crate::diagnostics::error::invalid_attr($attr, $meta);
+    ($attr:expr) => {{ throw_invalid_attr!($attr, |diag| diag) }};
+    ($attr:expr, $f:expr) => {{
+        let diag = crate::diagnostics::error::invalid_attr($attr);
         return Err(crate::diagnostics::error::_throw_err(diag, $f));
     }};
 }
 
 pub(crate) use throw_invalid_attr;
-
-/// Returns an error diagnostic for an invalid nested attribute.
-pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diagnostic {
-    let name = attr.path.segments.last().unwrap().ident.to_string();
-    let name = name.as_str();
-
-    let span = nested.span().unwrap();
-    let meta = match nested {
-        syn::NestedMeta::Meta(meta) => meta,
-        syn::NestedMeta::Lit(_) => {
-            return span_err(span, &format!("`#[{name}(\"...\")]` is not a valid attribute"));
-        }
-    };
-
-    let span = meta.span().unwrap();
-    let path = path_to_string(meta.path());
-    match meta {
-        Meta::NameValue(..) => {
-            span_err(span, &format!("`#[{name}({path} = ...)]` is not a valid attribute"))
-        }
-        Meta::Path(..) => span_err(span, &format!("`#[{name}({path})]` is not a valid attribute")),
-        Meta::List(..) => {
-            span_err(span, &format!("`#[{name}({path}(...))]` is not a valid attribute"))
-        }
-    }
-}
-
-/// Emit an error diagnostic for an invalid nested attribute (optionally performing additional
-/// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
-///
-/// For methods that return a `Result<_, DiagnosticDeriveError>`:
-macro_rules! throw_invalid_nested_attr {
-    ($attr:expr, $nested_attr:expr) => {{ throw_invalid_nested_attr!($attr, $nested_attr, |diag| diag) }};
-    ($attr:expr, $nested_attr:expr, $f:expr) => {{
-        let diag = crate::diagnostics::error::invalid_nested_attr($attr, $nested_attr);
-        return Err(crate::diagnostics::error::_throw_err(diag, $f));
-    }};
-}
-
-pub(crate) use throw_invalid_nested_attr;
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 90660fc1f93d..2f42a3b0bd48 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -1,8 +1,7 @@
 #![deny(unused_must_use)]
 
 use crate::diagnostics::error::{
-    invalid_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
-    DiagnosticDeriveError,
+    invalid_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
 };
 use crate::diagnostics::utils::{
     build_field_mapping, is_doc_comment, new_code_ident,
@@ -11,7 +10,7 @@ use crate::diagnostics::utils::{
 };
 use proc_macro2::TokenStream;
 use quote::{format_ident, quote};
-use syn::{spanned::Spanned, Attribute, Meta, MetaList, NestedMeta, Path};
+use syn::{spanned::Spanned, Attribute, Meta, MetaList, Path};
 use synstructure::{BindingInfo, Structure, VariantInfo};
 
 use super::utils::{build_suggestion_code, AllowMultipleAlternatives};
@@ -39,7 +38,8 @@ impl SubdiagnosticDeriveBuilder {
                     span_err(
                         span,
                         "`#[derive(Subdiagnostic)]` can only be used on structs and enums",
-                    );
+                    )
+                    .emit();
                 }
             }
 
@@ -192,7 +192,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
             };
 
             let Some(slug) = slug else {
-                let name = attr.path.segments.last().unwrap().ident.to_string();
+                let name = attr.path().segments.last().unwrap().ident.to_string();
                 let name = name.as_str();
 
                 throw_span_err!(
@@ -265,17 +265,18 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
         info: FieldInfo<'_>,
         clone_suggestion_code: bool,
     ) -> Result {
-        let meta = attr.parse_meta()?;
-        match meta {
-            Meta::Path(path) => self.generate_field_code_inner_path(kind_stats, attr, info, path),
-            Meta::List(list @ MetaList { .. }) => self.generate_field_code_inner_list(
+        match &attr.meta {
+            Meta::Path(path) => {
+                self.generate_field_code_inner_path(kind_stats, attr, info, path.clone())
+            }
+            Meta::List(list) => self.generate_field_code_inner_list(
                 kind_stats,
                 attr,
                 info,
                 list,
                 clone_suggestion_code,
             ),
-            _ => throw_invalid_attr!(attr, &meta),
+            _ => throw_invalid_attr!(attr),
         }
     }
 
@@ -296,7 +297,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
             "skip_arg" => Ok(quote! {}),
             "primary_span" => {
                 if kind_stats.has_multipart_suggestion {
-                    invalid_attr(attr, &Meta::Path(path))
+                    invalid_attr(attr)
                         .help(
                             "multipart suggestions use one or more `#[suggestion_part]`s rather \
                             than one `#[primary_span]`",
@@ -309,7 +310,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                     // FIXME(#100717): support `Option` on `primary_span` like in the
                     // diagnostic derive
                     if !matches!(info.ty, FieldInnerTy::Plain(_)) {
-                        throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
+                        throw_invalid_attr!(attr, |diag| {
                             let diag = diag.note("there must be exactly one primary span");
 
                             if kind_stats.has_normal_suggestion {
@@ -335,7 +336,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                     span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
                         .emit();
                 } else {
-                    invalid_attr(attr, &Meta::Path(path))
+                    invalid_attr(attr)
                         .help(
                             "`#[suggestion_part(...)]` is only valid in multipart suggestions, \
                              use `#[primary_span]` instead",
@@ -375,7 +376,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                     span_attrs.push("primary_span")
                 }
 
-                invalid_attr(attr, &Meta::Path(path))
+                invalid_attr(attr)
                     .help(format!(
                         "only `{}`, `applicability` and `skip_arg` are valid field attributes",
                         span_attrs.join(", ")
@@ -394,7 +395,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
         kind_stats: KindsStatistics,
         attr: &Attribute,
         info: FieldInfo<'_>,
-        list: MetaList,
+        list: &MetaList,
         clone_suggestion_code: bool,
     ) -> Result {
         let span = attr.span().unwrap();
@@ -405,7 +406,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
         match name {
             "suggestion_part" => {
                 if !kind_stats.has_multipart_suggestion {
-                    throw_invalid_attr!(attr, &Meta::List(list), |diag| {
+                    throw_invalid_attr!(attr, |diag| {
                         diag.help(
                             "`#[suggestion_part(...)]` is only valid in multipart suggestions",
                         )
@@ -417,31 +418,26 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                 report_error_if_not_applied_to_span(attr, &info)?;
 
                 let mut code = None;
-                for nested_attr in list.nested.iter() {
-                    let NestedMeta::Meta(ref meta) = nested_attr else {
-                        throw_invalid_nested_attr!(attr, nested_attr);
-                    };
 
-                    let span = meta.span().unwrap();
-                    let nested_name = meta.path().segments.last().unwrap().ident.to_string();
-                    let nested_name = nested_name.as_str();
-
-                    match nested_name {
-                        "code" => {
-                            let code_field = new_code_ident();
-                            let formatting_init = build_suggestion_code(
-                                &code_field,
-                                meta,
-                                self,
-                                AllowMultipleAlternatives::No,
-                            );
-                            code.set_once((code_field, formatting_init), span);
-                        }
-                        _ => throw_invalid_nested_attr!(attr, nested_attr, |diag| {
-                            diag.help("`code` is the only valid nested attribute")
-                        }),
+                list.parse_nested_meta(|nested| {
+                    if nested.path.is_ident("code") {
+                        let code_field = new_code_ident();
+                        let formatting_init = build_suggestion_code(
+                            &code_field,
+                            nested,
+                            self,
+                            AllowMultipleAlternatives::No,
+                        );
+                        code.set_once((code_field, formatting_init), span);
+                    } else {
+                        span_err(
+                            nested.path.span().unwrap(),
+                            "`code` is the only valid nested attribute",
+                        )
+                        .emit();
                     }
-                }
+                    Ok(())
+                })?;
 
                 let Some((code_field, formatting_init)) = code.value() else {
                     span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
@@ -458,7 +454,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                 };
                 Ok(quote! { suggestions.push((#binding, #code_field)); })
             }
-            _ => throw_invalid_attr!(attr, &Meta::List(list), |diag| {
+            _ => throw_invalid_attr!(attr, |diag| {
                 let mut span_attrs = vec![];
                 if kind_stats.has_multipart_suggestion {
                     span_attrs.push("suggestion_part");
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 65bb154d7f39..38292df6d854 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -1,5 +1,5 @@
 use crate::diagnostics::error::{
-    span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError,
+    span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
 };
 use proc_macro::Span;
 use proc_macro2::{Ident, TokenStream};
@@ -8,11 +8,13 @@ use std::cell::RefCell;
 use std::collections::{BTreeSet, HashMap};
 use std::fmt;
 use std::str::FromStr;
+use syn::meta::ParseNestedMeta;
+use syn::punctuated::Punctuated;
+use syn::{parenthesized, LitStr, Path, Token};
 use syn::{spanned::Spanned, Attribute, Field, Meta, Type, TypeTuple};
-use syn::{MetaList, MetaNameValue, NestedMeta, Path};
 use synstructure::{BindingInfo, VariantInfo};
 
-use super::error::{invalid_attr, invalid_nested_attr};
+use super::error::invalid_attr;
 
 thread_local! {
     pub static CODE_IDENT_COUNT: RefCell = RefCell::new(0);
@@ -60,8 +62,8 @@ pub(crate) fn report_type_error(
     attr: &Attribute,
     ty_name: &str,
 ) -> Result {
-    let name = attr.path.segments.last().unwrap().ident.to_string();
-    let meta = attr.parse_meta()?;
+    let name = attr.path().segments.last().unwrap().ident.to_string();
+    let meta = &attr.meta;
 
     throw_span_err!(
         attr.span().unwrap(),
@@ -422,55 +424,53 @@ pub(super) enum AllowMultipleAlternatives {
 /// `#[suggestion*(code("foo", "bar"))]` attribute field
 pub(super) fn build_suggestion_code(
     code_field: &Ident,
-    meta: &Meta,
+    nested: ParseNestedMeta<'_>,
     fields: &impl HasFieldMap,
     allow_multiple: AllowMultipleAlternatives,
 ) -> TokenStream {
-    let values = match meta {
-        // `code = "foo"`
-        Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => vec![s],
-        // `code("foo", "bar")`
-        Meta::List(MetaList { nested, .. }) => {
+    let values = match (|| {
+        let values: Vec = if let Ok(val) = nested.value() {
+            vec![val.parse()?]
+        } else {
+            let content;
+            parenthesized!(content in nested.input);
+
             if let AllowMultipleAlternatives::No = allow_multiple {
                 span_err(
-                    meta.span().unwrap(),
+                    nested.input.span().unwrap(),
                     "expected exactly one string literal for `code = ...`",
                 )
                 .emit();
                 vec![]
-            } else if nested.is_empty() {
-                span_err(
-                    meta.span().unwrap(),
-                    "expected at least one string literal for `code(...)`",
-                )
-                .emit();
-                vec![]
             } else {
-                nested
-                    .into_iter()
-                    .filter_map(|item| {
-                        if let NestedMeta::Lit(syn::Lit::Str(s)) = item {
-                            Some(s)
-                        } else {
-                            span_err(
-                                item.span().unwrap(),
-                                "`code(...)` must contain only string literals",
-                            )
-                            .emit();
-                            None
-                        }
-                    })
-                    .collect()
+                let literals = Punctuated::::parse_terminated(&content);
+
+                match literals {
+                    Ok(p) if p.is_empty() => {
+                        span_err(
+                            content.span().unwrap(),
+                            "expected at least one string literal for `code(...)`",
+                        )
+                        .emit();
+                        vec![]
+                    }
+                    Ok(p) => p.into_iter().collect(),
+                    Err(_) => {
+                        span_err(
+                            content.span().unwrap(),
+                            "`code(...)` must contain only string literals",
+                        )
+                        .emit();
+                        vec![]
+                    }
+                }
             }
-        }
-        _ => {
-            span_err(
-                meta.span().unwrap(),
-                r#"`code = "..."`/`code(...)` must contain only string literals"#,
-            )
-            .emit();
-            vec![]
-        }
+        };
+
+        Ok(values)
+    })() {
+        Ok(x) => x,
+        Err(e) => return e.into_compile_error(),
     };
 
     if let AllowMultipleAlternatives::Yes = allow_multiple {
@@ -601,11 +601,9 @@ impl SubdiagnosticKind {
 
         let span = attr.span().unwrap();
 
-        let name = attr.path.segments.last().unwrap().ident.to_string();
+        let name = attr.path().segments.last().unwrap().ident.to_string();
         let name = name.as_str();
 
-        let meta = attr.parse_meta()?;
-
         let mut kind = match name {
             "label" => SubdiagnosticKind::Label,
             "note" => SubdiagnosticKind::Note,
@@ -618,7 +616,7 @@ impl SubdiagnosticKind {
                     name.strip_prefix("suggestion").and_then(SuggestionKind::from_suffix)
                 {
                     if suggestion_kind != SuggestionKind::Normal {
-                        invalid_attr(attr, &meta)
+                        invalid_attr(attr)
                             .help(format!(
                                 r#"Use `#[suggestion(..., style = "{suggestion_kind}")]` instead"#
                             ))
@@ -635,7 +633,7 @@ impl SubdiagnosticKind {
                     name.strip_prefix("multipart_suggestion").and_then(SuggestionKind::from_suffix)
                 {
                     if suggestion_kind != SuggestionKind::Normal {
-                        invalid_attr(attr, &meta)
+                        invalid_attr(attr)
                             .help(format!(
                                 r#"Use `#[multipart_suggestion(..., style = "{suggestion_kind}")]` instead"#
                             ))
@@ -647,16 +645,16 @@ impl SubdiagnosticKind {
                         applicability: None,
                     }
                 } else {
-                    throw_invalid_attr!(attr, &meta);
+                    throw_invalid_attr!(attr);
                 }
             }
         };
 
-        let nested = match meta {
-            Meta::List(MetaList { ref nested, .. }) => {
+        let list = match &attr.meta {
+            Meta::List(list) => {
                 // An attribute with properties, such as `#[suggestion(code = "...")]` or
                 // `#[error(some::slug)]`
-                nested
+                list
             }
             Meta::Path(_) => {
                 // An attribute without a slug or other properties, such as `#[note]` - return
@@ -678,52 +676,51 @@ impl SubdiagnosticKind {
                 }
             }
             _ => {
-                throw_invalid_attr!(attr, &meta)
+                throw_invalid_attr!(attr)
             }
         };
 
         let mut code = None;
         let mut suggestion_kind = None;
 
-        let mut nested_iter = nested.into_iter().peekable();
+        let mut first = true;
+        let mut slug = None;
 
-        // Peek at the first nested attribute: if it's a slug path, consume it.
-        let slug = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() {
-            let path = path.clone();
-            // Advance the iterator.
-            nested_iter.next();
-            Some(path)
-        } else {
-            None
-        };
-
-        for nested_attr in nested_iter {
-            let meta = match nested_attr {
-                NestedMeta::Meta(ref meta) => meta,
-                NestedMeta::Lit(_) => {
-                    invalid_nested_attr(attr, nested_attr).emit();
-                    continue;
+        list.parse_nested_meta(|nested| {
+            if nested.input.is_empty() || nested.input.peek(Token![,]) {
+                if first {
+                    slug = Some(nested.path);
+                } else {
+                    span_err(nested.input.span().unwrap(), "a diagnostic slug must be the first argument to the attribute").emit();
                 }
-            };
 
-            let span = meta.span().unwrap();
-            let nested_name = meta.path().segments.last().unwrap().ident.to_string();
+                first = false;
+                return Ok(());
+            }
+
+            first = false;
+
+            let nested_name = nested.path.segments.last().unwrap().ident.to_string();
             let nested_name = nested_name.as_str();
 
-            let string_value = match meta {
-                Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value),
+            let path_span = nested.path.span().unwrap();
+            let val_span = nested.input.span().unwrap();
 
-                Meta::Path(_) => throw_invalid_nested_attr!(attr, nested_attr, |diag| {
-                    diag.help("a diagnostic slug must be the first argument to the attribute")
-                }),
-                _ => None,
-            };
+            macro get_string() {
+                {
+                    let Ok(value) = nested.value().and_then(|x| x.parse::()) else {
+                        span_err(val_span, "expected `= \"xxx\"`").emit();
+                        return Ok(());
+                    };
+                    value
+                }
+            }
 
             match (nested_name, &mut kind) {
                 ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => {
                     let code_init = build_suggestion_code(
                         code_field,
-                        meta,
+                        nested,
                         fields,
                         AllowMultipleAlternatives::Yes,
                     );
@@ -734,13 +731,9 @@ impl SubdiagnosticKind {
                     SubdiagnosticKind::Suggestion { ref mut applicability, .. }
                     | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. },
                 ) => {
-                    let Some(value) = string_value else {
-                        invalid_nested_attr(attr, nested_attr).emit();
-                        continue;
-                    };
-
+                    let value = get_string!();
                     let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| {
-                        span_err(span, "invalid applicability").emit();
+                        span_err(value.span().unwrap(), "invalid applicability").emit();
                         Applicability::Unspecified
                     });
                     applicability.set_once(value, span);
@@ -750,10 +743,7 @@ impl SubdiagnosticKind {
                     SubdiagnosticKind::Suggestion { .. }
                     | SubdiagnosticKind::MultipartSuggestion { .. },
                 ) => {
-                    let Some(value) = string_value else {
-                        invalid_nested_attr(attr, nested_attr).emit();
-                        continue;
-                    };
+                    let value = get_string!();
 
                     let value = value.value().parse().unwrap_or_else(|()| {
                         span_err(value.span().unwrap(), "invalid suggestion style")
@@ -767,22 +757,24 @@ impl SubdiagnosticKind {
 
                 // Invalid nested attribute
                 (_, SubdiagnosticKind::Suggestion { .. }) => {
-                    invalid_nested_attr(attr, nested_attr)
+                    span_err(path_span, "invalid nested attribute")
                         .help(
                             "only `style`, `code` and `applicability` are valid nested attributes",
                         )
                         .emit();
                 }
                 (_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
-                    invalid_nested_attr(attr, nested_attr)
+                    span_err(path_span, "invalid nested attribute")
                         .help("only `style` and `applicability` are valid nested attributes")
-                        .emit()
+                        .emit();
                 }
                 _ => {
-                    invalid_nested_attr(attr, nested_attr).emit();
+                    span_err(path_span, "invalid nested attribute").emit();
                 }
             }
-        }
+
+            Ok(())
+        })?;
 
         match kind {
             SubdiagnosticKind::Suggestion {
@@ -845,5 +837,5 @@ pub(super) fn should_generate_set_arg(field: &Field) -> bool {
 }
 
 pub(super) fn is_doc_comment(attr: &Attribute) -> bool {
-    attr.path.segments.last().unwrap().ident == "doc"
+    attr.path().segments.last().unwrap().ident == "doc"
 }
diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs
index 63bdcea87f81..75a2f7009c25 100644
--- a/compiler/rustc_macros/src/hash_stable.rs
+++ b/compiler/rustc_macros/src/hash_stable.rs
@@ -1,6 +1,6 @@
 use proc_macro2::{self, Ident};
 use quote::quote;
-use syn::{self, parse_quote, Meta, NestedMeta};
+use syn::{self, parse_quote};
 
 struct Attributes {
     ignore: bool,
@@ -10,32 +10,29 @@ struct Attributes {
 fn parse_attributes(field: &syn::Field) -> Attributes {
     let mut attrs = Attributes { ignore: false, project: None };
     for attr in &field.attrs {
-        if let Ok(meta) = attr.parse_meta() {
-            if !meta.path().is_ident("stable_hasher") {
-                continue;
+        let meta = &attr.meta;
+        if !meta.path().is_ident("stable_hasher") {
+            continue;
+        }
+        let mut any_attr = false;
+        let _ = attr.parse_nested_meta(|nested| {
+            if nested.path.is_ident("ignore") {
+                attrs.ignore = true;
+                any_attr = true;
             }
-            let mut any_attr = false;
-            if let Meta::List(list) = meta {
-                for nested in list.nested.iter() {
-                    if let NestedMeta::Meta(meta) = nested {
-                        if meta.path().is_ident("ignore") {
-                            attrs.ignore = true;
-                            any_attr = true;
-                        }
-                        if meta.path().is_ident("project") {
-                            if let Meta::List(list) = meta {
-                                if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() {
-                                    attrs.project = meta.path().get_ident().cloned();
-                                    any_attr = true;
-                                }
-                            }
-                        }
+            if nested.path.is_ident("project") {
+                let _ = nested.parse_nested_meta(|meta| {
+                    if attrs.project.is_none() {
+                        attrs.project = meta.path.get_ident().cloned();
                     }
-                }
-            }
-            if !any_attr {
-                panic!("error parsing stable_hasher");
+                    any_attr = true;
+                    Ok(())
+                });
             }
+            Ok(())
+        });
+        if !any_attr {
+            panic!("error parsing stable_hasher");
         }
     }
     attrs
diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs
index 89ea89cf502e..04e762e91de3 100644
--- a/compiler/rustc_macros/src/newtype.rs
+++ b/compiler/rustc_macros/src/newtype.rs
@@ -25,7 +25,7 @@ impl Parse for Newtype {
         let mut encodable = true;
         let mut ord = true;
 
-        attrs.retain(|attr| match attr.path.get_ident() {
+        attrs.retain(|attr| match attr.path().get_ident() {
             Some(ident) => match &*ident.to_string() {
                 "custom_encodable" => {
                     encodable = false;
@@ -36,22 +36,22 @@ impl Parse for Newtype {
                     false
                 }
                 "max" => {
-                    let Ok(Meta::NameValue(literal) )= attr.parse_meta() else {
+                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else {
                         panic!("#[max = NUMBER] attribute requires max value");
                     };
 
-                    if let Some(old) = max.replace(literal.lit) {
+                    if let Some(old) = max.replace(lit.lit.clone()) {
                         panic!("Specified multiple max: {old:?}");
                     }
 
                     false
                 }
                 "debug_format" => {
-                    let Ok(Meta::NameValue(literal) )= attr.parse_meta() else {
+                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. } ) = &attr.meta else {
                         panic!("#[debug_format = FMT] attribute requires a format");
                     };
 
-                    if let Some(old) = debug_format.replace(literal.lit) {
+                    if let Some(old) = debug_format.replace(lit.lit.clone()) {
                         panic!("Specified multiple debug format options: {old:?}");
                     }
 
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 08e42a8a08f9..f85ba38003c1 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -15,7 +15,7 @@ mod kw {
 /// Ensures only doc comment attributes are used
 fn check_attributes(attrs: Vec) -> Result> {
     let inner = |attr: Attribute| {
-        if !attr.path.is_ident("doc") {
+        if !attr.path().is_ident("doc") {
             Err(Error::new(attr.span(), "attributes not supported on queries"))
         } else if attr.style != AttrStyle::Outer {
             Err(Error::new(
@@ -48,7 +48,7 @@ impl Parse for Query {
         let name: Ident = input.parse()?;
         let arg_content;
         parenthesized!(arg_content in input);
-        let key = arg_content.parse()?;
+        let key = Pat::parse_single(&arg_content)?;
         arg_content.parse::()?;
         let arg = arg_content.parse()?;
         let result = input.parse()?;
@@ -158,7 +158,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result {
             } else {
                 None
             };
-            let list = attr_content.parse_terminated(Expr::parse)?;
+            let list = attr_content.parse_terminated(Expr::parse, Token![,])?;
             try_insert!(desc = (tcx, list));
         } else if modifier == "cache_on_disk_if" {
             // Parse a cache modifier like:
@@ -166,7 +166,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result {
             let args = if input.peek(token::Paren) {
                 let args;
                 parenthesized!(args in input);
-                let tcx = args.parse()?;
+                let tcx = Pat::parse_single(&args)?;
                 Some(tcx)
             } else {
                 None
diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs
index 388e254cd645..5ee4d8793135 100644
--- a/compiler/rustc_macros/src/type_foldable.rs
+++ b/compiler/rustc_macros/src/type_foldable.rs
@@ -1,5 +1,5 @@
 use quote::{quote, ToTokens};
-use syn::{parse_quote, Attribute, Meta, NestedMeta};
+use syn::parse_quote;
 
 pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
@@ -17,21 +17,20 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
         vi.construct(|_, index| {
             let bind = &bindings[index];
 
+            let mut fixed = false;
+
             // retain value of fields with #[type_foldable(identity)]
-            let fixed = bind
-                .ast()
-                .attrs
-                .iter()
-                .map(Attribute::parse_meta)
-                .filter_map(Result::ok)
-                .flat_map(|attr| match attr {
-                    Meta::List(list) if list.path.is_ident("type_foldable") => list.nested,
-                    _ => Default::default(),
-                })
-                .any(|nested| match nested {
-                    NestedMeta::Meta(Meta::Path(path)) => path.is_ident("identity"),
-                    _ => false,
+            bind.ast().attrs.iter().for_each(|x| {
+                if !x.path().is_ident("type_foldable") {
+                    return;
+                }
+                let _ = x.parse_nested_meta(|nested| {
+                    if nested.path.is_ident("identity") {
+                        fixed = true;
+                    }
+                    Ok(())
                 });
+            });
 
             if fixed {
                 bind.to_token_stream()
diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs
index f6f4c4779c30..dcd505a105e5 100644
--- a/compiler/rustc_macros/src/type_visitable.rs
+++ b/compiler/rustc_macros/src/type_visitable.rs
@@ -1,5 +1,5 @@
 use quote::quote;
-use syn::{parse_quote, Attribute, Meta, NestedMeta};
+use syn::parse_quote;
 
 pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
@@ -8,19 +8,21 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
 
     // ignore fields with #[type_visitable(ignore)]
     s.filter(|bi| {
-        !bi.ast()
-            .attrs
-            .iter()
-            .map(Attribute::parse_meta)
-            .filter_map(Result::ok)
-            .flat_map(|attr| match attr {
-                Meta::List(list) if list.path.is_ident("type_visitable") => list.nested,
-                _ => Default::default(),
-            })
-            .any(|nested| match nested {
-                NestedMeta::Meta(Meta::Path(path)) => path.is_ident("ignore"),
-                _ => false,
-            })
+        let mut ignored = false;
+
+        bi.ast().attrs.iter().for_each(|attr| {
+            if !attr.path().is_ident("type_visitable") {
+                return;
+            }
+            let _ = attr.parse_nested_meta(|nested| {
+                if nested.path.is_ident("ignore") {
+                    ignored = true;
+                }
+                Ok(())
+            });
+        });
+
+        !ignored
     });
 
     if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {

From fc01b4b63c5336a0f296b049525e18798b95b374 Mon Sep 17 00:00:00 2001
From: Deadbeef 
Date: Mon, 3 Apr 2023 14:36:50 +0000
Subject: [PATCH 154/267] fix and bless ui tests 1/2

---
 .../src/diagnostics/diagnostic_builder.rs     |   7 +-
 .../rustc_macros/src/diagnostics/utils.rs     |  13 +
 .../session-diagnostic/diagnostic-derive.rs   |  44 ++-
 .../diagnostic-derive.stderr                  | 313 ++++++++----------
 .../subdiagnostic-derive.stderr               | 184 +++++-----
 5 files changed, 289 insertions(+), 272 deletions(-)

diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index fb75d87f8d2e..9b91627883a8 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -214,10 +214,15 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                 if path.is_ident("code") {
                     self.code.set_once((), path.span().unwrap());
 
-                    let code = nested.parse::()?;
+                    let code = nested.parse::()?;
                     tokens.extend(quote! {
                         #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
                     });
+                } else {
+                    span_err(path.span().unwrap(), "unknown argument").note("only the `code` parameter is valid after the slug").emit();
+
+                    // consume the buffer so we don't have syntax errors from syn
+                    let _ = nested.parse::();
                 }
                 Ok(())
             })?;
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 38292df6d854..bc104941c380 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -716,6 +716,9 @@ impl SubdiagnosticKind {
                 }
             }
 
+            let mut has_errors = false;
+            let input = nested.input;
+
             match (nested_name, &mut kind) {
                 ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => {
                     let code_init = build_suggestion_code(
@@ -734,6 +737,7 @@ impl SubdiagnosticKind {
                     let value = get_string!();
                     let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| {
                         span_err(value.span().unwrap(), "invalid applicability").emit();
+                        has_errors = true;
                         Applicability::Unspecified
                     });
                     applicability.set_once(value, span);
@@ -749,6 +753,7 @@ impl SubdiagnosticKind {
                         span_err(value.span().unwrap(), "invalid suggestion style")
                             .help("valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`")
                             .emit();
+                        has_errors = true;
                         SuggestionKind::Normal
                     });
 
@@ -762,17 +767,25 @@ impl SubdiagnosticKind {
                             "only `style`, `code` and `applicability` are valid nested attributes",
                         )
                         .emit();
+                    has_errors = true;
                 }
                 (_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
                     span_err(path_span, "invalid nested attribute")
                         .help("only `style` and `applicability` are valid nested attributes")
                         .emit();
+                    has_errors = true;
                 }
                 _ => {
                     span_err(path_span, "invalid nested attribute").emit();
+                    has_errors = true;
                 }
             }
 
+            if has_errors {
+                // Consume the rest of the input to avoid spamming errors
+                let _ = input.parse::();
+            }
+
             Ok(())
         })?;
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 3151c712566a..61724c11745c 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -50,7 +50,7 @@ enum DiagnosticOnEnum {
 #[derive(Diagnostic)]
 #[diag(no_crate_example, code = "E0123")]
 #[diag = "E0123"]
-//~^ ERROR `#[diag = ...]` is not a valid attribute
+//~^ ERROR expected parentheses: #[diag(...)]
 struct WrongStructAttrStyle {}
 
 #[derive(Diagnostic)]
@@ -62,8 +62,7 @@ struct InvalidStructAttr {}
 
 #[derive(Diagnostic)]
 #[diag("E0123")]
-//~^ ERROR `#[diag("...")]` is not a valid attribute
-//~^^ ERROR diagnostic slug not specified
+//~^ ERROR diagnostic slug not specified
 struct InvalidLitNestedAttr {}
 
 #[derive(Diagnostic)]
@@ -73,27 +72,25 @@ struct InvalidNestedStructAttr {}
 
 #[derive(Diagnostic)]
 #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
-//~^ ERROR `#[diag(nonsense(...))]` is not a valid attribute
-//~^^ ERROR diagnostic slug not specified
+//~^ ERROR diagnostic slug must be the first argument
+//~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr1 {}
 
 #[derive(Diagnostic)]
 #[diag(nonsense = "...", code = "E0123", slug = "foo")]
-//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
-//~| ERROR `#[diag(slug = ...)]` is not a valid attribute
+//~^ ERROR unknown argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr2 {}
 
 #[derive(Diagnostic)]
 #[diag(nonsense = 4, code = "E0123", slug = "foo")]
-//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
-//~| ERROR `#[diag(slug = ...)]` is not a valid attribute
+//~^ ERROR unknown argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr3 {}
 
 #[derive(Diagnostic)]
 #[diag(no_crate_example, code = "E0123", slug = "foo")]
-//~^ ERROR `#[diag(slug = ...)]` is not a valid attribute
+//~^ ERROR unknown argument
 struct InvalidNestedStructAttr4 {}
 
 #[derive(Diagnostic)]
@@ -118,7 +115,7 @@ struct CodeSpecifiedTwice {}
 
 #[derive(Diagnostic)]
 #[diag(no_crate_example, no_crate::example, code = "E0456")]
-//~^ ERROR `#[diag(no_crate::example)]` is not a valid attribute
+//~^ ERROR diagnostic slug must be the first argument
 struct SlugSpecifiedTwice {}
 
 #[derive(Diagnostic)]
@@ -232,7 +229,7 @@ struct SuggestWithoutCode {
 #[diag(no_crate_example, code = "E0123")]
 struct SuggestWithBadKey {
     #[suggestion(nonsense = "bar")]
-    //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
+    //~^ ERROR invalid nested attribute
     //~| ERROR suggestion without `code = "..."`
     suggestion: (Span, Applicability),
 }
@@ -241,7 +238,7 @@ struct SuggestWithBadKey {
 #[diag(no_crate_example, code = "E0123")]
 struct SuggestWithShorthandMsg {
     #[suggestion(msg = "bar")]
-    //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
+    //~^ ERROR invalid nested attribute
     //~| ERROR suggestion without `code = "..."`
     suggestion: (Span, Applicability),
 }
@@ -530,7 +527,7 @@ struct BoolField {
 #[diag(no_crate_example, code = "E0123")]
 struct LabelWithTrailingPath {
     #[label(no_crate_label, foo)]
-    //~^ ERROR `#[label(foo)]` is not a valid attribute
+    //~^ ERROR a diagnostic slug must be the first argument to the attribute
     span: Span,
 }
 
@@ -538,7 +535,7 @@ struct LabelWithTrailingPath {
 #[diag(no_crate_example, code = "E0123")]
 struct LabelWithTrailingNameValue {
     #[label(no_crate_label, foo = "...")]
-    //~^ ERROR `#[label(foo = ...)]` is not a valid attribute
+    //~^ ERROR invalid nested attribute
     span: Span,
 }
 
@@ -546,7 +543,7 @@ struct LabelWithTrailingNameValue {
 #[diag(no_crate_example, code = "E0123")]
 struct LabelWithTrailingList {
     #[label(no_crate_label, foo("..."))]
-    //~^ ERROR `#[label(foo(...))]` is not a valid attribute
+    //~^ ERROR invalid nested attribute
     span: Span,
 }
 
@@ -643,8 +640,8 @@ struct MissingCodeInSuggestion {
 //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
 //~| ERROR cannot find attribute `multipart_suggestion` in this scope
 #[multipart_suggestion()]
-//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
-//~| ERROR cannot find attribute `multipart_suggestion` in this scope
+//~^ ERROR cannot find attribute `multipart_suggestion` in this scope
+//~| ERROR unexpected end of input, unexpected token in nested attribute, expected ident
 struct MultipartSuggestion {
     #[multipart_suggestion(no_crate_suggestion)]
     //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
@@ -698,7 +695,7 @@ struct RawIdentDiagnosticArg {
 #[diag(no_crate_example)]
 struct SubdiagnosticBad {
     #[subdiagnostic(bad)]
-    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
+    //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
     note: Note,
 }
 
@@ -714,7 +711,7 @@ struct SubdiagnosticBadStr {
 #[diag(no_crate_example)]
 struct SubdiagnosticBadTwice {
     #[subdiagnostic(bad, bad)]
-    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
+    //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
     note: Note,
 }
 
@@ -722,7 +719,7 @@ struct SubdiagnosticBadTwice {
 #[diag(no_crate_example)]
 struct SubdiagnosticBadLitStr {
     #[subdiagnostic("bad")]
-    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
+    //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
     note: Note,
 }
 
@@ -797,14 +794,15 @@ struct SuggestionsNoItem {
 struct SuggestionsInvalidItem {
     #[suggestion(code(foo))]
     //~^ ERROR `code(...)` must contain only string literals
+    //~| ERROR unexpected token
     sub: Span,
 }
 
-#[derive(Diagnostic)]
+#[derive(Diagnostic)] //~ ERROR cannot find value `__code_34` in this scope
 #[diag(no_crate_example)]
 struct SuggestionsInvalidLiteral {
     #[suggestion(code = 3)]
-    //~^ ERROR `code = "..."`/`code(...)` must contain only string literals
+    //~^ ERROR expected string literal
     sub: Span,
 }
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 513b675e5dd4..041ebdee0ab8 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -20,11 +20,11 @@ LL |     Bar,
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:52:1
+error: expected parentheses: #[diag(...)]
+  --> $DIR/diagnostic-derive.rs:52:8
    |
 LL | #[diag = "E0123"]
-   | ^^^^^^^^^^^^^^^^^
+   |        ^
 
 error: `#[nonsense(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:57:1
@@ -44,35 +44,24 @@ LL | | struct InvalidStructAttr {}
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag("...")]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:64:8
-   |
-LL | #[diag("E0123")]
-   |        ^^^^^^^
-   |
-   = help: a diagnostic slug is required as the first argument
-
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:64:1
    |
 LL | / #[diag("E0123")]
 LL | |
-LL | |
 LL | | struct InvalidLitNestedAttr {}
    | |______________________________^
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag(nonsense(...))]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:75:8
+error: diagnostic slug must be the first argument
+  --> $DIR/diagnostic-derive.rs:74:16
    |
 LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
-   |        ^^^^^^^^^^^^^^^
-   |
-   = help: a diagnostic slug is required as the first argument
+   |                ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:75:1
+  --> $DIR/diagnostic-derive.rs:74:1
    |
 LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
 LL | |
@@ -82,120 +71,102 @@ LL | | struct InvalidNestedStructAttr1 {}
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:81:8
+error: unknown argument
+  --> $DIR/diagnostic-derive.rs:80:8
    |
 LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
-   |        ^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^
    |
-   = help: only `code` is a valid nested attributes following the slug
-
-error: `#[diag(slug = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:81:42
-   |
-LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
-   |                                          ^^^^^^^^^^^^
-   |
-   = help: only `code` is a valid nested attributes following the slug
+   = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:81:1
+  --> $DIR/diagnostic-derive.rs:80:1
    |
 LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
 LL | |
 LL | |
-LL | |
 LL | | struct InvalidNestedStructAttr2 {}
    | |__________________________________^
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:88:8
+error: unknown argument
+  --> $DIR/diagnostic-derive.rs:86:8
    |
 LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
-   |        ^^^^^^^^^^^^
-
-error: `#[diag(slug = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:88:38
+   |        ^^^^^^^^
    |
-LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
-   |                                      ^^^^^^^^^^^^
-   |
-   = help: only `code` is a valid nested attributes following the slug
+   = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:88:1
+  --> $DIR/diagnostic-derive.rs:86:1
    |
 LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
 LL | |
 LL | |
-LL | |
 LL | | struct InvalidNestedStructAttr3 {}
    | |__________________________________^
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag(slug = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:95:42
+error: unknown argument
+  --> $DIR/diagnostic-derive.rs:92:42
    |
 LL | #[diag(no_crate_example, code = "E0123", slug = "foo")]
-   |                                          ^^^^^^^^^^^^
+   |                                          ^^^^
    |
-   = help: only `code` is a valid nested attributes following the slug
+   = note: only the `code` parameter is valid after the slug
 
 error: `#[suggestion = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:102:5
+  --> $DIR/diagnostic-derive.rs:99:5
    |
 LL |     #[suggestion = "bar"]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:109:8
+  --> $DIR/diagnostic-derive.rs:106:8
    |
 LL | #[diag(no_crate_example, code = "E0456")]
    |        ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:108:8
+  --> $DIR/diagnostic-derive.rs:105:8
    |
 LL | #[diag(no_crate_example, code = "E0123")]
    |        ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:109:33
+  --> $DIR/diagnostic-derive.rs:106:26
    |
 LL | #[diag(no_crate_example, code = "E0456")]
-   |                                 ^^^^^^^
+   |                          ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:108:33
+  --> $DIR/diagnostic-derive.rs:105:26
    |
 LL | #[diag(no_crate_example, code = "E0123")]
-   |                                 ^^^^^^^
+   |                          ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:115:49
+  --> $DIR/diagnostic-derive.rs:112:42
    |
 LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
-   |                                                 ^^^^^^^
+   |                                          ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:115:33
+  --> $DIR/diagnostic-derive.rs:112:26
    |
 LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
-   |                                 ^^^^^^^
+   |                          ^^^^
 
-error: `#[diag(no_crate::example)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:120:26
+error: diagnostic slug must be the first argument
+  --> $DIR/diagnostic-derive.rs:117:43
    |
 LL | #[diag(no_crate_example, no_crate::example, code = "E0456")]
-   |                          ^^^^^^^^^^^^^^^^^
-   |
-   = help: diagnostic slug must be the first argument
+   |                                           ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:125:1
+  --> $DIR/diagnostic-derive.rs:122:1
    |
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -203,7 +174,7 @@ LL | struct KindNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:128:1
+  --> $DIR/diagnostic-derive.rs:125:1
    |
 LL | / #[diag(code = "E0456")]
 LL | |
@@ -213,31 +184,31 @@ LL | | struct SlugNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:139:5
+  --> $DIR/diagnostic-derive.rs:136:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: `#[nonsense]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:147:5
+  --> $DIR/diagnostic-derive.rs:144:5
    |
 LL |     #[nonsense]
    |     ^^^^^^^^^^^
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:164:5
+  --> $DIR/diagnostic-derive.rs:161:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `name` doesn't refer to a field on this type
-  --> $DIR/diagnostic-derive.rs:172:46
+  --> $DIR/diagnostic-derive.rs:169:46
    |
 LL |     #[suggestion(no_crate_suggestion, code = "{name}")]
    |                                              ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/diagnostic-derive.rs:177:10
+  --> $DIR/diagnostic-derive.rs:174:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ expected `'}'` in format string
@@ -246,7 +217,7 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/diagnostic-derive.rs:187:10
+  --> $DIR/diagnostic-derive.rs:184:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ unmatched `}` in format string
@@ -255,47 +226,47 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:207:5
+  --> $DIR/diagnostic-derive.rs:204:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:226:5
+  --> $DIR/diagnostic-derive.rs:223:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[suggestion(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:234:18
+error: invalid nested attribute
+  --> $DIR/diagnostic-derive.rs:231:18
    |
 LL |     #[suggestion(nonsense = "bar")]
-   |                  ^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^
    |
    = help: only `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:234:5
+  --> $DIR/diagnostic-derive.rs:231:5
    |
 LL |     #[suggestion(nonsense = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[suggestion(msg = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:243:18
+error: invalid nested attribute
+  --> $DIR/diagnostic-derive.rs:240:18
    |
 LL |     #[suggestion(msg = "bar")]
-   |                  ^^^^^^^^^^^
+   |                  ^^^
    |
    = help: only `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:243:5
+  --> $DIR/diagnostic-derive.rs:240:5
    |
 LL |     #[suggestion(msg = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: wrong field type for suggestion
-  --> $DIR/diagnostic-derive.rs:266:5
+  --> $DIR/diagnostic-derive.rs:263:5
    |
 LL | /     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
 LL | |
@@ -305,81 +276,79 @@ LL | |     suggestion: Applicability,
    = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:282:24
+  --> $DIR/diagnostic-derive.rs:279:24
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                        ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:282:18
+  --> $DIR/diagnostic-derive.rs:279:18
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                  ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:290:33
+  --> $DIR/diagnostic-derive.rs:287:33
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                                 ^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:290:18
+  --> $DIR/diagnostic-derive.rs:287:18
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                  ^^^^^^^^^^^^^
 
 error: `#[label = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:297:5
+  --> $DIR/diagnostic-derive.rs:294:5
    |
 LL |     #[label = "bar"]
    |     ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:448:53
+  --> $DIR/diagnostic-derive.rs:445:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
-   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:450:24
+  --> $DIR/diagnostic-derive.rs:447:24
    |
 LL |     suggestion: (Span, Applicability),
    |                        ^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:456:53
+  --> $DIR/diagnostic-derive.rs:453:69
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
-   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                                     ^^^^^^^^
 
 error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `bool` or `()`
-  --> $DIR/diagnostic-derive.rs:523:5
+  --> $DIR/diagnostic-derive.rs:520:5
    |
 LL |     #[help(no_crate_help)]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[label(foo)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:532:29
+error: a diagnostic slug must be the first argument to the attribute
+  --> $DIR/diagnostic-derive.rs:529:32
    |
 LL |     #[label(no_crate_label, foo)]
-   |                             ^^^
-   |
-   = help: a diagnostic slug must be the first argument to the attribute
+   |                                ^
 
-error: `#[label(foo = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:540:29
+error: invalid nested attribute
+  --> $DIR/diagnostic-derive.rs:537:29
    |
 LL |     #[label(no_crate_label, foo = "...")]
-   |                             ^^^^^^^^^^^
+   |                             ^^^
 
-error: `#[label(foo(...))]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:548:29
+error: invalid nested attribute
+  --> $DIR/diagnostic-derive.rs:545:29
    |
 LL |     #[label(no_crate_label, foo("..."))]
-   |                             ^^^^^^^^^^
+   |                             ^^^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:560:5
+  --> $DIR/diagnostic-derive.rs:557:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -387,13 +356,13 @@ LL |     #[primary_span]
    = help: the `primary_span` field attribute is not valid for lint diagnostics
 
 error: `#[error(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:580:1
+  --> $DIR/diagnostic-derive.rs:577:1
    |
 LL | #[error(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:580:1
+  --> $DIR/diagnostic-derive.rs:577:1
    |
 LL | / #[error(no_crate_example, code = "E0123")]
 LL | |
@@ -405,13 +374,13 @@ LL | | struct ErrorAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[warn_(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:587:1
+  --> $DIR/diagnostic-derive.rs:584:1
    |
 LL | #[warn_(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:587:1
+  --> $DIR/diagnostic-derive.rs:584:1
    |
 LL | / #[warn_(no_crate_example, code = "E0123")]
 LL | |
@@ -423,13 +392,13 @@ LL | | struct WarnAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:594:1
+  --> $DIR/diagnostic-derive.rs:591:1
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:594:1
+  --> $DIR/diagnostic-derive.rs:591:1
    |
 LL | / #[lint(no_crate_example, code = "E0123")]
 LL | |
@@ -441,19 +410,19 @@ LL | | struct LintAttributeOnSessionDiag {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:601:1
+  --> $DIR/diagnostic-derive.rs:598:1
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:601:1
+  --> $DIR/diagnostic-derive.rs:598:1
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:601:1
+  --> $DIR/diagnostic-derive.rs:598:1
    |
 LL | / #[lint(no_crate_example, code = "E0123")]
 LL | |
@@ -466,19 +435,19 @@ LL | | struct LintAttributeOnLintDiag {}
    = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:611:53
+  --> $DIR/diagnostic-derive.rs:608:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
-   |                                                     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:611:39
+  --> $DIR/diagnostic-derive.rs:608:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
-   |                                       ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:620:24
+  --> $DIR/diagnostic-derive.rs:617:24
    |
 LL |     suggestion: (Span, usize),
    |                        ^^^^^
@@ -486,7 +455,7 @@ LL |     suggestion: (Span, usize),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:628:17
+  --> $DIR/diagnostic-derive.rs:625:17
    |
 LL |     suggestion: (Span,),
    |                 ^^^^^^^
@@ -494,13 +463,13 @@ LL |     suggestion: (Span,),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:635:5
+  --> $DIR/diagnostic-derive.rs:632:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:642:1
+  --> $DIR/diagnostic-derive.rs:639:1
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -508,23 +477,21 @@ LL | #[multipart_suggestion(no_crate_suggestion)]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:645:1
-   |
-LL | #[multipart_suggestion()]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider creating a `Subdiagnostic` instead
-
-error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:649:5
+  --> $DIR/diagnostic-derive.rs:646:5
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider creating a `Subdiagnostic` instead
 
+error: unexpected end of input, unexpected token in nested attribute, expected ident
+  --> $DIR/diagnostic-derive.rs:642:24
+   |
+LL | #[multipart_suggestion()]
+   |                        ^
+
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:657:1
+  --> $DIR/diagnostic-derive.rs:654:1
    |
 LL | #[suggestion(no_crate_suggestion, code = "...")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -532,45 +499,39 @@ LL | #[suggestion(no_crate_suggestion, code = "...")]
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
 error: `#[label]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:666:1
+  --> $DIR/diagnostic-derive.rs:663:1
    |
 LL | #[label]
    | ^^^^^^^^
    |
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
-error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:700:5
+error: `eager` is the only supported nested attribute for `subdiagnostic`
+  --> $DIR/diagnostic-derive.rs:697:7
    |
 LL |     #[subdiagnostic(bad)]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   |       ^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:708:5
+  --> $DIR/diagnostic-derive.rs:705:5
    |
 LL |     #[subdiagnostic = "bad"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:716:5
+error: `eager` is the only supported nested attribute for `subdiagnostic`
+  --> $DIR/diagnostic-derive.rs:713:7
    |
 LL |     #[subdiagnostic(bad, bad)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   |       ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:724:5
+error: `eager` is the only supported nested attribute for `subdiagnostic`
+  --> $DIR/diagnostic-derive.rs:721:7
    |
 LL |     #[subdiagnostic("bad")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   |       ^^^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:732:5
+  --> $DIR/diagnostic-derive.rs:729:5
    |
 LL |     #[subdiagnostic(eager)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -578,25 +539,31 @@ LL |     #[subdiagnostic(eager)]
    = help: eager subdiagnostics are not supported on lints
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:790:18
+  --> $DIR/diagnostic-derive.rs:787:23
    |
 LL |     #[suggestion(code())]
-   |                  ^^^^^^
+   |                       ^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:798:23
+  --> $DIR/diagnostic-derive.rs:795:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
-error: `code = "..."`/`code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:806:18
+error: unexpected token
+  --> $DIR/diagnostic-derive.rs:795:23
+   |
+LL |     #[suggestion(code(foo))]
+   |                       ^^^
+
+error: expected string literal
+  --> $DIR/diagnostic-derive.rs:804:25
    |
 LL |     #[suggestion(code = 3)]
-   |                  ^^^^^^^^
+   |                         ^
 
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:821:5
+  --> $DIR/diagnostic-derive.rs:819:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -612,61 +579,69 @@ LL | #[nonsense(no_crate_example, code = "E0123")]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:147:7
+  --> $DIR/diagnostic-derive.rs:144:7
    |
 LL |     #[nonsense]
    |       ^^^^^^^^
 
 error: cannot find attribute `error` in this scope
-  --> $DIR/diagnostic-derive.rs:580:3
+  --> $DIR/diagnostic-derive.rs:577:3
    |
 LL | #[error(no_crate_example, code = "E0123")]
    |   ^^^^^
 
 error: cannot find attribute `warn_` in this scope
-  --> $DIR/diagnostic-derive.rs:587:3
+  --> $DIR/diagnostic-derive.rs:584:3
    |
 LL | #[warn_(no_crate_example, code = "E0123")]
    |   ^^^^^ help: a built-in attribute with a similar name exists: `warn`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:594:3
+  --> $DIR/diagnostic-derive.rs:591:3
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:601:3
+  --> $DIR/diagnostic-derive.rs:598:3
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:642:3
+  --> $DIR/diagnostic-derive.rs:639:3
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:645:3
+  --> $DIR/diagnostic-derive.rs:642:3
    |
 LL | #[multipart_suggestion()]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:649:7
+  --> $DIR/diagnostic-derive.rs:646:7
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |       ^^^^^^^^^^^^^^^^^^^^
 
 error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated`
-  --> $DIR/diagnostic-derive.rs:70:8
+  --> $DIR/diagnostic-derive.rs:69:8
    |
 LL | #[diag(nonsense, code = "E0123")]
    |        ^^^^^^^^ not found in `crate::fluent_generated`
 
+error[E0425]: cannot find value `__code_34` in this scope
+  --> $DIR/diagnostic-derive.rs:801:10
+   |
+LL | #[derive(Diagnostic)]
+   |          ^^^^^^^^^^ not found in this scope
+   |
+   = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-  --> $DIR/diagnostic-derive.rs:341:10
+  --> $DIR/diagnostic-derive.rs:338:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
@@ -676,7 +651,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
   --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
    = note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 85 previous errors
+error: aborting due to 84 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index 343134af6bc1..d8bf0ba413cc 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -26,11 +26,11 @@ error: `#[label = ...]` is not a valid attribute
 LL | #[label = "..."]
    | ^^^^^^^^^^^^^^^^
 
-error: `#[label(bug = ...)]` is not a valid attribute
+error: invalid nested attribute
   --> $DIR/subdiagnostic-derive.rs:84:9
    |
 LL | #[label(bug = "...")]
-   |         ^^^^^^^^^^^
+   |         ^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
   --> $DIR/subdiagnostic-derive.rs:84:1
@@ -38,23 +38,17 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
 LL | #[label(bug = "...")]
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[label("...")]` is not a valid attribute
+error: unexpected literal in nested attribute, expected ident
   --> $DIR/subdiagnostic-derive.rs:94:9
    |
 LL | #[label("...")]
    |         ^^^^^
 
-error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:94:1
-   |
-LL | #[label("...")]
-   | ^^^^^^^^^^^^^^^
-
-error: `#[label(slug = ...)]` is not a valid attribute
+error: invalid nested attribute
   --> $DIR/subdiagnostic-derive.rs:104:9
    |
 LL | #[label(slug = 4)]
-   |         ^^^^^^^^
+   |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
   --> $DIR/subdiagnostic-derive.rs:104:1
@@ -62,11 +56,11 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
 LL | #[label(slug = 4)]
    | ^^^^^^^^^^^^^^^^^^
 
-error: `#[label(slug(...))]` is not a valid attribute
+error: invalid nested attribute
   --> $DIR/subdiagnostic-derive.rs:114:9
    |
 LL | #[label(slug("..."))]
-   |         ^^^^^^^^^^^
+   |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
   --> $DIR/subdiagnostic-derive.rs:114:1
@@ -74,23 +68,23 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
 LL | #[label(slug("..."))]
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:134:1
+error: unexpected end of input, unexpected token in nested attribute, expected ident
+  --> $DIR/subdiagnostic-derive.rs:134:9
    |
 LL | #[label()]
-   | ^^^^^^^^^^
+   |         ^
 
-error: `#[label(code = ...)]` is not a valid attribute
+error: invalid nested attribute
   --> $DIR/subdiagnostic-derive.rs:143:27
    |
 LL | #[label(no_crate_example, code = "...")]
-   |                           ^^^^^^^^^^^^
+   |                           ^^^^
 
-error: `#[label(applicability = ...)]` is not a valid attribute
+error: invalid nested attribute
   --> $DIR/subdiagnostic-derive.rs:152:27
    |
 LL | #[label(no_crate_example, applicability = "machine-applicable")]
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                           ^^^^^^^^^^^^^
 
 error: unsupported type attribute for subdiagnostic enum
   --> $DIR/subdiagnostic-derive.rs:161:1
@@ -122,11 +116,11 @@ error: `#[bar(...)]` is not a valid attribute
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
 
-error: `#[label(code = ...)]` is not a valid attribute
+error: invalid nested attribute
   --> $DIR/subdiagnostic-derive.rs:223:13
    |
 LL |     #[label(code = "...")]
-   |             ^^^^^^^^^^^^
+   |             ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
   --> $DIR/subdiagnostic-derive.rs:223:5
@@ -190,13 +184,11 @@ LL | |     b: u64,
 LL | | }
    | |_^
 
-error: `#[label(no_crate::example)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:325:27
+error: a diagnostic slug must be the first argument to the attribute
+  --> $DIR/subdiagnostic-derive.rs:325:44
    |
 LL | #[label(no_crate_example, no_crate::example)]
-   |                           ^^^^^^^^^^^^^^^^^
-   |
-   = help: a diagnostic slug must be the first argument to the attribute
+   |                                            ^
 
 error: specified multiple times
   --> $DIR/subdiagnostic-derive.rs:338:5
@@ -217,16 +209,16 @@ LL | struct AG {
    |        ^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:381:46
+  --> $DIR/subdiagnostic-derive.rs:381:1
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
-   |                                              ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:381:32
+  --> $DIR/subdiagnostic-derive.rs:381:1
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
-   |                                ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
   --> $DIR/subdiagnostic-derive.rs:399:5
@@ -253,10 +245,10 @@ LL | #[suggestion(no_crate_example)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/subdiagnostic-derive.rs:432:46
+  --> $DIR/subdiagnostic-derive.rs:432:62
    |
 LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")]
-   |                                              ^^^^^^^^^^^^^^^^^^^^^
+   |                                                              ^^^^^
 
 error: suggestion without `#[primary_span]` field
   --> $DIR/subdiagnostic-derive.rs:450:1
@@ -314,11 +306,11 @@ LL | |     var: String,
 LL | | }
    | |_^
 
-error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
+error: invalid nested attribute
   --> $DIR/subdiagnostic-derive.rs:538:42
    |
 LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
-   |                                          ^^^^^^^^^^^^
+   |                                          ^^^^
    |
    = help: only `style` and `applicability` are valid nested attributes
 
@@ -339,11 +331,11 @@ error: `#[suggestion_part(...)]` attribute without `code = "..."`
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
-error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:556:5
+error: unexpected end of input, unexpected token in nested attribute, expected ident
+  --> $DIR/subdiagnostic-derive.rs:556:23
    |
 LL |     #[suggestion_part()]
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |                       ^
 
 error: `#[primary_span]` is not a valid attribute
   --> $DIR/subdiagnostic-derive.rs:565:5
@@ -371,19 +363,11 @@ error: `#[suggestion_part(...)]` attribute without `code = "..."`
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
-error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:576:5
-   |
-LL |     #[suggestion_part()]
-   |     ^^^^^^^^^^^^^^^^^^^^
-
-error: `#[suggestion_part(foo = ...)]` is not a valid attribute
+error: `code` is the only valid nested attribute
   --> $DIR/subdiagnostic-derive.rs:579:23
    |
 LL |     #[suggestion_part(foo = "bar")]
-   |                       ^^^^^^^^^^^
-   |
-   = help: `code` is the only valid nested attribute
+   |                       ^^^
 
 error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
   --> $DIR/subdiagnostic-derive.rs:582:5
@@ -397,17 +381,29 @@ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of
 LL |     #[suggestion_part()]
    |     ^^^^^^^^^^^^^^^^^^^^
 
+error: unexpected end of input, unexpected token in nested attribute, expected ident
+  --> $DIR/subdiagnostic-derive.rs:576:23
+   |
+LL |     #[suggestion_part()]
+   |                       ^
+
+error: expected `,`
+  --> $DIR/subdiagnostic-derive.rs:579:27
+   |
+LL |     #[suggestion_part(foo = "bar")]
+   |                           ^
+
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:593:37
+  --> $DIR/subdiagnostic-derive.rs:593:5
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
-   |                                     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:593:23
+  --> $DIR/subdiagnostic-derive.rs:593:5
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
-   |                       ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
   --> $DIR/subdiagnostic-derive.rs:622:5
@@ -416,46 +412,64 @@ LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:670:23
+  --> $DIR/subdiagnostic-derive.rs:670:34
    |
 LL |     #[suggestion_part(code("foo"))]
-   |                       ^^^^^^^^^^^
+   |                                  ^
+
+error: unexpected token
+  --> $DIR/subdiagnostic-derive.rs:670:28
+   |
+LL |     #[suggestion_part(code("foo"))]
+   |                            ^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:679:23
+  --> $DIR/subdiagnostic-derive.rs:679:41
    |
 LL |     #[suggestion_part(code("foo", "bar"))]
-   |                       ^^^^^^^^^^^^^^^^^^
+   |                                         ^
+
+error: unexpected token
+  --> $DIR/subdiagnostic-derive.rs:679:28
+   |
+LL |     #[suggestion_part(code("foo", "bar"))]
+   |                            ^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:688:23
+  --> $DIR/subdiagnostic-derive.rs:688:30
    |
 LL |     #[suggestion_part(code(3))]
-   |                       ^^^^^^^
+   |                              ^
+
+error: unexpected token
+  --> $DIR/subdiagnostic-derive.rs:688:28
+   |
+LL |     #[suggestion_part(code(3))]
+   |                            ^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:697:23
+  --> $DIR/subdiagnostic-derive.rs:697:29
    |
 LL |     #[suggestion_part(code())]
-   |                       ^^^^^^
+   |                             ^
 
-error: `code = "..."`/`code(...)` must contain only string literals
-  --> $DIR/subdiagnostic-derive.rs:706:23
+error: expected string literal
+  --> $DIR/subdiagnostic-derive.rs:706:30
    |
 LL |     #[suggestion_part(code = 3)]
-   |                       ^^^^^^^^
+   |                              ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:748:61
+  --> $DIR/subdiagnostic-derive.rs:748:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
-   |                                                             ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:748:43
+  --> $DIR/subdiagnostic-derive.rs:748:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
-   |                                           ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion_hidden(...)]` is not a valid attribute
   --> $DIR/subdiagnostic-derive.rs:757:1
@@ -481,25 +495,29 @@ LL | #[suggestion(no_crate_example, code = "", style = "foo")]
    |
    = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`
 
-error: `#[suggestion(style = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:781:43
+error: expected `= "xxx"`
+  --> $DIR/subdiagnostic-derive.rs:781:49
    |
 LL | #[suggestion(no_crate_example, code = "", style = 42)]
-   |                                           ^^^^^^^^^^
+   |                                                 ^
 
-error: `#[suggestion(style)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:789:43
+error: a diagnostic slug must be the first argument to the attribute
+  --> $DIR/subdiagnostic-derive.rs:789:48
    |
 LL | #[suggestion(no_crate_example, code = "", style)]
-   |                                           ^^^^^
-   |
-   = help: a diagnostic slug must be the first argument to the attribute
+   |                                                ^
 
-error: `#[suggestion(style(...))]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:797:43
+error: expected `= "xxx"`
+  --> $DIR/subdiagnostic-derive.rs:797:48
    |
 LL | #[suggestion(no_crate_example, code = "", style("foo"))]
-   |                                           ^^^^^^^^^^^^
+   |                                                ^
+
+error: expected `,`
+  --> $DIR/subdiagnostic-derive.rs:797:48
+   |
+LL | #[suggestion(no_crate_example, code = "", style("foo"))]
+   |                                                ^
 
 error: `#[primary_span]` is not a valid attribute
   --> $DIR/subdiagnostic-derive.rs:808:5
@@ -582,6 +600,14 @@ error[E0425]: cannot find value `slug` in module `crate::fluent_generated`
 LL | #[label(slug)]
    |         ^^^^ not found in `crate::fluent_generated`
 
-error: aborting due to 81 previous errors
+error[E0425]: cannot find value `__code_29` in this scope
+  --> $DIR/subdiagnostic-derive.rs:703:10
+   |
+LL | #[derive(Subdiagnostic)]
+   |          ^^^^^^^^^^^^^ not found in this scope
+   |
+   = note: this error originates in the derive macro `Subdiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 86 previous errors
 
 For more information about this error, try `rustc --explain E0425`.

From 25fdea009ef0db01134d17cf97cd09b507beca99 Mon Sep 17 00:00:00 2001
From: Deadbeef 
Date: Mon, 3 Apr 2023 15:11:30 +0000
Subject: [PATCH 155/267] fix errors

---
 .../src/diagnostics/subdiagnostic.rs          |   1 +
 .../rustc_macros/src/diagnostics/utils.rs     |   2 +-
 .../diagnostic-derive.stderr                  |   8 +-
 .../subdiagnostic-derive.rs                   |  43 +++--
 .../subdiagnostic-derive.stderr               | 164 +++++++++---------
 5 files changed, 113 insertions(+), 105 deletions(-)

diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 2f42a3b0bd48..62d49c1c64e2 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -422,6 +422,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                 list.parse_nested_meta(|nested| {
                     if nested.path.is_ident("code") {
                         let code_field = new_code_ident();
+                        let span = nested.path.span().unwrap();
                         let formatting_init = build_suggestion_code(
                             &code_field,
                             nested,
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index bc104941c380..838347ecb61a 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -727,7 +727,7 @@ impl SubdiagnosticKind {
                         fields,
                         AllowMultipleAlternatives::Yes,
                     );
-                    code.set_once(code_init, span);
+                    code.set_once(code_init, path_span);
                 }
                 (
                     "applicability",
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 041ebdee0ab8..cd14c7496b37 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -435,16 +435,16 @@ LL | | struct LintAttributeOnLintDiag {}
    = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:608:5
+  --> $DIR/diagnostic-derive.rs:608:53
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                     ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:608:5
+  --> $DIR/diagnostic-derive.rs:608:39
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                       ^^^^
 
 error: wrong types for suggestion
   --> $DIR/diagnostic-derive.rs:617:24
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index c882f7792d5b..1d928ca93f9c 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -82,7 +82,7 @@ struct F {
 
 #[derive(Subdiagnostic)]
 #[label(bug = "...")]
-//~^ ERROR `#[label(bug = ...)]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 //~| ERROR diagnostic slug must be first argument
 struct G {
     #[primary_span]
@@ -92,8 +92,7 @@ struct G {
 
 #[derive(Subdiagnostic)]
 #[label("...")]
-//~^ ERROR `#[label("...")]` is not a valid attribute
-//~| ERROR diagnostic slug must be first argument
+//~^ ERROR unexpected literal in nested attribute, expected ident
 struct H {
     #[primary_span]
     span: Span,
@@ -102,7 +101,7 @@ struct H {
 
 #[derive(Subdiagnostic)]
 #[label(slug = 4)]
-//~^ ERROR `#[label(slug = ...)]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 //~| ERROR diagnostic slug must be first argument
 struct J {
     #[primary_span]
@@ -112,7 +111,7 @@ struct J {
 
 #[derive(Subdiagnostic)]
 #[label(slug("..."))]
-//~^ ERROR `#[label(slug(...))]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 //~| ERROR diagnostic slug must be first argument
 struct K {
     #[primary_span]
@@ -132,7 +131,7 @@ struct L {
 
 #[derive(Subdiagnostic)]
 #[label()]
-//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
+//~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident
 struct M {
     #[primary_span]
     span: Span,
@@ -141,7 +140,7 @@ struct M {
 
 #[derive(Subdiagnostic)]
 #[label(no_crate_example, code = "...")]
-//~^ ERROR `#[label(code = ...)]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 struct N {
     #[primary_span]
     span: Span,
@@ -150,7 +149,7 @@ struct N {
 
 #[derive(Subdiagnostic)]
 #[label(no_crate_example, applicability = "machine-applicable")]
-//~^ ERROR `#[label(applicability = ...)]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 struct O {
     #[primary_span]
     span: Span,
@@ -222,7 +221,7 @@ enum T {
 enum U {
     #[label(code = "...")]
     //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
-    //~| ERROR `#[label(code = ...)]` is not a valid attribute
+    //~| ERROR invalid nested attribute
     A {
         #[primary_span]
         span: Span,
@@ -323,7 +322,7 @@ struct AD {
 
 #[derive(Subdiagnostic)]
 #[label(no_crate_example, no_crate::example)]
-//~^ ERROR `#[label(no_crate::example)]` is not a valid attribute
+//~^ ERROR a diagnostic slug must be the first argument to the attribute
 struct AE {
     #[primary_span]
     span: Span,
@@ -537,7 +536,7 @@ struct BA {
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
 //~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
-//~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute
+//~| ERROR invalid nested attribute
 struct BBa {
     var: String,
 }
@@ -554,7 +553,7 @@ struct BBb {
 #[multipart_suggestion(no_crate_example, applicability = "machine-applicable")]
 struct BBc {
     #[suggestion_part()]
-    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+    //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident
     span1: Span,
 }
 
@@ -574,10 +573,11 @@ struct BD {
     //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
     span1: Span,
     #[suggestion_part()]
-    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+    //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident
     span2: Span,
     #[suggestion_part(foo = "bar")]
-    //~^ ERROR `#[suggestion_part(foo = ...)]` is not a valid attribute
+    //~^ ERROR `code` is the only valid nested attribute
+    //~| ERROR expected `,`
     span4: Span,
     #[suggestion_part(code = "...")]
     //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -669,6 +669,7 @@ enum BL {
 struct BM {
     #[suggestion_part(code("foo"))]
     //~^ ERROR expected exactly one string literal for `code = ...`
+    //~| ERROR unexpected token
     span: Span,
     r#type: String,
 }
@@ -678,6 +679,7 @@ struct BM {
 struct BN {
     #[suggestion_part(code("foo", "bar"))]
     //~^ ERROR expected exactly one string literal for `code = ...`
+    //~| ERROR unexpected token
     span: Span,
     r#type: String,
 }
@@ -687,6 +689,7 @@ struct BN {
 struct BO {
     #[suggestion_part(code(3))]
     //~^ ERROR expected exactly one string literal for `code = ...`
+    //~| ERROR unexpected token
     span: Span,
     r#type: String,
 }
@@ -701,10 +704,13 @@ struct BP {
 }
 
 #[derive(Subdiagnostic)]
+//~^ ERROR cannot find value `__code_29` in this scope
+//~| NOTE in this expansion
+//~| NOTE not found in this scope
 #[multipart_suggestion(no_crate_example)]
 struct BQ {
     #[suggestion_part(code = 3)]
-    //~^ ERROR `code = "..."`/`code(...)` must contain only string literals
+    //~^ ERROR expected string literal
     span: Span,
     r#type: String,
 }
@@ -779,7 +785,7 @@ struct SuggestionStyleInvalid1 {
 
 #[derive(Subdiagnostic)]
 #[suggestion(no_crate_example, code = "", style = 42)]
-//~^ ERROR `#[suggestion(style = ...)]` is not a valid attribute
+//~^ ERROR expected `= "xxx"`
 struct SuggestionStyleInvalid2 {
     #[primary_span]
     sub: Span,
@@ -787,7 +793,7 @@ struct SuggestionStyleInvalid2 {
 
 #[derive(Subdiagnostic)]
 #[suggestion(no_crate_example, code = "", style)]
-//~^ ERROR `#[suggestion(style)]` is not a valid attribute
+//~^ ERROR a diagnostic slug must be the first argument to the attribute
 struct SuggestionStyleInvalid3 {
     #[primary_span]
     sub: Span,
@@ -795,7 +801,8 @@ struct SuggestionStyleInvalid3 {
 
 #[derive(Subdiagnostic)]
 #[suggestion(no_crate_example, code = "", style("foo"))]
-//~^ ERROR `#[suggestion(style(...))]` is not a valid attribute
+//~^ ERROR expected `= "xxx"`
+//~| ERROr expected `,`
 struct SuggestionStyleInvalid4 {
     #[primary_span]
     sub: Span,
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index d8bf0ba413cc..4211b91f04a0 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -45,97 +45,97 @@ LL | #[label("...")]
    |         ^^^^^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:104:9
+  --> $DIR/subdiagnostic-derive.rs:103:9
    |
 LL | #[label(slug = 4)]
    |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:104:1
+  --> $DIR/subdiagnostic-derive.rs:103:1
    |
 LL | #[label(slug = 4)]
    | ^^^^^^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:114:9
+  --> $DIR/subdiagnostic-derive.rs:113:9
    |
 LL | #[label(slug("..."))]
    |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:114:1
+  --> $DIR/subdiagnostic-derive.rs:113:1
    |
 LL | #[label(slug("..."))]
    | ^^^^^^^^^^^^^^^^^^^^^
 
 error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:134:9
+  --> $DIR/subdiagnostic-derive.rs:133:9
    |
 LL | #[label()]
    |         ^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:143:27
+  --> $DIR/subdiagnostic-derive.rs:142:27
    |
 LL | #[label(no_crate_example, code = "...")]
    |                           ^^^^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:152:27
+  --> $DIR/subdiagnostic-derive.rs:151:27
    |
 LL | #[label(no_crate_example, applicability = "machine-applicable")]
    |                           ^^^^^^^^^^^^^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:161:1
+  --> $DIR/subdiagnostic-derive.rs:160:1
    |
 LL | #[foo]
    | ^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:175:5
+  --> $DIR/subdiagnostic-derive.rs:174:5
    |
 LL |     #[bar]
    |     ^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:187:5
+  --> $DIR/subdiagnostic-derive.rs:186:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:199:5
+  --> $DIR/subdiagnostic-derive.rs:198:5
    |
 LL |     #[bar = 4]
    |     ^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:211:5
+  --> $DIR/subdiagnostic-derive.rs:210:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:223:13
+  --> $DIR/subdiagnostic-derive.rs:222:13
    |
 LL |     #[label(code = "...")]
    |             ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:223:5
+  --> $DIR/subdiagnostic-derive.rs:222:5
    |
 LL |     #[label(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:252:5
+  --> $DIR/subdiagnostic-derive.rs:251:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: label without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:249:1
+  --> $DIR/subdiagnostic-derive.rs:248:1
    |
 LL | / #[label(no_crate_example)]
 LL | |
@@ -147,13 +147,13 @@ LL | | }
    | |_^
 
 error: `#[applicability]` is only valid on suggestions
-  --> $DIR/subdiagnostic-derive.rs:262:5
+  --> $DIR/subdiagnostic-derive.rs:261:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:272:5
+  --> $DIR/subdiagnostic-derive.rs:271:5
    |
 LL |     #[bar]
    |     ^^^^^^
@@ -161,13 +161,13 @@ LL |     #[bar]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:283:5
+  --> $DIR/subdiagnostic-derive.rs:282:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:294:5
+  --> $DIR/subdiagnostic-derive.rs:293:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
@@ -175,7 +175,7 @@ LL |     #[bar("...")]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: unexpected unsupported untagged union
-  --> $DIR/subdiagnostic-derive.rs:310:1
+  --> $DIR/subdiagnostic-derive.rs:309:1
    |
 LL | / union AC {
 LL | |
@@ -185,73 +185,73 @@ LL | | }
    | |_^
 
 error: a diagnostic slug must be the first argument to the attribute
-  --> $DIR/subdiagnostic-derive.rs:325:44
+  --> $DIR/subdiagnostic-derive.rs:324:44
    |
 LL | #[label(no_crate_example, no_crate::example)]
    |                                            ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:338:5
+  --> $DIR/subdiagnostic-derive.rs:337:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:335:5
+  --> $DIR/subdiagnostic-derive.rs:334:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: subdiagnostic kind not specified
-  --> $DIR/subdiagnostic-derive.rs:344:8
+  --> $DIR/subdiagnostic-derive.rs:343:8
    |
 LL | struct AG {
    |        ^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:381:1
+  --> $DIR/subdiagnostic-derive.rs:380:46
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                              ^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:381:1
+  --> $DIR/subdiagnostic-derive.rs:380:32
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                ^^^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:399:5
+  --> $DIR/subdiagnostic-derive.rs:398:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:396:5
+  --> $DIR/subdiagnostic-derive.rs:395:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
-  --> $DIR/subdiagnostic-derive.rs:409:5
+  --> $DIR/subdiagnostic-derive.rs:408:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:422:1
+  --> $DIR/subdiagnostic-derive.rs:421:1
    |
 LL | #[suggestion(no_crate_example)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/subdiagnostic-derive.rs:432:62
+  --> $DIR/subdiagnostic-derive.rs:431:62
    |
 LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")]
    |                                                              ^^^^^
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:450:1
+  --> $DIR/subdiagnostic-derive.rs:449:1
    |
 LL | / #[suggestion(no_crate_example, code = "...")]
 LL | |
@@ -261,25 +261,25 @@ LL | | }
    | |_^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:464:1
+  --> $DIR/subdiagnostic-derive.rs:463:1
    |
 LL | #[label]
    | ^^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:484:39
+  --> $DIR/subdiagnostic-derive.rs:483:39
    |
 LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
    |                                       ^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:503:43
+  --> $DIR/subdiagnostic-derive.rs:502:43
    |
 LL |     #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
    |                                           ^^^^^^^
 
 error: `#[suggestion_part]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:526:5
+  --> $DIR/subdiagnostic-derive.rs:525:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
@@ -287,7 +287,7 @@ LL |     #[suggestion_part]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
 
 error: `#[suggestion_part(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:529:5
+  --> $DIR/subdiagnostic-derive.rs:528:5
    |
 LL |     #[suggestion_part(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -295,7 +295,7 @@ LL |     #[suggestion_part(code = "...")]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:523:1
+  --> $DIR/subdiagnostic-derive.rs:522:1
    |
 LL | / #[suggestion(no_crate_example, code = "...")]
 LL | |
@@ -307,7 +307,7 @@ LL | | }
    | |_^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:538:42
+  --> $DIR/subdiagnostic-derive.rs:537:42
    |
 LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
    |                                          ^^^^
@@ -315,7 +315,7 @@ LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "mac
    = help: only `style` and `applicability` are valid nested attributes
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:538:1
+  --> $DIR/subdiagnostic-derive.rs:537:1
    |
 LL | / #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
 LL | |
@@ -326,19 +326,19 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:548:5
+  --> $DIR/subdiagnostic-derive.rs:547:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
 error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:556:23
+  --> $DIR/subdiagnostic-derive.rs:555:23
    |
 LL |     #[suggestion_part()]
    |                       ^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:565:5
+  --> $DIR/subdiagnostic-derive.rs:564:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -346,7 +346,7 @@ LL |     #[primary_span]
    = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:562:1
+  --> $DIR/subdiagnostic-derive.rs:561:1
    |
 LL | / #[multipart_suggestion(no_crate_example)]
 LL | |
@@ -358,13 +358,13 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:573:5
+  --> $DIR/subdiagnostic-derive.rs:572:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
 error: `code` is the only valid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:579:23
+  --> $DIR/subdiagnostic-derive.rs:578:23
    |
 LL |     #[suggestion_part(foo = "bar")]
    |                       ^^^
@@ -382,28 +382,28 @@ LL |     #[suggestion_part()]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:576:23
+  --> $DIR/subdiagnostic-derive.rs:575:23
    |
 LL |     #[suggestion_part()]
    |                       ^
 
 error: expected `,`
-  --> $DIR/subdiagnostic-derive.rs:579:27
+  --> $DIR/subdiagnostic-derive.rs:578:27
    |
 LL |     #[suggestion_part(foo = "bar")]
    |                           ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:593:5
+  --> $DIR/subdiagnostic-derive.rs:593:37
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                     ^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:593:5
+  --> $DIR/subdiagnostic-derive.rs:593:23
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^
 
 error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
   --> $DIR/subdiagnostic-derive.rs:622:5
@@ -424,55 +424,55 @@ LL |     #[suggestion_part(code("foo"))]
    |                            ^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:679:41
+  --> $DIR/subdiagnostic-derive.rs:680:41
    |
 LL |     #[suggestion_part(code("foo", "bar"))]
    |                                         ^
 
 error: unexpected token
-  --> $DIR/subdiagnostic-derive.rs:679:28
+  --> $DIR/subdiagnostic-derive.rs:680:28
    |
 LL |     #[suggestion_part(code("foo", "bar"))]
    |                            ^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:688:30
+  --> $DIR/subdiagnostic-derive.rs:690:30
    |
 LL |     #[suggestion_part(code(3))]
    |                              ^
 
 error: unexpected token
-  --> $DIR/subdiagnostic-derive.rs:688:28
+  --> $DIR/subdiagnostic-derive.rs:690:28
    |
 LL |     #[suggestion_part(code(3))]
    |                            ^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:697:29
+  --> $DIR/subdiagnostic-derive.rs:700:29
    |
 LL |     #[suggestion_part(code())]
    |                             ^
 
 error: expected string literal
-  --> $DIR/subdiagnostic-derive.rs:706:30
+  --> $DIR/subdiagnostic-derive.rs:712:30
    |
 LL |     #[suggestion_part(code = 3)]
    |                              ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:748:1
+  --> $DIR/subdiagnostic-derive.rs:754:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:748:1
+  --> $DIR/subdiagnostic-derive.rs:754:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion_hidden(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:757:1
+  --> $DIR/subdiagnostic-derive.rs:763:1
    |
 LL | #[suggestion_hidden(no_crate_example, code = "")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -480,7 +480,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "")]
    = help: Use `#[suggestion(..., style = "hidden")]` instead
 
 error: `#[suggestion_hidden(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:765:1
+  --> $DIR/subdiagnostic-derive.rs:771:1
    |
 LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -488,7 +488,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")]
    = help: Use `#[suggestion(..., style = "hidden")]` instead
 
 error: invalid suggestion style
-  --> $DIR/subdiagnostic-derive.rs:773:51
+  --> $DIR/subdiagnostic-derive.rs:779:51
    |
 LL | #[suggestion(no_crate_example, code = "", style = "foo")]
    |                                                   ^^^^^
@@ -496,31 +496,31 @@ LL | #[suggestion(no_crate_example, code = "", style = "foo")]
    = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`
 
 error: expected `= "xxx"`
-  --> $DIR/subdiagnostic-derive.rs:781:49
+  --> $DIR/subdiagnostic-derive.rs:787:49
    |
 LL | #[suggestion(no_crate_example, code = "", style = 42)]
    |                                                 ^
 
 error: a diagnostic slug must be the first argument to the attribute
-  --> $DIR/subdiagnostic-derive.rs:789:48
+  --> $DIR/subdiagnostic-derive.rs:795:48
    |
 LL | #[suggestion(no_crate_example, code = "", style)]
    |                                                ^
 
 error: expected `= "xxx"`
-  --> $DIR/subdiagnostic-derive.rs:797:48
+  --> $DIR/subdiagnostic-derive.rs:803:48
    |
 LL | #[suggestion(no_crate_example, code = "", style("foo"))]
    |                                                ^
 
 error: expected `,`
-  --> $DIR/subdiagnostic-derive.rs:797:48
+  --> $DIR/subdiagnostic-derive.rs:803:48
    |
 LL | #[suggestion(no_crate_example, code = "", style("foo"))]
    |                                                ^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:808:5
+  --> $DIR/subdiagnostic-derive.rs:815:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -529,7 +529,7 @@ LL |     #[primary_span]
    = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:805:1
+  --> $DIR/subdiagnostic-derive.rs:812:1
    |
 LL | / #[suggestion(no_crate_example, code = "")]
 LL | |
@@ -547,61 +547,61 @@ LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `foo` in this scope
-  --> $DIR/subdiagnostic-derive.rs:161:3
+  --> $DIR/subdiagnostic-derive.rs:160:3
    |
 LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:175:7
+  --> $DIR/subdiagnostic-derive.rs:174:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:187:7
+  --> $DIR/subdiagnostic-derive.rs:186:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:199:7
+  --> $DIR/subdiagnostic-derive.rs:198:7
    |
 LL |     #[bar = 4]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:211:7
+  --> $DIR/subdiagnostic-derive.rs:210:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:272:7
+  --> $DIR/subdiagnostic-derive.rs:271:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:283:7
+  --> $DIR/subdiagnostic-derive.rs:282:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:294:7
+  --> $DIR/subdiagnostic-derive.rs:293:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
 error[E0425]: cannot find value `slug` in module `crate::fluent_generated`
-  --> $DIR/subdiagnostic-derive.rs:124:9
+  --> $DIR/subdiagnostic-derive.rs:123:9
    |
 LL | #[label(slug)]
    |         ^^^^ not found in `crate::fluent_generated`
 
 error[E0425]: cannot find value `__code_29` in this scope
-  --> $DIR/subdiagnostic-derive.rs:703:10
+  --> $DIR/subdiagnostic-derive.rs:706:10
    |
 LL | #[derive(Subdiagnostic)]
    |          ^^^^^^^^^^^^^ not found in this scope

From d764c2da99fb20032e4dc41c1c23bb90aabd39ad Mon Sep 17 00:00:00 2001
From: Deadbeef 
Date: Thu, 6 Apr 2023 04:52:03 +0000
Subject: [PATCH 156/267] address comments

---
 .../rustc_macros/src/diagnostics/utils.rs     | 93 ++++++++++---------
 compiler/rustc_macros/src/newtype.rs          |  2 +-
 2 files changed, 50 insertions(+), 45 deletions(-)

diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 838347ecb61a..b9b09c66230b 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -420,6 +420,51 @@ pub(super) enum AllowMultipleAlternatives {
     Yes,
 }
 
+fn parse_suggestion_values(
+    nested: ParseNestedMeta<'_>,
+    allow_multiple: AllowMultipleAlternatives,
+) -> syn::Result> {
+    let values = if let Ok(val) = nested.value() {
+        vec![val.parse()?]
+    } else {
+        let content;
+        parenthesized!(content in nested.input);
+
+        if let AllowMultipleAlternatives::No = allow_multiple {
+            span_err(
+                nested.input.span().unwrap(),
+                "expected exactly one string literal for `code = ...`",
+            )
+            .emit();
+            vec![]
+        } else {
+            let literals = Punctuated::::parse_terminated(&content);
+
+            match literals {
+                Ok(p) if p.is_empty() => {
+                    span_err(
+                        content.span().unwrap(),
+                        "expected at least one string literal for `code(...)`",
+                    )
+                    .emit();
+                    vec![]
+                }
+                Ok(p) => p.into_iter().collect(),
+                Err(_) => {
+                    span_err(
+                        content.span().unwrap(),
+                        "`code(...)` must contain only string literals",
+                    )
+                    .emit();
+                    vec![]
+                }
+            }
+        }
+    };
+
+    Ok(values)
+}
+
 /// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or
 /// `#[suggestion*(code("foo", "bar"))]` attribute field
 pub(super) fn build_suggestion_code(
@@ -428,47 +473,7 @@ pub(super) fn build_suggestion_code(
     fields: &impl HasFieldMap,
     allow_multiple: AllowMultipleAlternatives,
 ) -> TokenStream {
-    let values = match (|| {
-        let values: Vec = if let Ok(val) = nested.value() {
-            vec![val.parse()?]
-        } else {
-            let content;
-            parenthesized!(content in nested.input);
-
-            if let AllowMultipleAlternatives::No = allow_multiple {
-                span_err(
-                    nested.input.span().unwrap(),
-                    "expected exactly one string literal for `code = ...`",
-                )
-                .emit();
-                vec![]
-            } else {
-                let literals = Punctuated::::parse_terminated(&content);
-
-                match literals {
-                    Ok(p) if p.is_empty() => {
-                        span_err(
-                            content.span().unwrap(),
-                            "expected at least one string literal for `code(...)`",
-                        )
-                        .emit();
-                        vec![]
-                    }
-                    Ok(p) => p.into_iter().collect(),
-                    Err(_) => {
-                        span_err(
-                            content.span().unwrap(),
-                            "`code(...)` must contain only string literals",
-                        )
-                        .emit();
-                        vec![]
-                    }
-                }
-            }
-        };
-
-        Ok(values)
-    })() {
+    let values = match parse_suggestion_values(nested, allow_multiple) {
         Ok(x) => x,
         Err(e) => return e.into_compile_error(),
     };
@@ -706,14 +711,14 @@ impl SubdiagnosticKind {
             let path_span = nested.path.span().unwrap();
             let val_span = nested.input.span().unwrap();
 
-            macro get_string() {
-                {
+            macro_rules! get_string {
+                () => {{
                     let Ok(value) = nested.value().and_then(|x| x.parse::()) else {
                         span_err(val_span, "expected `= \"xxx\"`").emit();
                         return Ok(());
                     };
                     value
-                }
+                }};
             }
 
             let mut has_errors = false;
diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs
index 04e762e91de3..78a6f74887d4 100644
--- a/compiler/rustc_macros/src/newtype.rs
+++ b/compiler/rustc_macros/src/newtype.rs
@@ -47,7 +47,7 @@ impl Parse for Newtype {
                     false
                 }
                 "debug_format" => {
-                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. } ) = &attr.meta else {
+                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else {
                         panic!("#[debug_format = FMT] attribute requires a format");
                     };
 

From 785459d630a129c4007e865b3c907cd5c469d604 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= 
Date: Tue, 7 Feb 2023 08:32:30 +0100
Subject: [PATCH 157/267] Erase query cache values

---
 compiler/rustc_middle/src/query/erase.rs      | 225 ++++++++++++++++++
 compiler/rustc_middle/src/query/mod.rs        |   1 +
 compiler/rustc_middle/src/ty/query.rs         |  34 ++-
 compiler/rustc_query_impl/src/lib.rs          |  14 +-
 .../rustc_query_impl/src/on_disk_cache.rs     |   9 +-
 compiler/rustc_query_impl/src/plumbing.rs     |  50 +++-
 .../rustc_query_system/src/query/config.rs    |   8 +-
 .../rustc_query_system/src/query/plumbing.rs  |  37 +--
 8 files changed, 329 insertions(+), 49 deletions(-)
 create mode 100644 compiler/rustc_middle/src/query/erase.rs

diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
new file mode 100644
index 000000000000..83046e14f116
--- /dev/null
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -0,0 +1,225 @@
+use crate::ty;
+use std::intrinsics::type_name;
+use std::{
+    fmt,
+    mem::{size_of, transmute_copy, MaybeUninit},
+};
+
+#[derive(Copy, Clone)]
+pub struct Erased {
+    data: MaybeUninit,
+}
+
+impl fmt::Debug for Erased {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "Erased")
+    }
+}
+
+pub trait EraseType: Copy {
+    type Result: Copy;
+}
+
+// Allow `type_alias_bounds` since compilation will fail without `EraseType`.
+#[allow(type_alias_bounds)]
+pub type Erase = Erased;
+
+#[inline(always)]
+pub fn erase(src: T) -> Erase {
+    assert_eq!(
+        size_of::(),
+        size_of::(),
+        "size of {} must match erased type {}",
+        type_name::(),
+        type_name::()
+    );
+    Erased::<::Result> {
+        // SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes.
+        data: unsafe { transmute_copy(&src) },
+    }
+}
+
+/// Restores an erased value.
+#[inline(always)]
+pub fn restore(value: Erase) -> T {
+    let value: Erased<::Result> = value;
+    // SAFETY: Due to the use of impl Trait in `Erase` the only way to safetly create an instance
+    // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of
+    // the right size.
+    unsafe { transmute_copy(&value.data) }
+}
+
+impl EraseType for &'_ T {
+    type Result = [u8; size_of::<*const ()>()];
+}
+
+impl EraseType for &'_ [T] {
+    type Result = [u8; size_of::<*const [()]>()];
+}
+
+impl EraseType for &'_ ty::List {
+    type Result = [u8; size_of::<*const ()>()];
+}
+
+impl EraseType for Result {
+    type Result = Self;
+}
+
+impl EraseType for Option {
+    type Result = Self;
+}
+
+impl EraseType for rustc_hir::MaybeOwner {
+    type Result = Self;
+}
+
+impl EraseType for ty::Visibility {
+    type Result = Self;
+}
+
+impl EraseType for ty::Binder<'_, T> {
+    type Result = Self;
+}
+
+impl EraseType for ty::EarlyBinder {
+    type Result = Self;
+}
+
+impl EraseType for (T0, T1) {
+    type Result = Self;
+}
+
+macro_rules! trivial {
+    ($($ty:ty),+ $(,)?) => {
+        $(
+            impl EraseType for $ty {
+                type Result = [u8; size_of::<$ty>()];
+            }
+        )*
+    }
+}
+
+trivial! {
+    (),
+    bool,
+    rustc_ast::expand::allocator::AllocatorKind,
+    rustc_attr::ConstStability,
+    rustc_attr::DefaultBodyStability,
+    rustc_attr::Deprecation,
+    rustc_attr::Stability,
+    rustc_data_structures::svh::Svh,
+    rustc_errors::ErrorGuaranteed,
+    rustc_hir::Constness,
+    rustc_hir::def_id::DefId,
+    rustc_hir::def_id::DefIndex,
+    rustc_hir::def_id::LocalDefId,
+    rustc_hir::def::DefKind,
+    rustc_hir::Defaultness,
+    rustc_hir::definitions::DefKey,
+    rustc_hir::GeneratorKind,
+    rustc_hir::HirId,
+    rustc_hir::IsAsync,
+    rustc_hir::ItemLocalId,
+    rustc_hir::LangItem,
+    rustc_hir::OwnerId,
+    rustc_hir::Upvar,
+    rustc_index::bit_set::FiniteBitSet,
+    rustc_middle::metadata::ModChild,
+    rustc_middle::middle::dependency_format::Linkage,
+    rustc_middle::middle::exported_symbols::SymbolExportInfo,
+    rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault,
+    rustc_middle::middle::resolve_bound_vars::ResolvedArg,
+    rustc_middle::middle::stability::DeprecationEntry,
+    rustc_middle::mir::ConstQualifs,
+    rustc_middle::mir::interpret::AllocId,
+    rustc_middle::mir::interpret::ErrorHandled,
+    rustc_middle::mir::interpret::LitToConstError,
+    rustc_middle::thir::ExprId,
+    rustc_middle::traits::CodegenObligationError,
+    rustc_middle::traits::EvaluationResult,
+    rustc_middle::traits::OverflowError,
+    rustc_middle::traits::query::NoSolution,
+    rustc_middle::traits::WellFormedLoc,
+    rustc_middle::ty::adjustment::CoerceUnsizedInfo,
+    rustc_middle::ty::AssocItem,
+    rustc_middle::ty::AssocItemContainer,
+    rustc_middle::ty::BoundVariableKind,
+    rustc_middle::ty::DeducedParamAttrs,
+    rustc_middle::ty::Destructor,
+    rustc_middle::ty::fast_reject::SimplifiedType,
+    rustc_middle::ty::ImplPolarity,
+    rustc_middle::ty::Representability,
+    rustc_middle::ty::ReprOptions,
+    rustc_middle::ty::UnusedGenericParams,
+    rustc_middle::ty::util::AlwaysRequiresDrop,
+    rustc_session::config::CrateType,
+    rustc_session::config::EntryFnType,
+    rustc_session::config::OptLevel,
+    rustc_session::config::SymbolManglingVersion,
+    rustc_session::cstore::CrateDepKind,
+    rustc_session::cstore::ExternCrate,
+    rustc_session::cstore::LinkagePreference,
+    rustc_session::Limits,
+    rustc_session::lint::LintExpectationId,
+    rustc_span::def_id::CrateNum,
+    rustc_span::def_id::DefPathHash,
+    rustc_span::ExpnHash,
+    rustc_span::ExpnId,
+    rustc_span::Span,
+    rustc_span::Symbol,
+    rustc_span::symbol::Ident,
+    rustc_target::spec::PanicStrategy,
+    rustc_type_ir::Variance,
+    u32,
+    usize,
+}
+
+macro_rules! tcx_lifetime {
+    ($($($fake_path:ident)::+),+ $(,)?) => {
+        $(
+            impl<'tcx> EraseType for $($fake_path)::+<'tcx> {
+                type Result = [u8; size_of::<$($fake_path)::+<'static>>()];
+            }
+        )*
+    }
+}
+
+tcx_lifetime! {
+    rustc_middle::hir::Owner,
+    rustc_middle::middle::exported_symbols::ExportedSymbol,
+    rustc_middle::mir::ConstantKind,
+    rustc_middle::mir::DestructuredConstant,
+    rustc_middle::mir::interpret::ConstAlloc,
+    rustc_middle::mir::interpret::ConstValue,
+    rustc_middle::mir::interpret::GlobalId,
+    rustc_middle::mir::interpret::LitToConstInput,
+    rustc_middle::traits::ChalkEnvironmentAndGoal,
+    rustc_middle::traits::query::MethodAutoderefStepsResult,
+    rustc_middle::traits::query::type_op::AscribeUserType,
+    rustc_middle::traits::query::type_op::Eq,
+    rustc_middle::traits::query::type_op::ProvePredicate,
+    rustc_middle::traits::query::type_op::Subtype,
+    rustc_middle::ty::AdtDef,
+    rustc_middle::ty::AliasTy,
+    rustc_middle::ty::Clause,
+    rustc_middle::ty::ClosureTypeInfo,
+    rustc_middle::ty::Const,
+    rustc_middle::ty::DestructuredConst,
+    rustc_middle::ty::ExistentialTraitRef,
+    rustc_middle::ty::FnSig,
+    rustc_middle::ty::GenericArg,
+    rustc_middle::ty::GenericPredicates,
+    rustc_middle::ty::inhabitedness::InhabitedPredicate,
+    rustc_middle::ty::Instance,
+    rustc_middle::ty::InstanceDef,
+    rustc_middle::ty::layout::FnAbiError,
+    rustc_middle::ty::layout::LayoutError,
+    rustc_middle::ty::ParamEnv,
+    rustc_middle::ty::Predicate,
+    rustc_middle::ty::SymbolName,
+    rustc_middle::ty::TraitRef,
+    rustc_middle::ty::Ty,
+    rustc_middle::ty::UnevaluatedConst,
+    rustc_middle::ty::ValTree,
+    rustc_middle::ty::VtblEntry,
+}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 9203dd59a7e6..846df6d5188f 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -7,6 +7,7 @@
 use crate::ty::{self, print::describe_as_module, TyCtxt};
 use rustc_span::def_id::LOCAL_CRATE;
 
+pub mod erase;
 mod keys;
 pub use keys::{AsLocalKey, Key, LocalCrate};
 
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index 30246fe4dbeb..734512b4048c 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -17,6 +17,7 @@ use crate::mir::interpret::{
 };
 use crate::mir::interpret::{LitToConstError, LitToConstInput};
 use crate::mir::mono::CodegenUnit;
+use crate::query::erase::{erase, restore, Erase};
 use crate::query::{AsLocalKey, Key};
 use crate::thir;
 use crate::traits::query::{
@@ -57,6 +58,8 @@ use rustc_hir::hir_id::OwnerId;
 use rustc_hir::lang_items::{LangItem, LanguageItems};
 use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
 use rustc_index::vec::IndexVec;
+pub(crate) use rustc_query_system::query::QueryJobId;
+use rustc_query_system::query::*;
 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use rustc_session::cstore::{CrateDepKind, CrateSource};
 use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
@@ -66,18 +69,19 @@ use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi;
 use rustc_target::spec::PanicStrategy;
+
+use std::marker::PhantomData;
 use std::mem;
 use std::ops::Deref;
 use std::path::PathBuf;
 use std::sync::Arc;
 
-pub(crate) use rustc_query_system::query::QueryJobId;
-use rustc_query_system::query::*;
-
 #[derive(Default)]
 pub struct QuerySystem<'tcx> {
     pub arenas: QueryArenas<'tcx>,
     pub caches: QueryCaches<'tcx>,
+    // Since we erase query value types we tell the typesystem about them with `PhantomData`.
+    _phantom_values: QueryPhantomValues<'tcx>,
 }
 
 #[derive(Copy, Clone)]
@@ -263,8 +267,8 @@ macro_rules! define_callbacks {
                 pub fn $name<'tcx>(
                     _tcx: TyCtxt<'tcx>,
                     value: query_provided::$name<'tcx>,
-                ) -> query_values::$name<'tcx> {
-                    query_if_arena!([$($modifiers)*]
+                ) -> Erase> {
+                    erase(query_if_arena!([$($modifiers)*]
                         {
                             if mem::needs_drop::>() {
                                 &*_tcx.query_system.arenas.$name.alloc(value)
@@ -273,7 +277,7 @@ macro_rules! define_callbacks {
                             }
                         }
                         (value)
-                    )
+                    ))
                 }
             )*
         }
@@ -282,7 +286,7 @@ macro_rules! define_callbacks {
             use super::*;
 
             $(
-                pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache;
+                pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>>::Cache;
             )*
         }
 
@@ -334,6 +338,11 @@ macro_rules! define_callbacks {
             }
         }
 
+        #[derive(Default)]
+        pub struct QueryPhantomValues<'tcx> {
+            $($(#[$attr])* pub $name: PhantomData>,)*
+        }
+
         #[derive(Default)]
         pub struct QueryCaches<'tcx> {
             $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
@@ -395,10 +404,10 @@ macro_rules! define_callbacks {
                 let key = key.into_query_param();
                 opt_remap_env_constness!([$($modifiers)*][key]);
 
-                match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
+                restore::<$V>(match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
                     Some(value) => value,
                     None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
-                }
+                })
             })*
         }
 
@@ -459,7 +468,7 @@ macro_rules! define_callbacks {
                 span: Span,
                 key: query_keys::$name<'tcx>,
                 mode: QueryMode,
-            ) -> Option<$V>;)*
+            ) -> Option>;)*
         }
     };
 }
@@ -486,7 +495,8 @@ macro_rules! define_feedable {
                 opt_remap_env_constness!([$($modifiers)*][key]);
 
                 let tcx = self.tcx;
-                let value = query_provided_to_value::$name(tcx, value);
+                let erased = query_provided_to_value::$name(tcx, value);
+                let value = restore::<$V>(erased);
                 let cache = &tcx.query_system.caches.$name;
 
                 match try_get_cached(tcx, cache, &key) {
@@ -505,7 +515,7 @@ macro_rules! define_feedable {
                             &value,
                             hash_result!([$($modifiers)*]),
                         );
-                        cache.complete(key, value, dep_node_index);
+                        cache.complete(key, erased, dep_node_index);
                         value
                     }
                 }
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 021a67c9513c..7e053735aa9c 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -18,19 +18,21 @@ extern crate rustc_middle;
 
 use rustc_data_structures::sync::AtomicU64;
 use rustc_middle::arena::Arena;
-use rustc_middle::dep_graph::{self, DepKindStruct};
+use rustc_middle::dep_graph::{self, DepKind, DepKindStruct};
+use rustc_middle::query::erase::{erase, restore, Erase};
 use rustc_middle::query::AsLocalKey;
 use rustc_middle::ty::query::{
     query_keys, query_provided, query_provided_to_value, query_storage, query_values,
 };
 use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
 use rustc_middle::ty::TyCtxt;
+use rustc_query_system::dep_graph::SerializedDepNodeIndex;
+use rustc_query_system::Value;
 use rustc_span::Span;
 
 #[macro_use]
 mod plumbing;
 pub use plumbing::QueryCtxt;
-use rustc_query_system::dep_graph::SerializedDepNodeIndex;
 use rustc_query_system::query::*;
 #[cfg(parallel_compiler)]
 pub use rustc_query_system::query::{deadlock, QueryContext};
@@ -43,6 +45,14 @@ pub use on_disk_cache::OnDiskCache;
 mod profiling_support;
 pub use self::profiling_support::alloc_self_profile_query_strings;
 
+trait QueryToConfig<'tcx>: 'tcx {
+    type Value;
+    type Config: QueryConfig>;
+
+    fn config(qcx: QueryCtxt<'tcx>) -> Self::Config;
+    fn restore(value: >>::Value) -> Self::Value;
+}
+
 rustc_query_append! { define_queries! }
 
 impl<'tcx> Queries<'tcx> {
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 35b7e5919e42..4d64517d4a31 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -13,6 +13,7 @@ use rustc_middle::mir::{self, interpret};
 use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_query_system::dep_graph::DepContext;
+use rustc_query_system::query::QueryConfig;
 use rustc_query_system::query::{QueryCache, QuerySideEffects};
 use rustc_serialize::{
     opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder},
@@ -1064,13 +1065,13 @@ impl<'a, 'tcx> Encodable> for [u8] {
     }
 }
 
-pub fn encode_query_results<'a, 'tcx, Q>(
-    query: Q,
+pub(crate) fn encode_query_results<'a, 'tcx, Q>(
+    query: Q::Config,
     qcx: QueryCtxt<'tcx>,
     encoder: &mut CacheEncoder<'a, 'tcx>,
     query_result_index: &mut EncodedDepNodeIndex,
 ) where
-    Q: super::QueryConfig>,
+    Q: super::QueryToConfig<'tcx>,
     Q::Value: Encodable>,
 {
     let _timer = qcx
@@ -1089,7 +1090,7 @@ pub fn encode_query_results<'a, 'tcx, Q>(
 
             // Encode the type check tables with the `SerializedDepNodeIndex`
             // as tag.
-            encoder.encode_tagged(dep_node, value);
+            encoder.encode_tagged(dep_node, &Q::restore(*value));
         }
     });
 }
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 9bba26cc8e84..ddc86b5173fb 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -263,14 +263,14 @@ macro_rules! feedable {
 }
 
 macro_rules! hash_result {
-    ([]) => {{
-        Some(dep_graph::hash_result)
+    ([][$V:ty]) => {{
+        Some(|hcx, result| dep_graph::hash_result(hcx, &restore::<$V>(*result)))
     }};
-    ([(no_hash) $($rest:tt)*]) => {{
+    ([(no_hash) $($rest:tt)*][$V:ty]) => {{
         None
     }};
-    ([$other:tt $($modifiers:tt)*]) => {
-        hash_result!([$($modifiers)*])
+    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
+        hash_result!([$($modifiers)*][$($args)*])
     };
 }
 
@@ -479,7 +479,7 @@ macro_rules! define_queries {
 
         $(impl<'tcx> QueryConfig> for queries::$name<'tcx> {
             type Key = query_keys::$name<'tcx>;
-            type Value = query_values::$name<'tcx>;
+            type Value = Erase>;
 
             #[inline(always)]
             fn name(self) -> &'static str {
@@ -508,7 +508,7 @@ macro_rules! define_queries {
             }
 
             fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
-                tcx.$name(key)
+                erase(tcx.$name(key))
             }
 
             #[inline]
@@ -558,6 +558,16 @@ macro_rules! define_queries {
                 })
             }
 
+            #[inline]
+            fn from_cycle_error(
+                self,
+                tcx: TyCtxt<'tcx>,
+                cycle: &[QueryInfo],
+            ) -> Self::Value {
+                let result: query_values::$name<'tcx> = Value::from_cycle_error(tcx, cycle);
+                erase(result)
+            }
+
             #[inline(always)]
             fn anon(self) -> bool {
                 is_anon!([$($modifiers)*])
@@ -590,7 +600,22 @@ macro_rules! define_queries {
 
             #[inline(always)]
             fn hash_result(self) -> rustc_query_system::query::HashResult {
-                hash_result!([$($modifiers)*])
+                hash_result!([$($modifiers)*][query_values::$name<'tcx>])
+            }
+        })*
+
+        $(impl<'tcx> QueryToConfig<'tcx> for queries::$name<'tcx> {
+            type Value = query_values::$name<'tcx>;
+            type Config = Self;
+
+            #[inline(always)]
+            fn config(_qcx: QueryCtxt<'tcx>) -> Self::Config {
+                Self::default()
+            }
+
+            #[inline(always)]
+            fn restore(value: >>::Value) -> Self::Value {
+                restore::>(value)
             }
         })*
 
@@ -665,6 +690,7 @@ macro_rules! define_queries {
             use $crate::profiling_support::QueryKeyStringCache;
             use rustc_query_system::query::QueryMap;
             use rustc_middle::dep_graph::DepKind;
+            use crate::QueryToConfig;
 
             pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
                 fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> {
@@ -708,8 +734,8 @@ macro_rules! define_queries {
                     )
                 },
                 encode_query_results: expand_if_cached!([$($modifiers)*], |qcx, encoder, query_result_index|
-                    $crate::on_disk_cache::encode_query_results(
-                        super::queries::$name::default(),
+                    $crate::on_disk_cache::encode_query_results::>(
+                        super::queries::$name::config(qcx),
                         qcx,
                         encoder,
                         query_result_index,
@@ -798,9 +824,9 @@ macro_rules! define_queries_struct {
                 &'tcx self,
                 tcx: TyCtxt<'tcx>,
                 span: Span,
-                key:  as QueryConfig>>::Key,
+                key: query_keys::$name<'tcx>,
                 mode: QueryMode,
-            ) -> Option> {
+            ) -> Option>> {
                 let qcx = QueryCtxt { tcx, queries: self };
                 get_query(
                     queries::$name::default(),
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index a0aeb812af96..ae3b67915cbd 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -4,7 +4,7 @@ use crate::dep_graph::{DepNode, DepNodeParams, SerializedDepNodeIndex};
 use crate::error::HandleCycleError;
 use crate::ich::StableHashingContext;
 use crate::query::caches::QueryCache;
-use crate::query::{QueryContext, QueryState};
+use crate::query::{QueryContext, QueryInfo, QueryState};
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use std::fmt::Debug;
@@ -45,6 +45,12 @@ pub trait QueryConfig: Copy {
 
     fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool;
 
+    fn from_cycle_error(
+        self,
+        tcx: Qcx::DepContext,
+        cycle: &[QueryInfo],
+    ) -> Self::Value;
+
     fn anon(self) -> bool;
     fn eval_always(self) -> bool;
     fn depth_limit(self) -> bool;
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 519ea5ffed18..5314d26b9401 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -11,7 +11,6 @@ use crate::query::job::QueryLatch;
 use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo};
 use crate::query::SerializedDepNodeIndex;
 use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame};
-use crate::values::Value;
 use crate::HandleCycleError;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
@@ -120,43 +119,45 @@ where
 
 #[cold]
 #[inline(never)]
-fn mk_cycle(
+fn mk_cycle(
+    query: Q,
     qcx: Qcx,
-    cycle_error: CycleError,
+    cycle_error: CycleError,
     handler: HandleCycleError,
-) -> R
+) -> Q::Value
 where
-    Qcx: QueryContext + HasDepContext,
-    R: std::fmt::Debug + Value,
+    Q: QueryConfig,
+    Qcx: QueryContext,
 {
     let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
-    handle_cycle_error(*qcx.dep_context(), &cycle_error, error, handler)
+    handle_cycle_error(query, qcx, &cycle_error, error, handler)
 }
 
-fn handle_cycle_error(
-    tcx: Tcx,
-    cycle_error: &CycleError,
+fn handle_cycle_error(
+    query: Q,
+    qcx: Qcx,
+    cycle_error: &CycleError,
     mut error: DiagnosticBuilder<'_, ErrorGuaranteed>,
     handler: HandleCycleError,
-) -> V
+) -> Q::Value
 where
-    Tcx: DepContext,
-    V: Value,
+    Q: QueryConfig,
+    Qcx: QueryContext,
 {
     use HandleCycleError::*;
     match handler {
         Error => {
             error.emit();
-            Value::from_cycle_error(tcx, &cycle_error.cycle)
+            query.from_cycle_error(*qcx.dep_context(), &cycle_error.cycle)
         }
         Fatal => {
             error.emit();
-            tcx.sess().abort_if_errors();
+            qcx.dep_context().sess().abort_if_errors();
             unreachable!()
         }
         DelayBug => {
             error.delay_as_bug();
-            Value::from_cycle_error(tcx, &cycle_error.cycle)
+            query.from_cycle_error(*qcx.dep_context(), &cycle_error.cycle)
         }
     }
 }
@@ -269,7 +270,7 @@ where
         &qcx.current_query_job(),
         span,
     );
-    (mk_cycle(qcx, error, query.handle_cycle_error()), None)
+    (mk_cycle(query, qcx, error, query.handle_cycle_error()), None)
 }
 
 #[inline(always)]
@@ -306,7 +307,7 @@ where
 
             (v, Some(index))
         }
-        Err(cycle) => (mk_cycle(qcx, cycle, query.handle_cycle_error()), None),
+        Err(cycle) => (mk_cycle(query, qcx, cycle, query.handle_cycle_error()), None),
     }
 }
 

From 36b4199a8e4197420760438df464cffcaa674e6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= 
Date: Sun, 26 Mar 2023 11:00:26 +0200
Subject: [PATCH 158/267] Don't rely on `Debug` impl for `Erased`

---
 compiler/rustc_middle/src/query/erase.rs         | 11 +----------
 compiler/rustc_middle/src/ty/query.rs            |  1 +
 compiler/rustc_query_impl/src/plumbing.rs        |  7 ++++++-
 .../rustc_query_system/src/dep_graph/graph.rs    |  9 ++++++++-
 compiler/rustc_query_system/src/query/caches.rs  |  8 ++++----
 compiler/rustc_query_system/src/query/config.rs  |  4 +++-
 .../rustc_query_system/src/query/plumbing.rs     | 16 ++++++++++------
 7 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 83046e14f116..705300b9b7a7 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -1,21 +1,12 @@
 use crate::ty;
 use std::intrinsics::type_name;
-use std::{
-    fmt,
-    mem::{size_of, transmute_copy, MaybeUninit},
-};
+use std::mem::{size_of, transmute_copy, MaybeUninit};
 
 #[derive(Copy, Clone)]
 pub struct Erased {
     data: MaybeUninit,
 }
 
-impl fmt::Debug for Erased {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "Erased")
-    }
-}
-
 pub trait EraseType: Copy {
     type Result: Copy;
 }
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index 734512b4048c..fa9fea723448 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -501,6 +501,7 @@ macro_rules! define_feedable {
 
                 match try_get_cached(tcx, cache, &key) {
                     Some(old) => {
+                        let old = restore::<$V>(old);
                         bug!(
                             "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
                             stringify!($name),
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index ddc86b5173fb..a1dfb27c5d73 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -486,6 +486,11 @@ macro_rules! define_queries {
                 stringify!($name)
             }
 
+            #[inline]
+            fn format_value(self) -> fn(&Self::Value) -> String {
+                |value| format!("{:?}", restore::>(*value))
+            }
+
             #[inline]
             fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
                 ::rustc_middle::query::cached::$name(tcx, key)
@@ -819,7 +824,7 @@ macro_rules! define_queries_struct {
 
             $($(#[$attr])*
             #[inline(always)]
-            #[tracing::instrument(level = "trace", skip(self, tcx), ret)]
+            #[tracing::instrument(level = "trace", skip(self, tcx))]
             fn $name(
                 &'tcx self,
                 tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 2ff7de8cb9ef..534d13b1ae0f 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -538,7 +538,14 @@ impl DepGraph {
             if let Some(prev_index) = data.previous.node_to_index_opt(&node) {
                 let dep_node_index = data.current.prev_index_to_index.lock()[prev_index];
                 if let Some(dep_node_index) = dep_node_index {
-                    crate::query::incremental_verify_ich(cx, data, result, prev_index, hash_result);
+                    crate::query::incremental_verify_ich(
+                        cx,
+                        data,
+                        result,
+                        prev_index,
+                        hash_result,
+                        |value| format!("{:?}", value),
+                    );
 
                     #[cfg(debug_assertions)]
                     if hash_result.is_some() {
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index d3efc22a1945..3ac8a852a4e7 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -18,7 +18,7 @@ pub trait CacheSelector<'tcx, V> {
 
 pub trait QueryCache: Sized {
     type Key: Hash + Eq + Copy + Debug;
-    type Value: Copy + Debug;
+    type Value: Copy;
 
     /// Checks if the query is already computed and in the cache.
     fn lookup(&self, key: &Self::Key) -> Option<(Self::Value, DepNodeIndex)>;
@@ -52,7 +52,7 @@ impl Default for DefaultCache {
 impl QueryCache for DefaultCache
 where
     K: Eq + Hash + Copy + Debug,
-    V: Copy + Debug,
+    V: Copy,
 {
     type Key = K;
     type Value = V;
@@ -120,7 +120,7 @@ impl Default for SingleCache {
 
 impl QueryCache for SingleCache
 where
-    V: Copy + Debug,
+    V: Copy,
 {
     type Key = ();
     type Value = V;
@@ -164,7 +164,7 @@ impl Default for VecCache {
 impl QueryCache for VecCache
 where
     K: Eq + Idx + Copy + Debug,
-    V: Copy + Debug,
+    V: Copy,
 {
     type Key = K;
     type Value = V;
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index ae3b67915cbd..dc981a802f36 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -20,10 +20,12 @@ pub trait QueryConfig: Copy {
     // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap,
     // but it isn't necessary.
     type Key: DepNodeParams + Eq + Hash + Copy + Debug;
-    type Value: Debug + Copy;
+    type Value: Copy;
 
     type Cache: QueryCache;
 
+    fn format_value(self) -> fn(&Self::Value) -> String;
+
     // Don't use this method to access query results, instead use the methods on TyCtxt
     fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState
     where
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 5314d26b9401..95366e1ad0b8 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -411,7 +411,8 @@ where
         // get evaluated first, and re-feed the query.
         if let Some((cached_result, _)) = cache.lookup(&key) {
             panic!(
-                "fed query later has its value computed. The already cached value: {cached_result:?}"
+                "fed query later has its value computed. The already cached value: {}",
+                (query.format_value())(&cached_result)
             );
         }
     }
@@ -582,6 +583,7 @@ where
                     &result,
                     prev_dep_node_index,
                     query.hash_result(),
+                    query.format_value(),
                 );
             }
 
@@ -627,19 +629,21 @@ where
         &result,
         prev_dep_node_index,
         query.hash_result(),
+        query.format_value(),
     );
 
     Some((result, dep_node_index))
 }
 
 #[inline]
-#[instrument(skip(tcx, dep_graph_data, result, hash_result), level = "debug")]
-pub(crate) fn incremental_verify_ich(
+#[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")]
+pub(crate) fn incremental_verify_ich(
     tcx: Tcx,
     dep_graph_data: &DepGraphData,
     result: &V,
     prev_index: SerializedDepNodeIndex,
     hash_result: Option, &V) -> Fingerprint>,
+    format_value: fn(&V) -> String,
 ) where
     Tcx: DepContext,
 {
@@ -654,7 +658,7 @@ pub(crate) fn incremental_verify_ich(
     let old_hash = dep_graph_data.prev_fingerprint_of(prev_index);
 
     if new_hash != old_hash {
-        incremental_verify_ich_failed(tcx, prev_index, result);
+        incremental_verify_ich_failed(tcx, prev_index, &|| format_value(&result));
     }
 }
 
@@ -678,7 +682,7 @@ where
 fn incremental_verify_ich_failed(
     tcx: Tcx,
     prev_index: SerializedDepNodeIndex,
-    result: &dyn Debug,
+    result: &dyn Fn() -> String,
 ) where
     Tcx: DepContext,
 {
@@ -708,7 +712,7 @@ fn incremental_verify_ich_failed(
             run_cmd,
             dep_node: format!("{dep_node:?}"),
         });
-        panic!("Found unstable fingerprints for {dep_node:?}: {result:?}");
+        panic!("Found unstable fingerprints for {dep_node:?}: {}", result());
     }
 
     INSIDE_VERIFY_PANIC.with(|in_panic| in_panic.set(old_in_panic));

From 453e919c3748c2e057d4e2c3fc3b881ac84668c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= 
Date: Sun, 26 Mar 2023 11:22:21 +0200
Subject: [PATCH 159/267] Avoid the assertion in `erase`

---
 compiler/rustc_middle/src/lib.rs         |  1 +
 compiler/rustc_middle/src/query/erase.rs | 15 +++++++--------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 0e883424fd47..b4edb02f6c48 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -33,6 +33,7 @@
 #![feature(generators)]
 #![feature(get_mut_unchecked)]
 #![feature(if_let_guard)]
+#![feature(inline_const)]
 #![feature(iter_from_generator)]
 #![feature(local_key_cell_methods)]
 #![feature(negative_impls)]
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 705300b9b7a7..131f91c28870 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -1,5 +1,4 @@
 use crate::ty;
-use std::intrinsics::type_name;
 use std::mem::{size_of, transmute_copy, MaybeUninit};
 
 #[derive(Copy, Clone)]
@@ -17,13 +16,13 @@ pub type Erase = Erased;
 
 #[inline(always)]
 pub fn erase(src: T) -> Erase {
-    assert_eq!(
-        size_of::(),
-        size_of::(),
-        "size of {} must match erased type {}",
-        type_name::(),
-        type_name::()
-    );
+    // Ensure the sizes match
+    const {
+        if std::mem::size_of::() != std::mem::size_of::() {
+            panic!("size of T must match erased type T::Result")
+        }
+    };
+
     Erased::<::Result> {
         // SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes.
         data: unsafe { transmute_copy(&src) },

From 6d99dd91895f9dafbaa08d1ada7782d884089503 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= 
Date: Sun, 26 Mar 2023 12:24:44 +0200
Subject: [PATCH 160/267] Address comments

---
 compiler/rustc_middle/src/query/erase.rs        |  4 +++-
 compiler/rustc_query_impl/src/lib.rs            |  9 ++++-----
 compiler/rustc_query_impl/src/on_disk_cache.rs  |  7 +++----
 compiler/rustc_query_impl/src/plumbing.rs       | 17 +++++------------
 compiler/rustc_query_system/src/query/config.rs |  3 ++-
 .../rustc_query_system/src/query/plumbing.rs    |  4 ++--
 6 files changed, 19 insertions(+), 25 deletions(-)

diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 131f91c28870..86532f4f264f 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -3,6 +3,8 @@ use std::mem::{size_of, transmute_copy, MaybeUninit};
 
 #[derive(Copy, Clone)]
 pub struct Erased {
+    // We use `MaybeUninit` here so we can store any value
+    // in `data` since we aren't actually storing a `T`.
     data: MaybeUninit,
 }
 
@@ -12,7 +14,7 @@ pub trait EraseType: Copy {
 
 // Allow `type_alias_bounds` since compilation will fail without `EraseType`.
 #[allow(type_alias_bounds)]
-pub type Erase = Erased;
+pub type Erase = Erased;
 
 #[inline(always)]
 pub fn erase(src: T) -> Erase {
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 7e053735aa9c..7001a1eed57e 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -45,12 +45,11 @@ pub use on_disk_cache::OnDiskCache;
 mod profiling_support;
 pub use self::profiling_support::alloc_self_profile_query_strings;
 
-trait QueryToConfig<'tcx>: 'tcx {
-    type Value;
-    type Config: QueryConfig>;
+/// This is implemented per query and restoring query values from their erased state.
+trait QueryConfigRestored<'tcx>: QueryConfig> + Default {
+    type RestoredValue;
 
-    fn config(qcx: QueryCtxt<'tcx>) -> Self::Config;
-    fn restore(value: >>::Value) -> Self::Value;
+    fn restore(value: >>::Value) -> Self::RestoredValue;
 }
 
 rustc_query_append! { define_queries! }
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 4d64517d4a31..eec9dac7b9b0 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -13,7 +13,6 @@ use rustc_middle::mir::{self, interpret};
 use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_query_system::dep_graph::DepContext;
-use rustc_query_system::query::QueryConfig;
 use rustc_query_system::query::{QueryCache, QuerySideEffects};
 use rustc_serialize::{
     opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder},
@@ -1066,13 +1065,13 @@ impl<'a, 'tcx> Encodable> for [u8] {
 }
 
 pub(crate) fn encode_query_results<'a, 'tcx, Q>(
-    query: Q::Config,
+    query: Q,
     qcx: QueryCtxt<'tcx>,
     encoder: &mut CacheEncoder<'a, 'tcx>,
     query_result_index: &mut EncodedDepNodeIndex,
 ) where
-    Q: super::QueryToConfig<'tcx>,
-    Q::Value: Encodable>,
+    Q: super::QueryConfigRestored<'tcx>,
+    Q::RestoredValue: Encodable>,
 {
     let _timer = qcx
         .tcx
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index a1dfb27c5d73..afbead7d1ae9 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -564,7 +564,7 @@ macro_rules! define_queries {
             }
 
             #[inline]
-            fn from_cycle_error(
+            fn value_from_cycle_error(
                 self,
                 tcx: TyCtxt<'tcx>,
                 cycle: &[QueryInfo],
@@ -609,17 +609,11 @@ macro_rules! define_queries {
             }
         })*
 
-        $(impl<'tcx> QueryToConfig<'tcx> for queries::$name<'tcx> {
-            type Value = query_values::$name<'tcx>;
-            type Config = Self;
+        $(impl<'tcx> QueryConfigRestored<'tcx> for queries::$name<'tcx> {
+            type RestoredValue = query_values::$name<'tcx>;
 
             #[inline(always)]
-            fn config(_qcx: QueryCtxt<'tcx>) -> Self::Config {
-                Self::default()
-            }
-
-            #[inline(always)]
-            fn restore(value: >>::Value) -> Self::Value {
+            fn restore(value: >>::Value) -> Self::RestoredValue {
                 restore::>(value)
             }
         })*
@@ -695,7 +689,6 @@ macro_rules! define_queries {
             use $crate::profiling_support::QueryKeyStringCache;
             use rustc_query_system::query::QueryMap;
             use rustc_middle::dep_graph::DepKind;
-            use crate::QueryToConfig;
 
             pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
                 fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> {
@@ -740,7 +733,7 @@ macro_rules! define_queries {
                 },
                 encode_query_results: expand_if_cached!([$($modifiers)*], |qcx, encoder, query_result_index|
                     $crate::on_disk_cache::encode_query_results::>(
-                        super::queries::$name::config(qcx),
+                        super::queries::$name::default(),
                         qcx,
                         encoder,
                         query_result_index,
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index dc981a802f36..c8d779385108 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -47,7 +47,8 @@ pub trait QueryConfig: Copy {
 
     fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool;
 
-    fn from_cycle_error(
+    /// Synthesize an error value to let compilation continue after a cycle.
+    fn value_from_cycle_error(
         self,
         tcx: Qcx::DepContext,
         cycle: &[QueryInfo],
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 95366e1ad0b8..20310483d7e8 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -148,7 +148,7 @@ where
     match handler {
         Error => {
             error.emit();
-            query.from_cycle_error(*qcx.dep_context(), &cycle_error.cycle)
+            query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle)
         }
         Fatal => {
             error.emit();
@@ -157,7 +157,7 @@ where
         }
         DelayBug => {
             error.delay_as_bug();
-            query.from_cycle_error(*qcx.dep_context(), &cycle_error.cycle)
+            query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle)
         }
     }
 }

From 0110073d035530139835585a78c3a62db838a49e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= 
Date: Sun, 26 Mar 2023 12:51:16 +0200
Subject: [PATCH 161/267] Fully erase query values

---
 compiler/rustc_middle/src/query/erase.rs | 150 ++++++++++++++++++++---
 1 file changed, 135 insertions(+), 15 deletions(-)

diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 86532f4f264f..5462ced16d6b 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -1,4 +1,6 @@
-use crate::ty;
+use crate::mir;
+use crate::traits;
+use crate::ty::{self, Ty};
 use std::mem::{size_of, transmute_copy, MaybeUninit};
 
 #[derive(Copy, Clone)]
@@ -53,32 +55,128 @@ impl EraseType for &'_ ty::List {
     type Result = [u8; size_of::<*const ()>()];
 }
 
-impl EraseType for Result {
-    type Result = Self;
+impl EraseType for Result<&'_ T, traits::query::NoSolution> {
+    type Result = [u8; size_of::>()];
 }
 
-impl EraseType for Option {
-    type Result = Self;
+impl EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> {
+    type Result = [u8; size_of::>()];
 }
 
-impl EraseType for rustc_hir::MaybeOwner {
-    type Result = Self;
+impl EraseType for Result<&'_ T, traits::CodegenObligationError> {
+    type Result = [u8; size_of::>()];
 }
 
-impl EraseType for ty::Visibility {
-    type Result = Self;
+impl EraseType for Result<&'_ T, ty::layout::FnAbiError<'_>> {
+    type Result = [u8; size_of::>>()];
 }
 
-impl EraseType for ty::Binder<'_, T> {
-    type Result = Self;
+impl EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> {
+    type Result = [u8; size_of::<
+        Result<(&'static (), rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed>,
+    >()];
 }
 
-impl EraseType for ty::EarlyBinder {
-    type Result = Self;
+impl EraseType for Result>, rustc_errors::ErrorGuaranteed> {
+    type Result =
+        [u8; size_of::>, rustc_errors::ErrorGuaranteed>>()];
 }
 
-impl EraseType for (T0, T1) {
-    type Result = Self;
+impl EraseType for Result>, rustc_errors::ErrorGuaranteed> {
+    type Result =
+        [u8; size_of::>, rustc_errors::ErrorGuaranteed>>()];
+}
+
+impl EraseType for Result, traits::query::NoSolution> {
+    type Result = [u8; size_of::, traits::query::NoSolution>>()];
+}
+
+impl EraseType for Result> {
+    type Result = [u8; size_of::>>()];
+}
+
+impl EraseType for Result>, ty::layout::LayoutError<'_>> {
+    type Result = [u8; size_of::<
+        Result<
+            rustc_target::abi::TyAndLayout<'static, Ty<'static>>,
+            ty::layout::LayoutError<'static>,
+        >,
+    >()];
+}
+
+impl EraseType for Result, mir::interpret::LitToConstError> {
+    type Result = [u8; size_of::, mir::interpret::LitToConstError>>()];
+}
+
+impl EraseType for Result, mir::interpret::LitToConstError> {
+    type Result =
+        [u8; size_of::, mir::interpret::LitToConstError>>()];
+}
+
+impl EraseType for Result, mir::interpret::ErrorHandled> {
+    type Result = [u8; size_of::<
+        Result, mir::interpret::ErrorHandled>,
+    >()];
+}
+
+impl EraseType for Result, mir::interpret::ErrorHandled> {
+    type Result = [u8; size_of::<
+        Result, mir::interpret::ErrorHandled>,
+    >()];
+}
+
+impl EraseType for Result>, mir::interpret::ErrorHandled> {
+    type Result =
+        [u8; size_of::>, mir::interpret::ErrorHandled>>()];
+}
+
+impl EraseType for Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop> {
+    type Result =
+        [u8; size_of::>, ty::util::AlwaysRequiresDrop>>()];
+}
+
+impl EraseType for Option<&'_ T> {
+    type Result = [u8; size_of::>()];
+}
+
+impl EraseType for Option<&'_ [T]> {
+    type Result = [u8; size_of::>()];
+}
+
+impl EraseType for Option> {
+    type Result = [u8; size_of::>>()];
+}
+
+impl EraseType for Option> {
+    type Result = [u8; size_of::>>()];
+}
+
+impl EraseType for Option>> {
+    type Result = [u8; size_of::>>>()];
+}
+
+impl EraseType for Option>> {
+    type Result = [u8; size_of::>>>()];
+}
+
+impl EraseType for rustc_hir::MaybeOwner<&'_ T> {
+    type Result = [u8; size_of::>()];
+}
+
+impl EraseType for ty::EarlyBinder {
+    type Result = T::Result;
+}
+
+impl EraseType for ty::Binder<'_, ty::FnSig<'_>> {
+    type Result = [u8; size_of::>>()];
+}
+
+impl EraseType for (&'_ T0, &'_ T1) {
+    type Result = [u8; size_of::<(&'static (), &'static ())>()];
+}
+
+impl EraseType for (&'_ T0, &'_ [T1]) {
+    type Result = [u8; size_of::<(&'static (), &'static [()])>()];
 }
 
 macro_rules! trivial {
@@ -94,6 +192,27 @@ macro_rules! trivial {
 trivial! {
     (),
     bool,
+    Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Option,
+    Result<(), rustc_errors::ErrorGuaranteed>,
+    Result<(), rustc_middle::traits::query::NoSolution>,
+    Result,
     rustc_ast::expand::allocator::AllocatorKind,
     rustc_attr::ConstStability,
     rustc_attr::DefaultBodyStability,
@@ -144,6 +263,7 @@ trivial! {
     rustc_middle::ty::ReprOptions,
     rustc_middle::ty::UnusedGenericParams,
     rustc_middle::ty::util::AlwaysRequiresDrop,
+    rustc_middle::ty::Visibility,
     rustc_session::config::CrateType,
     rustc_session::config::EntryFnType,
     rustc_session::config::OptLevel,

From 5cb23e4a439df21e90d5a4789b5d61b2586ee2d2 Mon Sep 17 00:00:00 2001
From: Scott McMurray 
Date: Wed, 5 Apr 2023 14:46:09 -0700
Subject: [PATCH 162/267] Remove f32 & f64 from MemDecoder/MemEncoder

---
 compiler/rustc_metadata/src/rmeta/encoder.rs  |  2 --
 compiler/rustc_middle/src/ty/codec.rs         |  2 --
 .../rustc_query_impl/src/on_disk_cache.rs     |  2 --
 compiler/rustc_serialize/src/opaque.rs        | 36 -------------------
 compiler/rustc_serialize/src/serialize.rs     | 16 +++++----
 compiler/rustc_serialize/tests/opaque.rs      | 32 +++--------------
 6 files changed, 14 insertions(+), 76 deletions(-)

diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 2652a4280d37..5a30371a8456 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -112,8 +112,6 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
         emit_i8(i8);
 
         emit_bool(bool);
-        emit_f64(f64);
-        emit_f32(f32);
         emit_char(char);
         emit_str(&str);
         emit_raw_bytes(&[u8]);
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 3ce80e06ad9e..8ef4a46a733a 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -511,8 +511,6 @@ macro_rules! implement_ty_decoder {
                     read_isize -> isize;
 
                     read_bool -> bool;
-                    read_f64 -> f64;
-                    read_f32 -> f32;
                     read_char -> char;
                     read_str -> &str;
                 }
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 35b7e5919e42..9aa8231dcdae 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -1046,8 +1046,6 @@ impl<'a, 'tcx> Encoder for CacheEncoder<'a, 'tcx> {
         emit_i8(i8);
 
         emit_bool(bool);
-        emit_f64(f64);
-        emit_f32(f32);
         emit_char(char);
         emit_str(&str);
         emit_raw_bytes(&[u8]);
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 0e0ebc79eb2e..53e5c8967365 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -122,18 +122,6 @@ impl Encoder for MemEncoder {
         self.emit_u8(if v { 1 } else { 0 });
     }
 
-    #[inline]
-    fn emit_f64(&mut self, v: f64) {
-        let as_u64: u64 = v.to_bits();
-        self.emit_u64(as_u64);
-    }
-
-    #[inline]
-    fn emit_f32(&mut self, v: f32) {
-        let as_u32: u32 = v.to_bits();
-        self.emit_u32(as_u32);
-    }
-
     #[inline]
     fn emit_char(&mut self, v: char) {
         self.emit_u32(v as u32);
@@ -500,18 +488,6 @@ impl Encoder for FileEncoder {
         self.emit_u8(if v { 1 } else { 0 });
     }
 
-    #[inline]
-    fn emit_f64(&mut self, v: f64) {
-        let as_u64: u64 = v.to_bits();
-        self.emit_u64(as_u64);
-    }
-
-    #[inline]
-    fn emit_f32(&mut self, v: f32) {
-        let as_u32: u32 = v.to_bits();
-        self.emit_u32(as_u32);
-    }
-
     #[inline]
     fn emit_char(&mut self, v: char) {
         self.emit_u32(v as u32);
@@ -642,18 +618,6 @@ impl<'a> Decoder for MemDecoder<'a> {
         value != 0
     }
 
-    #[inline]
-    fn read_f64(&mut self) -> f64 {
-        let bits = self.read_u64();
-        f64::from_bits(bits)
-    }
-
-    #[inline]
-    fn read_f32(&mut self) -> f32 {
-        let bits = self.read_u32();
-        f32::from_bits(bits)
-    }
-
     #[inline]
     fn read_char(&mut self) -> char {
         let bits = self.read_u32();
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index 567fe06109b7..527abc237271 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -22,6 +22,11 @@ use std::sync::Arc;
 /// be processed or ignored, whichever is appropriate. Then they should provide
 /// a `finish` method that finishes up encoding. If the encoder is fallible,
 /// `finish` should return a `Result` that indicates success or failure.
+///
+/// This current does not support `f32` nor `f64`, as they're not needed in any
+/// serialized data structures. That could be changed, but consider whether it
+/// really makes sense to store floating-point values at all.
+/// (If you need it, revert .)
 pub trait Encoder {
     // Primitive types:
     fn emit_usize(&mut self, v: usize);
@@ -37,8 +42,6 @@ pub trait Encoder {
     fn emit_i16(&mut self, v: i16);
     fn emit_i8(&mut self, v: i8);
     fn emit_bool(&mut self, v: bool);
-    fn emit_f64(&mut self, v: f64);
-    fn emit_f32(&mut self, v: f32);
     fn emit_char(&mut self, v: char);
     fn emit_str(&mut self, v: &str);
     fn emit_raw_bytes(&mut self, s: &[u8]);
@@ -58,6 +61,11 @@ pub trait Encoder {
 // top-level invocation would also just panic on failure. Switching to
 // infallibility made things faster and lots of code a little simpler and more
 // concise.
+///
+/// This current does not support `f32` nor `f64`, as they're not needed in any
+/// serialized data structures. That could be changed, but consider whether it
+/// really makes sense to store floating-point values at all.
+/// (If you need it, revert .)
 pub trait Decoder {
     // Primitive types:
     fn read_usize(&mut self) -> usize;
@@ -73,8 +81,6 @@ pub trait Decoder {
     fn read_i16(&mut self) -> i16;
     fn read_i8(&mut self) -> i8;
     fn read_bool(&mut self) -> bool;
-    fn read_f64(&mut self) -> f64;
-    fn read_f32(&mut self) -> f32;
     fn read_char(&mut self) -> char;
     fn read_str(&mut self) -> &str;
     fn read_raw_bytes(&mut self, len: usize) -> &[u8];
@@ -143,8 +149,6 @@ direct_serialize_impls! {
     i64 emit_i64 read_i64,
     i128 emit_i128 read_i128,
 
-    f32 emit_f32 read_f32,
-    f64 emit_f64 read_f64,
     bool emit_bool read_bool,
     char emit_char read_char
 }
diff --git a/compiler/rustc_serialize/tests/opaque.rs b/compiler/rustc_serialize/tests/opaque.rs
index 3a695d0714ee..5e7dd18aa840 100644
--- a/compiler/rustc_serialize/tests/opaque.rs
+++ b/compiler/rustc_serialize/tests/opaque.rs
@@ -22,8 +22,6 @@ struct Struct {
 
     l: char,
     m: String,
-    n: f32,
-    o: f64,
     p: bool,
     q: Option,
 }
@@ -119,24 +117,6 @@ fn test_bool() {
     check_round_trip(vec![false, true, true, false, false]);
 }
 
-#[test]
-fn test_f32() {
-    let mut vec = vec![];
-    for i in -100..100 {
-        vec.push((i as f32) / 3.0);
-    }
-    check_round_trip(vec);
-}
-
-#[test]
-fn test_f64() {
-    let mut vec = vec![];
-    for i in -100..100 {
-        vec.push((i as f64) / 3.0);
-    }
-    check_round_trip(vec);
-}
-
 #[test]
 fn test_char() {
     let vec = vec!['a', 'b', 'c', 'd', 'A', 'X', ' ', '#', 'Ö', 'Ä', 'µ', '€'];
@@ -200,8 +180,6 @@ fn test_struct() {
 
         l: 'x',
         m: "abc".to_string(),
-        n: 20.5,
-        o: 21.5,
         p: false,
         q: None,
     }]);
@@ -222,8 +200,6 @@ fn test_struct() {
 
         l: 'y',
         m: "def".to_string(),
-        n: -20.5,
-        o: -21.5,
         p: true,
         q: Some(1234567),
     }]);
@@ -232,7 +208,7 @@ fn test_struct() {
 #[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
 enum Enum {
     Variant1,
-    Variant2(usize, f32),
+    Variant2(usize, u32),
     Variant3 { a: i32, b: char, c: bool },
 }
 
@@ -240,7 +216,7 @@ enum Enum {
 fn test_enum() {
     check_round_trip(vec![
         Enum::Variant1,
-        Enum::Variant2(1, 2.5),
+        Enum::Variant2(1, 25),
         Enum::Variant3 { a: 3, b: 'b', c: false },
         Enum::Variant3 { a: -4, b: 'f', c: true },
     ]);
@@ -269,8 +245,8 @@ fn test_hash_map() {
 
 #[test]
 fn test_tuples() {
-    check_round_trip(vec![('x', (), false, 0.5f32)]);
-    check_round_trip(vec![(9i8, 10u16, 1.5f64)]);
+    check_round_trip(vec![('x', (), false, 5u32)]);
+    check_round_trip(vec![(9i8, 10u16, 15i64)]);
     check_round_trip(vec![(-12i16, 11u8, 12usize)]);
     check_round_trip(vec![(1234567isize, 100000000000000u64, 99999999999999i64)]);
     check_round_trip(vec![(String::new(), "some string".to_string())]);

From 502cb6f4b9ccb4ead43b76949252bf087b6d2c05 Mon Sep 17 00:00:00 2001
From: Sergei Belokon 
Date: Thu, 6 Apr 2023 18:32:01 +1000
Subject: [PATCH 163/267] chore(tcp): change the hardcoded port number to
 `port` var

The `listen_on` function in the example has a `port` option but doesn't
use it
---
 library/std/src/net/tcp.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 3982d3636614..6a5f2923210d 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -869,7 +869,7 @@ impl TcpListener {
     /// use std::net::{TcpListener, TcpStream};
     ///
     /// fn listen_on(port: u16) -> impl Iterator {
-    ///     let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+    ///     let listener = TcpListener::bind(format!("127.0.0.1:{port}")).unwrap();
     ///     listener.into_incoming()
     ///         .filter_map(Result::ok) /* Ignore failed connections */
     /// }

From daeb844e0ccddb9e058128974b290f2022e88be7 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Sat, 8 Oct 2022 23:47:59 +0100
Subject: [PATCH 164/267] Refactor unwind from Option to a new enum

---
 .../src/diagnostics/find_use.rs               |   7 +-
 compiler/rustc_borrowck/src/invalidation.rs   |   6 +-
 compiler/rustc_borrowck/src/lib.rs            |   6 +-
 compiler/rustc_borrowck/src/type_check/mod.rs |  14 +-
 compiler/rustc_codegen_cranelift/src/base.rs  |   6 +-
 compiler/rustc_codegen_ssa/src/mir/analyze.rs |   8 +-
 compiler/rustc_codegen_ssa/src/mir/block.rs   |  46 +++---
 .../src/const_eval/machine.rs                 |   2 +-
 .../rustc_const_eval/src/interpret/machine.rs |   2 +-
 .../src/interpret/terminator.rs               |  20 +--
 .../src/transform/promote_consts.rs           |   2 +-
 .../src/transform/validate.rs                 |  18 +--
 compiler/rustc_middle/src/mir/syntax.rs       |  41 +++--
 compiler/rustc_middle/src/mir/terminator.rs   | 144 +++++++++---------
 compiler/rustc_middle/src/mir/visit.rs        |   6 +-
 .../src/build/expr/as_rvalue.rs               |   8 +-
 .../rustc_mir_build/src/build/expr/into.rs    |   9 +-
 .../rustc_mir_build/src/build/matches/test.rs |   4 +-
 compiler/rustc_mir_build/src/build/scope.rs   |  30 +++-
 compiler/rustc_mir_build/src/lints.rs         |   6 +-
 .../rustc_mir_dataflow/src/elaborate_drops.rs |  16 +-
 .../src/framework/direction.rs                |  14 +-
 .../rustc_mir_dataflow/src/framework/tests.rs |   4 +-
 .../src/move_paths/builder.rs                 |   4 +-
 .../src/abort_unwinding_calls.rs              |   4 +-
 .../src/add_call_guards.rs                    |   4 +-
 .../rustc_mir_transform/src/const_prop.rs     |   2 +-
 .../rustc_mir_transform/src/coverage/tests.rs |   2 +-
 .../src/elaborate_drops.rs                    |  20 ++-
 .../src/function_item_references.rs           |   2 +-
 compiler/rustc_mir_transform/src/generator.rs |  20 ++-
 compiler/rustc_mir_transform/src/inline.rs    |  57 +++----
 compiler/rustc_mir_transform/src/lib.rs       |   4 +-
 .../src/lower_slice_len.rs                    |   2 +-
 .../src/remove_noop_landing_pads.rs           |   4 +-
 compiler/rustc_mir_transform/src/shim.rs      |  26 +++-
 .../clippy_utils/src/qualify_min_const_fn.rs  |   4 +-
 src/tools/miri/src/machine.rs                 |   2 +-
 src/tools/miri/src/shims/panic.rs             |   2 +-
 39 files changed, 328 insertions(+), 250 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index fd1fda2ee4bd..e2d04324f3b6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -11,7 +11,7 @@ use crate::{
 };
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
-use rustc_middle::mir::{Body, Local, Location};
+use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{RegionVid, TyCtxt};
 
 pub(crate) fn find<'tcx>(
@@ -70,7 +70,10 @@ impl<'cx, 'tcx> UseFinder<'cx, 'tcx> {
                             block_data
                                 .terminator()
                                 .successors()
-                                .filter(|&bb| Some(&Some(bb)) != block_data.terminator().unwind())
+                                .filter(|&bb| {
+                                    Some(&mir::UnwindAction::Cleanup(bb))
+                                        != block_data.terminator().unwind()
+                                })
                                 .map(|bb| Location { statement_index: 0, block: bb }),
                         );
                     }
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index a71c41632861..f69b35549b41 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -125,7 +125,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 args,
                 destination,
                 target: _,
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -135,7 +135,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 }
                 self.mutate_place(location, *destination, Deep);
             }
-            TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
                 self.consume_operand(location, cond);
                 use rustc_middle::mir::AssertKind;
                 if let AssertKind::BoundsCheck { len, index } = msg {
@@ -173,7 +173,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 options: _,
                 line_spans: _,
                 destination: _,
-                cleanup: _,
+                unwind: _,
             } => {
                 for op in operands {
                     match op {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 1d4d1406239d..4787b0ea4e9d 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -740,7 +740,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                 args,
                 destination,
                 target: _,
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -750,7 +750,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                 }
                 self.mutate_place(loc, (*destination, span), Deep, flow_state);
             }
-            TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
                 self.consume_operand(loc, (cond, span), flow_state);
                 use rustc_middle::mir::AssertKind;
                 if let AssertKind::BoundsCheck { len, index } = msg {
@@ -770,7 +770,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                 options: _,
                 line_spans: _,
                 destination: _,
-                cleanup: _,
+                unwind: _,
             } => {
                 for op in operands {
                     match op {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 2fc4e32ecb24..10332c6d9b5f 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1610,20 +1610,20 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::Unreachable => {}
             TerminatorKind::Drop { target, unwind, .. }
-            | TerminatorKind::Assert { target, cleanup: unwind, .. } => {
+            | TerminatorKind::Assert { target, unwind, .. } => {
                 self.assert_iscleanup(body, block_data, target, is_cleanup);
-                if let Some(unwind) = unwind {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     if is_cleanup {
                         span_mirbug!(self, block_data, "unwind on cleanup block")
                     }
                     self.assert_iscleanup(body, block_data, unwind, true);
                 }
             }
-            TerminatorKind::Call { ref target, cleanup, .. } => {
+            TerminatorKind::Call { ref target, unwind, .. } => {
                 if let &Some(target) = target {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
-                if let Some(cleanup) = cleanup {
+                if let UnwindAction::Cleanup(cleanup) = unwind {
                     if is_cleanup {
                         span_mirbug!(self, block_data, "cleanup on cleanup block")
                     }
@@ -1636,18 +1636,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::FalseUnwind { real_target, unwind } => {
                 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
-                if let Some(unwind) = unwind {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     if is_cleanup {
                         span_mirbug!(self, block_data, "cleanup in cleanup block via false unwind");
                     }
                     self.assert_iscleanup(body, block_data, unwind, true);
                 }
             }
-            TerminatorKind::InlineAsm { destination, cleanup, .. } => {
+            TerminatorKind::InlineAsm { destination, unwind, .. } => {
                 if let Some(target) = destination {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
-                if let Some(cleanup) = cleanup {
+                if let UnwindAction::Cleanup(cleanup) = unwind {
                     if is_cleanup {
                         span_mirbug!(self, block_data, "cleanup on cleanup block")
                     }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 2630f02e6eb3..94413318492f 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -345,7 +345,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
             TerminatorKind::Return => {
                 crate::abi::codegen_return(fx);
             }
-            TerminatorKind::Assert { cond, expected, msg, target, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected, msg, target, unwind: _ } => {
                 if !fx.tcx.sess.overflow_checks() && msg.is_optional_overflow_check() {
                     let target = fx.get_block(*target);
                     fx.bcx.ins().jump(target, &[]);
@@ -450,7 +450,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                 destination,
                 target,
                 fn_span,
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
             } => {
                 fx.tcx.prof.generic_activity("codegen call").run(|| {
@@ -470,7 +470,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                 options,
                 destination,
                 line_spans: _,
-                cleanup: _,
+                unwind: _,
             } => {
                 if options.contains(InlineAsmOptions::MAY_UNWIND) {
                     fx.tcx.sess.span_fatal(
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index dcf533dc39c3..7d1c80ba88f8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -292,11 +292,11 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec { /* nothing to do */ }
-                TerminatorKind::Call { cleanup: unwind, .. }
-                | TerminatorKind::InlineAsm { cleanup: unwind, .. }
-                | TerminatorKind::Assert { cleanup: unwind, .. }
+                TerminatorKind::Call { unwind, .. }
+                | TerminatorKind::InlineAsm { unwind, .. }
+                | TerminatorKind::Assert { unwind, .. }
                 | TerminatorKind::Drop { unwind, .. } => {
-                    if let Some(unwind) = unwind {
+                    if let mir::UnwindAction::Cleanup(unwind) = unwind {
                         debug!(
                             "cleanup_kinds: {:?}/{:?} registering {:?} as funclet",
                             bb, data, unwind
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index c086d1b7f5a3..a6891a8ff2f9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -156,7 +156,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         fn_ptr: Bx::Value,
         llargs: &[Bx::Value],
         destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
-        cleanup: Option,
+        unwind: mir::UnwindAction,
         copied_constant_arguments: &[PlaceRef<'tcx, ::Value>],
         mergeable_succ: bool,
     ) -> MergingSucc {
@@ -164,6 +164,10 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         // do an invoke, otherwise do a call.
         let fn_ty = bx.fn_decl_backend_type(&fn_abi);
 
+        let cleanup = match unwind {
+            mir::UnwindAction::Cleanup(cleanup) => Some(cleanup),
+            mir::UnwindAction::Continue => None,
+        };
         let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
             Some(self.llbb_with_cleanup(fx, cleanup))
         } else if fx.mir[self.bb].is_cleanup
@@ -244,11 +248,11 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         options: InlineAsmOptions,
         line_spans: &[Span],
         destination: Option,
-        cleanup: Option,
+        unwind: mir::UnwindAction,
         instance: Instance<'_>,
         mergeable_succ: bool,
     ) -> MergingSucc {
-        if let Some(cleanup) = cleanup {
+        if let mir::UnwindAction::Cleanup(cleanup) = unwind {
             let ret_llbb = if let Some(target) = destination {
                 fx.llbb(target)
             } else {
@@ -431,7 +435,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         bx: &mut Bx,
         location: mir::Place<'tcx>,
         target: mir::BasicBlock,
-        unwind: Option,
+        unwind: mir::UnwindAction,
         mergeable_succ: bool,
     ) -> MergingSucc {
         let ty = location.ty(self.mir, bx.tcx()).ty;
@@ -552,7 +556,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         expected: bool,
         msg: &mir::AssertMessage<'tcx>,
         target: mir::BasicBlock,
-        cleanup: Option,
+        unwind: mir::UnwindAction,
         mergeable_succ: bool,
     ) -> MergingSucc {
         let span = terminator.source_info.span;
@@ -618,7 +622,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let (fn_abi, llfn) = common::build_langcall(bx, Some(span), lang_item);
 
         // Codegen the actual panic invoke/call.
-        let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, cleanup, &[], false);
+        let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], false);
         assert_eq!(merging_succ, MergingSucc::False);
         MergingSucc::False
     }
@@ -636,7 +640,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind);
 
         // Codegen the actual panic invoke/call.
-        let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &[], None, None, &[], false);
+        let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &[], None, mir::UnwindAction::Continue, &[], false);
         assert_eq!(merging_succ, MergingSucc::False);
     }
 
@@ -649,7 +653,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         instance: Option>,
         source_info: mir::SourceInfo,
         target: Option,
-        cleanup: Option,
+        unwind: mir::UnwindAction,
         mergeable_succ: bool,
     ) -> Option {
         // Emit a panic or a no-op for `assert_*` intrinsics.
@@ -696,7 +700,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     llfn,
                     &[msg.0, msg.1],
                     target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
-                    cleanup,
+                    unwind,
                     &[],
                     mergeable_succ,
                 )
@@ -719,7 +723,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         args: &[mir::Operand<'tcx>],
         destination: mir::Place<'tcx>,
         target: Option,
-        cleanup: Option,
+        unwind: mir::UnwindAction,
         fn_span: Span,
         mergeable_succ: bool,
     ) -> MergingSucc {
@@ -783,7 +787,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             instance,
             source_info,
             target,
-            cleanup,
+            unwind,
             mergeable_succ,
         ) {
             return merging_succ;
@@ -1064,7 +1068,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 fn_ptr,
                 &llargs,
                 target.as_ref().map(|&target| (ret_dest, target)),
-                cleanup,
+                unwind,
                 &copied_constant_arguments,
                 false,
             );
@@ -1084,7 +1088,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             fn_ptr,
             &llargs,
             target.as_ref().map(|&target| (ret_dest, target)),
-            cleanup,
+            unwind,
             &copied_constant_arguments,
             mergeable_succ,
         )
@@ -1100,7 +1104,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         options: ast::InlineAsmOptions,
         line_spans: &[Span],
         destination: Option,
-        cleanup: Option,
+        unwind: mir::UnwindAction,
         instance: Instance<'_>,
         mergeable_succ: bool,
     ) -> MergingSucc {
@@ -1164,7 +1168,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             options,
             line_spans,
             destination,
-            cleanup,
+            unwind,
             instance,
             mergeable_succ,
         )
@@ -1274,7 +1278,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 self.codegen_drop_terminator(helper, bx, place, target, unwind, mergeable_succ())
             }
 
-            mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => self
+            mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self
                 .codegen_assert_terminator(
                     helper,
                     bx,
@@ -1283,7 +1287,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     expected,
                     msg,
                     target,
-                    cleanup,
+                    unwind,
                     mergeable_succ(),
                 ),
 
@@ -1292,7 +1296,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 ref args,
                 destination,
                 target,
-                cleanup,
+                unwind,
                 from_hir_call: _,
                 fn_span,
             } => self.codegen_call_terminator(
@@ -1303,7 +1307,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 args,
                 destination,
                 target,
-                cleanup,
+                unwind,
                 fn_span,
                 mergeable_succ(),
             ),
@@ -1320,7 +1324,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 options,
                 line_spans,
                 destination,
-                cleanup,
+                unwind,
             } => self.codegen_asm_terminator(
                 helper,
                 bx,
@@ -1330,7 +1334,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 options,
                 line_spans,
                 destination,
-                cleanup,
+                unwind,
                 self.instance,
                 mergeable_succ(),
             ),
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index c87ea18af4f4..5fd99a9a84ac 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -526,7 +526,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     fn assert_panic(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         msg: &AssertMessage<'tcx>,
-        _unwind: Option,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         use rustc_middle::mir::AssertKind::*;
         // Convert `AssertKind` to `AssertKind`.
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index aca68dc454be..ca4da29ebbd3 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -215,7 +215,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     fn assert_panic(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         msg: &mir::AssertMessage<'tcx>,
-        unwind: Option,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
 
     /// Called to evaluate `Abort` MIR terminator.
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 2d9fee9852cc..2546423d4cce 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -60,7 +60,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 ref args,
                 destination,
                 target,
-                ref cleanup,
+                ref unwind,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -106,9 +106,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     with_caller_location,
                     &destination,
                     target,
-                    match (cleanup, fn_abi.can_unwind) {
-                        (Some(cleanup), true) => StackPopUnwind::Cleanup(*cleanup),
-                        (None, true) => StackPopUnwind::Skip,
+                    match (unwind, fn_abi.can_unwind) {
+                        (mir::UnwindAction::Cleanup(cleanup), true) => {
+                            StackPopUnwind::Cleanup(*cleanup)
+                        }
+                        (mir::UnwindAction::Continue, true) => StackPopUnwind::Skip,
                         (_, false) => StackPopUnwind::NotAllowed,
                     },
                 )?;
@@ -137,14 +139,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.drop_in_place(&place, instance, target, unwind)?;
             }
 
-            Assert { ref cond, expected, ref msg, target, cleanup } => {
+            Assert { ref cond, expected, ref msg, target, unwind } => {
                 let ignored =
                     M::ignore_optional_overflow_checks(self) && msg.is_optional_overflow_check();
                 let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?;
                 if ignored || expected == cond_val {
                     self.go_to_block(target);
                 } else {
-                    M::assert_panic(self, msg, cleanup)?;
+                    M::assert_panic(self, msg, unwind)?;
                 }
             }
 
@@ -676,7 +678,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         place: &PlaceTy<'tcx, M::Provenance>,
         instance: ty::Instance<'tcx>,
         target: mir::BasicBlock,
-        unwind: Option,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         trace!("drop_in_place: {:?},\n  {:?}, {:?}", *place, place.layout.ty, instance);
         // We take the address of the object. This may well be unaligned, which is fine
@@ -718,8 +720,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             &ret.into(),
             Some(target),
             match unwind {
-                Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
-                None => StackPopUnwind::Skip,
+                mir::UnwindAction::Cleanup(cleanup) => StackPopUnwind::Cleanup(cleanup),
+                mir::UnwindAction::Continue => StackPopUnwind::Skip,
             },
         )
     }
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 6774e5a58376..7919aed097a4 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -807,7 +807,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                         kind: TerminatorKind::Call {
                             func,
                             args,
-                            cleanup: None,
+                            unwind: UnwindAction::Continue,
                             destination: Place::from(new_temp),
                             target: Some(new_target),
                             from_hir_call,
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index e798c9d236e1..be840ef6f7f7 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::{
     traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
     MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem,
     RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
-    TerminatorKind, UnOp, VarDebugInfo, VarDebugInfoContents, START_BLOCK,
+    TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, START_BLOCK,
 };
 use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
 use rustc_mir_dataflow::impls::MaybeStorageLive;
@@ -902,11 +902,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::Drop { target, unwind, .. } => {
                 self.check_edge(location, *target, EdgeKind::Normal);
-                if let Some(unwind) = unwind {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     self.check_edge(location, *unwind, EdgeKind::Unwind);
                 }
             }
-            TerminatorKind::Call { func, args, destination, target, cleanup, .. } => {
+            TerminatorKind::Call { func, args, destination, target, unwind, .. } => {
                 let func_ty = func.ty(&self.body.local_decls, self.tcx);
                 match func_ty.kind() {
                     ty::FnPtr(..) | ty::FnDef(..) => {}
@@ -918,7 +918,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 if let Some(target) = target {
                     self.check_edge(location, *target, EdgeKind::Normal);
                 }
-                if let Some(cleanup) = cleanup {
+                if let UnwindAction::Cleanup(cleanup) = unwind {
                     self.check_edge(location, *cleanup, EdgeKind::Unwind);
                 }
 
@@ -946,7 +946,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            TerminatorKind::Assert { cond, target, cleanup, .. } => {
+            TerminatorKind::Assert { cond, target, unwind, .. } => {
                 let cond_ty = cond.ty(&self.body.local_decls, self.tcx);
                 if cond_ty != self.tcx.types.bool {
                     self.fail(
@@ -958,7 +958,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
                 self.check_edge(location, *target, EdgeKind::Normal);
-                if let Some(cleanup) = cleanup {
+                if let UnwindAction::Cleanup(cleanup) = unwind {
                     self.check_edge(location, *cleanup, EdgeKind::Unwind);
                 }
             }
@@ -992,15 +992,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
                 self.check_edge(location, *real_target, EdgeKind::Normal);
-                if let Some(unwind) = unwind {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     self.check_edge(location, *unwind, EdgeKind::Unwind);
                 }
             }
-            TerminatorKind::InlineAsm { destination, cleanup, .. } => {
+            TerminatorKind::InlineAsm { destination, unwind, .. } => {
                 if let Some(destination) = destination {
                     self.check_edge(location, *destination, EdgeKind::Normal);
                 }
-                if let Some(cleanup) = cleanup {
+                if let UnwindAction::Cleanup(cleanup) = unwind {
                     self.check_edge(location, *cleanup, EdgeKind::Unwind);
                 }
             }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index cc35e6106e29..c2a12bb3b662 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -515,14 +515,14 @@ pub struct CopyNonOverlapping<'tcx> {
 ///
 /// A note on unwinding: Panics may occur during the execution of some terminators. Depending on the
 /// `-C panic` flag, this may either cause the program to abort or the call stack to unwind. Such
-/// terminators have a `cleanup: Option` field on them. If stack unwinding occurs, then
-/// once the current function is reached, execution continues at the given basic block, if any. If
-/// `cleanup` is `None` then no cleanup is performed, and the stack continues unwinding. This is
-/// equivalent to the execution of a `Resume` terminator.
+/// terminators have a `unwind: UnwindAction` field on them. If stack unwinding occurs, then
+/// once the current function is reached, an action will be taken based on the `unwind` field.
+/// If the action is `Cleanup`, then the execution continues at the given basic block. If the
+/// action is `Continue` then no cleanup is performed, and the stack continues unwinding.
 ///
-/// The basic block pointed to by a `cleanup` field must have its `cleanup` flag set. `cleanup`
-/// basic blocks have a couple restrictions:
-///  1. All `cleanup` fields in them must be `None`.
+/// The basic block pointed to by a `Cleanup` unwind action must have its `cleanup` flag set.
+/// `cleanup` basic blocks have a couple restrictions:
+///  1. All `unwind` fields in them must be `UnwindAction::Continue`.
 ///  2. `Return` terminators are not allowed in them. `Abort` and `Unwind` terminators are.
 ///  3. All other basic blocks (in the current body) that are reachable from `cleanup` basic blocks
 ///     must also be `cleanup`. This is a part of the type system and checked statically, so it is
@@ -604,7 +604,7 @@ pub enum TerminatorKind<'tcx> {
     /// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to
     /// > the place or one of its "parents" occurred more recently than a move out of it. This does not
     /// > consider indirect assignments.
-    Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option },
+    Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction },
 
     /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
     /// the referred to function. The operand types must match the argument types of the function.
@@ -628,8 +628,8 @@ pub enum TerminatorKind<'tcx> {
         destination: Place<'tcx>,
         /// Where to go after this call returns. If none, the call necessarily diverges.
         target: Option,
-        /// Cleanups to be done if the call unwinds.
-        cleanup: Option,
+        /// Action to be taken if the call unwinds.
+        unwind: UnwindAction,
         /// `true` if this is from a call in HIR rather than from an overloaded
         /// operator. True for overloaded function call.
         from_hir_call: bool,
@@ -654,7 +654,7 @@ pub enum TerminatorKind<'tcx> {
         expected: bool,
         msg: AssertMessage<'tcx>,
         target: BasicBlock,
-        cleanup: Option,
+        unwind: UnwindAction,
     },
 
     /// Marks a suspend point.
@@ -720,9 +720,10 @@ pub enum TerminatorKind<'tcx> {
         /// in practice, but in order to avoid fragility we want to always
         /// consider it in borrowck. We don't want to accept programs which
         /// pass borrowck only when `panic=abort` or some assertions are disabled
-        /// due to release vs. debug mode builds. This needs to be an `Option` because
+        /// due to release vs. debug mode builds.
+        /// This field does not necessary have to be `UnwindAction::Cleanup` because
         /// of the `remove_noop_landing_pads` and `abort_unwinding_calls` passes.
-        unwind: Option,
+        unwind: UnwindAction,
     },
 
     /// Block ends with an inline assembly block. This is a terminator since
@@ -745,12 +746,22 @@ pub enum TerminatorKind<'tcx> {
         /// diverging (InlineAsmOptions::NORETURN).
         destination: Option,
 
-        /// Cleanup to be done if the inline assembly unwinds. This is present
+        /// Action to be taken if the inline assembly unwinds. This is present
         /// if and only if InlineAsmOptions::MAY_UNWIND is set.
-        cleanup: Option,
+        unwind: UnwindAction,
     },
 }
 
+/// Action to be taken when a stack unwind happens.
+#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub enum UnwindAction {
+    // No action is to be taken. Continue unwinding.
+    Continue,
+    // Cleanups to be done.
+    Cleanup(BasicBlock),
+}
+
 /// Information about an assertion failure.
 #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
 pub enum AssertKind {
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index cd970270727f..19aa01c12bd4 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -1,6 +1,6 @@
 use smallvec::SmallVec;
 
-use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind};
+use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction};
 use rustc_ast::InlineAsmTemplatePiece;
 pub use rustc_ast::Mutability;
 use rustc_macros::HashStable;
@@ -118,11 +118,11 @@ impl<'tcx> Terminator<'tcx> {
         self.kind.successors_mut()
     }
 
-    pub fn unwind(&self) -> Option<&Option> {
+    pub fn unwind(&self) -> Option<&UnwindAction> {
         self.kind.unwind()
     }
 
-    pub fn unwind_mut(&mut self) -> Option<&mut Option> {
+    pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> {
         self.kind.unwind_mut()
     }
 }
@@ -135,34 +135,34 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn successors(&self) -> Successors<'_> {
         use self::TerminatorKind::*;
         match *self {
+            Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. }
+            | Yield { resume: t, drop: Some(ref u), .. }
+            | Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
+            | Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
+            | FalseUnwind { real_target: t, unwind: UnwindAction::Cleanup(ref u) }
+            | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => {
+                Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
+            }
+            Goto { target: t }
+            | Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
+            | Call { target: Some(t), unwind: _, .. }
+            | Yield { resume: t, drop: None, .. }
+            | Drop { target: t, unwind: _, .. }
+            | Assert { target: t, unwind: _, .. }
+            | FalseUnwind { real_target: t, unwind: _ }
+            | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
+            | InlineAsm { destination: Some(t), unwind: _, .. } => {
+                Some(t).into_iter().chain((&[]).into_iter().copied())
+            }
             Resume
             | Abort
             | GeneratorDrop
             | Return
             | Unreachable
-            | Call { target: None, cleanup: None, .. }
-            | InlineAsm { destination: None, cleanup: None, .. } => {
+            | Call { target: None, unwind: _, .. }
+            | InlineAsm { destination: None, unwind: _, .. } => {
                 None.into_iter().chain((&[]).into_iter().copied())
             }
-            Goto { target: t }
-            | Call { target: None, cleanup: Some(t), .. }
-            | Call { target: Some(t), cleanup: None, .. }
-            | Yield { resume: t, drop: None, .. }
-            | Drop { target: t, unwind: None, .. }
-            | Assert { target: t, cleanup: None, .. }
-            | FalseUnwind { real_target: t, unwind: None }
-            | InlineAsm { destination: Some(t), cleanup: None, .. }
-            | InlineAsm { destination: None, cleanup: Some(t), .. } => {
-                Some(t).into_iter().chain((&[]).into_iter().copied())
-            }
-            Call { target: Some(t), cleanup: Some(ref u), .. }
-            | Yield { resume: t, drop: Some(ref u), .. }
-            | Drop { target: t, unwind: Some(ref u), .. }
-            | Assert { target: t, cleanup: Some(ref u), .. }
-            | FalseUnwind { real_target: t, unwind: Some(ref u) }
-            | InlineAsm { destination: Some(t), cleanup: Some(ref u), .. } => {
-                Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
-            }
             SwitchInt { ref targets, .. } => {
                 None.into_iter().chain(targets.targets.iter().copied())
             }
@@ -175,32 +175,34 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
         use self::TerminatorKind::*;
         match *self {
+            Call { target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), .. }
+            | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
+            | Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
+            | Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
+            | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) }
+            | InlineAsm {
+                destination: Some(ref mut t),
+                unwind: UnwindAction::Cleanup(ref mut u),
+                ..
+            } => Some(t).into_iter().chain(slice::from_mut(u)),
+            Goto { target: ref mut t }
+            | Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
+            | Call { target: Some(ref mut t), unwind: _, .. }
+            | Yield { resume: ref mut t, drop: None, .. }
+            | Drop { target: ref mut t, unwind: _, .. }
+            | Assert { target: ref mut t, unwind: _, .. }
+            | FalseUnwind { real_target: ref mut t, unwind: _ }
+            | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
+            | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
+                Some(t).into_iter().chain(&mut [])
+            }
             Resume
             | Abort
             | GeneratorDrop
             | Return
             | Unreachable
-            | Call { target: None, cleanup: None, .. }
-            | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []),
-            Goto { target: ref mut t }
-            | Call { target: None, cleanup: Some(ref mut t), .. }
-            | Call { target: Some(ref mut t), cleanup: None, .. }
-            | Yield { resume: ref mut t, drop: None, .. }
-            | Drop { target: ref mut t, unwind: None, .. }
-            | Assert { target: ref mut t, cleanup: None, .. }
-            | FalseUnwind { real_target: ref mut t, unwind: None }
-            | InlineAsm { destination: Some(ref mut t), cleanup: None, .. }
-            | InlineAsm { destination: None, cleanup: Some(ref mut t), .. } => {
-                Some(t).into_iter().chain(&mut [])
-            }
-            Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. }
-            | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
-            | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
-            | Assert { target: ref mut t, cleanup: Some(ref mut u), .. }
-            | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) }
-            | InlineAsm { destination: Some(ref mut t), cleanup: Some(ref mut u), .. } => {
-                Some(t).into_iter().chain(slice::from_mut(u))
-            }
+            | Call { target: None, unwind: _, .. }
+            | InlineAsm { destination: None, unwind: _, .. } => None.into_iter().chain(&mut []),
             SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets),
             FalseEdge { ref mut real_target, ref mut imaginary_target } => {
                 Some(real_target).into_iter().chain(slice::from_mut(imaginary_target))
@@ -208,7 +210,7 @@ impl<'tcx> TerminatorKind<'tcx> {
         }
     }
 
-    pub fn unwind(&self) -> Option<&Option> {
+    pub fn unwind(&self) -> Option<&UnwindAction> {
         match *self {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
@@ -219,15 +221,15 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdge { .. } => None,
-            TerminatorKind::Call { cleanup: ref unwind, .. }
-            | TerminatorKind::Assert { cleanup: ref unwind, .. }
+            TerminatorKind::Call { ref unwind, .. }
+            | TerminatorKind::Assert { ref unwind, .. }
             | TerminatorKind::Drop { ref unwind, .. }
             | TerminatorKind::FalseUnwind { ref unwind, .. }
-            | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind),
+            | TerminatorKind::InlineAsm { ref unwind, .. } => Some(unwind),
         }
     }
 
-    pub fn unwind_mut(&mut self) -> Option<&mut Option> {
+    pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> {
         match *self {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
@@ -238,11 +240,11 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdge { .. } => None,
-            TerminatorKind::Call { cleanup: ref mut unwind, .. }
-            | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
+            TerminatorKind::Call { ref mut unwind, .. }
+            | TerminatorKind::Assert { ref mut unwind, .. }
             | TerminatorKind::Drop { ref mut unwind, .. }
             | TerminatorKind::FalseUnwind { ref mut unwind, .. }
-            | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind),
+            | TerminatorKind::InlineAsm { ref mut unwind, .. } => Some(unwind),
         }
     }
 
@@ -386,31 +388,33 @@ impl<'tcx> TerminatorKind<'tcx> {
                 .map(|&u| Cow::Owned(u.to_string()))
                 .chain(iter::once("otherwise".into()))
                 .collect(),
-            Call { target: Some(_), cleanup: Some(_), .. } => {
+            Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
                 vec!["return".into(), "unwind".into()]
             }
-            Call { target: Some(_), cleanup: None, .. } => vec!["return".into()],
-            Call { target: None, cleanup: Some(_), .. } => vec!["unwind".into()],
-            Call { target: None, cleanup: None, .. } => vec![],
+            Call { target: Some(_), unwind: UnwindAction::Continue, .. } => vec!["return".into()],
+            Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()],
+            Call { target: None, unwind: UnwindAction::Continue, .. } => vec![],
             Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
             Yield { drop: None, .. } => vec!["resume".into()],
-            Drop { unwind: None, .. } => {
-                vec!["return".into()]
-            }
-            Drop { unwind: Some(_), .. } => {
-                vec!["return".into(), "unwind".into()]
-            }
-            Assert { cleanup: None, .. } => vec!["".into()],
+            Drop { unwind: UnwindAction::Continue, .. } => vec!["return".into()],
+            Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
+            Assert { unwind: UnwindAction::Continue, .. } => vec!["".into()],
             Assert { .. } => vec!["success".into(), "unwind".into()],
             FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
-            FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
-            FalseUnwind { unwind: None, .. } => vec!["real".into()],
-            InlineAsm { destination: Some(_), cleanup: Some(_), .. } => {
+            FalseUnwind { unwind: UnwindAction::Cleanup(_), .. } => {
+                vec!["real".into(), "cleanup".into()]
+            }
+            FalseUnwind { unwind: UnwindAction::Continue, .. } => vec!["real".into()],
+            InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
                 vec!["return".into(), "unwind".into()]
             }
-            InlineAsm { destination: Some(_), cleanup: None, .. } => vec!["return".into()],
-            InlineAsm { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()],
-            InlineAsm { destination: None, cleanup: None, .. } => vec![],
+            InlineAsm { destination: Some(_), unwind: UnwindAction::Continue, .. } => {
+                vec!["return".into()]
+            }
+            InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
+                vec!["unwind".into()]
+            }
+            InlineAsm { destination: None, unwind: UnwindAction::Continue, .. } => vec![],
         }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 7aa446ae966c..243c62f4a9c2 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -509,7 +509,7 @@ macro_rules! make_mir_visitor {
                         args,
                         destination,
                         target: _,
-                        cleanup: _,
+                        unwind: _,
                         from_hir_call: _,
                         fn_span: _
                     } => {
@@ -529,7 +529,7 @@ macro_rules! make_mir_visitor {
                         expected: _,
                         msg,
                         target: _,
-                        cleanup: _,
+                        unwind: _,
                     } => {
                         self.visit_operand(cond, location);
                         self.visit_assert_message(msg, location);
@@ -555,7 +555,7 @@ macro_rules! make_mir_visitor {
                         options: _,
                         line_spans: _,
                         destination: _,
-                        cleanup: _,
+                        unwind: _,
                     } => {
                         for op in operands {
                             match op {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index baa12ec11c32..8631749a524b 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -171,7 +171,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         args: vec![Operand::Move(size), Operand::Move(align)],
                         destination: storage,
                         target: Some(success),
-                        cleanup: None,
+                        unwind: UnwindAction::Continue,
                         from_hir_call: false,
                         fn_span: expr_span,
                     },
@@ -702,7 +702,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.cfg.terminate(
                     block,
                     outer_source_info,
-                    TerminatorKind::Drop { place: to_drop, target: success, unwind: None },
+                    TerminatorKind::Drop {
+                        place: to_drop,
+                        target: success,
+                        unwind: UnwindAction::Continue,
+                    },
                 );
                 this.diverge_from(block);
                 block = success;
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 8efaba1f602e..bafe7ede3d90 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -228,7 +228,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     this.cfg.terminate(
                         loop_block,
                         source_info,
-                        TerminatorKind::FalseUnwind { real_target: body_block, unwind: None },
+                        TerminatorKind::FalseUnwind {
+                            real_target: body_block,
+                            unwind: UnwindAction::Continue,
+                        },
                     );
                     this.diverge_from(loop_block);
 
@@ -264,7 +267,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     TerminatorKind::Call {
                         func: fun,
                         args,
-                        cleanup: None,
+                        unwind: UnwindAction::Continue,
                         destination,
                         // The presence or absence of a return edge affects control-flow sensitive
                         // MIR checks and ultimately whether code is accepted or not. We can only
@@ -466,7 +469,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         } else {
                             Some(destination_block)
                         },
-                        cleanup: None,
+                        unwind: UnwindAction::Continue,
                     },
                 );
                 if options.contains(InlineAsmOptions::MAY_UNWIND) {
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 2de89f67dfdc..8a03ea7e2cc7 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -263,7 +263,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             args: vec![Operand::Move(ref_string)],
                             destination: ref_str,
                             target: Some(eq_block),
-                            cleanup: None,
+                            unwind: UnwindAction::Continue,
                             from_hir_call: false,
                             fn_span: source_info.span
                         }
@@ -466,7 +466,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 args: vec![val, expect],
                 destination: eq_result,
                 target: Some(eq_block),
-                cleanup: None,
+                unwind: UnwindAction::Continue,
                 from_hir_call: false,
                 fn_span: source_info.span,
             },
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 25af221bf369..f67659ac6bf0 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -369,7 +369,7 @@ impl DropTree {
                     let terminator = TerminatorKind::Drop {
                         target: blocks[drop_data.1].unwrap(),
                         // The caller will handle this if needed.
-                        unwind: None,
+                        unwind: UnwindAction::Continue,
                         place: drop_data.0.local.into(),
                     };
                     cfg.terminate(block, drop_data.0.source_info, terminator);
@@ -1141,7 +1141,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.terminate(
             block,
             source_info,
-            TerminatorKind::Drop { place, target: assign, unwind: Some(assign_unwind) },
+            TerminatorKind::Drop {
+                place,
+                target: assign,
+                unwind: UnwindAction::Cleanup(assign_unwind),
+            },
         );
         self.diverge_from(block);
 
@@ -1165,7 +1169,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.terminate(
             block,
             source_info,
-            TerminatorKind::Assert { cond, expected, msg, target: success_block, cleanup: None },
+            TerminatorKind::Assert {
+                cond,
+                expected,
+                msg,
+                target: success_block,
+                unwind: UnwindAction::Continue,
+            },
         );
         self.diverge_from(block);
 
@@ -1244,7 +1254,11 @@ fn build_scope_drops<'tcx>(
                 cfg.terminate(
                     block,
                     source_info,
-                    TerminatorKind::Drop { place: local.into(), target: next, unwind: None },
+                    TerminatorKind::Drop {
+                        place: local.into(),
+                        target: next,
+                        unwind: UnwindAction::Continue,
+                    },
                 );
                 block = next;
             }
@@ -1432,10 +1446,10 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
                 }
             }
             TerminatorKind::FalseUnwind { unwind, .. }
-            | TerminatorKind::Call { cleanup: unwind, .. }
-            | TerminatorKind::Assert { cleanup: unwind, .. }
-            | TerminatorKind::InlineAsm { cleanup: unwind, .. } => {
-                *unwind = Some(to);
+            | TerminatorKind::Call { unwind, .. }
+            | TerminatorKind::Assert { unwind, .. }
+            | TerminatorKind::InlineAsm { unwind, .. } => {
+                *unwind = UnwindAction::Cleanup(to);
             }
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 8937b78fe34e..910db7f676d7 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::graph::iterate::{
     NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
 };
 use rustc_hir::def::DefKind;
-use rustc_middle::mir::{BasicBlock, BasicBlocks, Body, Operand, TerminatorKind};
+use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Operand, TerminatorKind};
 use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
@@ -149,7 +149,9 @@ impl<'mir, 'tcx> TriColorVisitor> for Search<'mir, 'tcx> {
 
     fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock) -> bool {
         let terminator = self.body[bb].terminator();
-        if terminator.unwind() == Some(&Some(target)) && terminator.successors().count() > 1 {
+        if terminator.unwind() == Some(&mir::UnwindAction::Cleanup(target))
+            && terminator.successors().count() > 1
+        {
             return true;
         }
         // Don't traverse successors of recursive calls or false CFG edges.
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 7ef3d41ac48c..70ed0c226404 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -77,10 +77,10 @@ impl Unwind {
         }
     }
 
-    fn into_option(self) -> Option {
+    fn into_action(self) -> UnwindAction {
         match self {
-            Unwind::To(bb) => Some(bb),
-            Unwind::InCleanup => None,
+            Unwind::To(bb) => UnwindAction::Cleanup(bb),
+            Unwind::InCleanup => UnwindAction::Continue,
         }
     }
 
@@ -236,7 +236,7 @@ where
                     TerminatorKind::Drop {
                         place: self.place,
                         target: self.succ,
-                        unwind: self.unwind.into_option(),
+                        unwind: self.unwind.into_action(),
                     },
                 );
             }
@@ -640,7 +640,7 @@ where
                     args: vec![Operand::Move(Place::from(ref_place))],
                     destination: unit_temp,
                     target: Some(succ),
-                    cleanup: unwind.into_option(),
+                    unwind: unwind.into_action(),
                     from_hir_call: true,
                     fn_span: self.source_info.span,
                 },
@@ -717,7 +717,7 @@ where
             TerminatorKind::Drop {
                 place: tcx.mk_place_deref(ptr),
                 target: loop_block,
-                unwind: unwind.into_option(),
+                unwind: unwind.into_action(),
             },
         );
 
@@ -946,7 +946,7 @@ where
             args,
             destination: unit_temp,
             target: Some(target),
-            cleanup: None,
+            unwind: UnwindAction::Continue,
             from_hir_call: false,
             fn_span: self.source_info.span,
         }; // FIXME(#43234)
@@ -959,7 +959,7 @@ where
 
     fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
         let block =
-            TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_option() };
+            TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_action() };
         self.new_block(unwind, block)
     }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index a40c38aa4c33..a078c6b550e1 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -1,4 +1,4 @@
-use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets};
+use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets, UnwindAction};
 use rustc_middle::ty::TyCtxt;
 use std::ops::RangeInclusive;
 
@@ -478,10 +478,10 @@ impl Direction for Forward {
 
             Goto { target } => propagate(target, exit_state),
 
-            Assert { target, cleanup: unwind, expected: _, msg: _, cond: _ }
+            Assert { target, unwind, expected: _, msg: _, cond: _ }
             | Drop { target, unwind, place: _ }
             | FalseUnwind { real_target: target, unwind } => {
-                if let Some(unwind) = unwind {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     propagate(unwind, exit_state);
                 }
 
@@ -503,7 +503,7 @@ impl Direction for Forward {
             }
 
             Call {
-                cleanup,
+                unwind,
                 destination,
                 target,
                 func: _,
@@ -511,7 +511,7 @@ impl Direction for Forward {
                 from_hir_call: _,
                 fn_span: _,
             } => {
-                if let Some(unwind) = cleanup {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     propagate(unwind, exit_state);
                 }
 
@@ -533,9 +533,9 @@ impl Direction for Forward {
                 options: _,
                 line_spans: _,
                 destination,
-                cleanup,
+                unwind,
             } => {
-                if let Some(unwind) = cleanup {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     propagate(unwind, exit_state);
                 }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs
index 17102454a88d..60679b17d6c4 100644
--- a/compiler/rustc_mir_dataflow/src/framework/tests.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs
@@ -39,7 +39,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
             args: vec![],
             destination: dummy_place.clone(),
             target: Some(mir::START_BLOCK),
-            cleanup: None,
+            unwind: mir::UnwindAction::Continue,
             from_hir_call: false,
             fn_span: DUMMY_SP,
         },
@@ -53,7 +53,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
             args: vec![],
             destination: dummy_place.clone(),
             target: Some(mir::START_BLOCK),
-            cleanup: None,
+            unwind: mir::UnwindAction::Continue,
             from_hir_call: false,
             fn_span: DUMMY_SP,
         },
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index d9ceac1154f4..9f9a5c94b560 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -398,7 +398,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                 ref args,
                 destination,
                 target,
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -417,7 +417,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                 options: _,
                 line_spans: _,
                 destination: _,
-                cleanup: _,
+                unwind: _,
             } => {
                 for op in operands {
                     match *op {
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index 893018e0d8e7..8fddbe4ad9f4 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -125,13 +125,13 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
 
             for bb in calls_to_terminate {
                 let cleanup = body.basic_blocks_mut()[bb].terminator_mut().unwind_mut().unwrap();
-                *cleanup = Some(abort_bb);
+                *cleanup = UnwindAction::Cleanup(abort_bb);
             }
         }
 
         for id in cleanups_to_remove {
             let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
-            *cleanup = None;
+            *cleanup = UnwindAction::Continue;
         }
 
         // We may have invalidated some `cleanup` blocks so clean those up now.
diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index 30966d22e2f6..ea7ccb512e09 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -50,10 +50,10 @@ impl AddCallGuards {
         for block in body.basic_blocks_mut() {
             match block.terminator {
                 Some(Terminator {
-                    kind: TerminatorKind::Call { target: Some(ref mut destination), cleanup, .. },
+                    kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. },
                     source_info,
                 }) if pred_count[*destination] > 1
-                    && (cleanup.is_some() || self == &AllCallEdges) =>
+                    && (matches!(unwind, UnwindAction::Cleanup(_)) || self == &AllCallEdges) =>
                 {
                     // It's a critical edge, break it
                     let call_guard = BasicBlockData {
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index ac55948e61b5..b9af74a2061d 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -228,7 +228,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
     fn assert_panic(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _msg: &rustc_middle::mir::AssertMessage<'tcx>,
-        _unwind: Option,
+        _unwind: rustc_middle::mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         bug!("panics terminators are not evaluated in ConstProp")
     }
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 59b506e73455..0f6c06e370ba 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -140,7 +140,7 @@ impl<'tcx> MockBlocks<'tcx> {
                 args: vec![],
                 destination: self.dummy_place.clone(),
                 target: Some(TEMP_BLOCK),
-                cleanup: None,
+                unwind: UnwindAction::Continue,
                 from_hir_call: false,
                 fn_span: DUMMY_SP,
             },
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index a028d6356d50..9217c2dc81cc 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -120,7 +120,7 @@ fn remove_dead_unwinds<'tcx>(
         .into_results_cursor(body);
     for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
         let place = match bb_data.terminator().kind {
-            TerminatorKind::Drop { ref place, unwind: Some(_), .. } => {
+            TerminatorKind::Drop { ref place, unwind: UnwindAction::Cleanup(_), .. } => {
                 und.derefer(place.as_ref(), body).unwrap_or(*place)
             }
             _ => continue,
@@ -417,7 +417,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                             if data.is_cleanup {
                                 Unwind::InCleanup
                             } else {
-                                Unwind::To(Option::unwrap_or(unwind, resume_block))
+                                match unwind {
+                                    UnwindAction::Cleanup(cleanup) => Unwind::To(cleanup),
+                                    UnwindAction::Continue => Unwind::To(resume_block),
+                                }
                             },
                             bb,
                         ),
@@ -474,7 +477,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                 continue;
             }
             if let TerminatorKind::Call {
-                destination, target: Some(tgt), cleanup: Some(_), ..
+                destination,
+                target: Some(tgt),
+                unwind: UnwindAction::Cleanup(_),
+                ..
             } = data.terminator().kind
             {
                 assert!(!self.patch.is_patched(bb));
@@ -543,8 +549,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             // There may be a critical edge after this call,
             // so mark the return as initialized *before* the
             // call.
-            if let TerminatorKind::Call { destination, target: Some(_), cleanup: None, .. } =
-                data.terminator().kind
+            if let TerminatorKind::Call {
+                destination,
+                target: Some(_),
+                unwind: UnwindAction::Continue,
+                ..
+            } = data.terminator().kind
             {
                 assert!(!self.patch.is_patched(bb));
 
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 66d32b954e47..8601c1b2d71a 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -34,7 +34,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
             args,
             destination: _,
             target: _,
-            cleanup: _,
+            unwind: _,
             from_hir_call: _,
             fn_span: _,
         } = &terminator.kind
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index af6422c72464..a83e6a5b6807 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1060,7 +1060,10 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let unwind = if block_data.is_cleanup {
             Unwind::InCleanup
         } else {
-            Unwind::To(unwind.unwrap_or_else(|| elaborator.patch.resume_block()))
+            Unwind::To(match *unwind {
+                UnwindAction::Cleanup(tgt) => tgt,
+                UnwindAction::Continue => elaborator.patch.resume_block(),
+            })
         };
         elaborate_drop(
             &mut elaborator,
@@ -1147,7 +1150,7 @@ fn insert_panic_block<'tcx>(
         expected: true,
         msg: message,
         target: assert_block,
-        cleanup: None,
+        unwind: UnwindAction::Continue,
     };
 
     let source_info = SourceInfo::outermost(body.span);
@@ -1248,8 +1251,8 @@ fn create_generator_resume_function<'tcx>(
             } else if !block.is_cleanup {
                 // Any terminators that *can* unwind but don't have an unwind target set are also
                 // pointed at our poisoning block (unless they're part of the cleanup path).
-                if let Some(unwind @ None) = block.terminator_mut().unwind_mut() {
-                    *unwind = Some(poison_block);
+                if let Some(unwind @ UnwindAction::Continue) = block.terminator_mut().unwind_mut() {
+                    *unwind = UnwindAction::Cleanup(poison_block);
                 }
             }
         }
@@ -1294,8 +1297,11 @@ fn create_generator_resume_function<'tcx>(
 fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
     let return_block = insert_term_block(body, TerminatorKind::Return);
 
-    let term =
-        TerminatorKind::Drop { place: Place::from(SELF_ARG), target: return_block, unwind: None };
+    let term = TerminatorKind::Drop {
+        place: Place::from(SELF_ARG),
+        target: return_block,
+        unwind: UnwindAction::Continue,
+    };
     let source_info = SourceInfo::outermost(body.span);
 
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
@@ -1670,7 +1676,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
                 args,
                 destination,
                 target: Some(_),
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
                 fn_span: _,
             } => {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 15b31d383944..c46cb5e98df6 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -453,7 +453,7 @@ impl<'tcx> Inliner<'tcx> {
 
                 // If the place doesn't actually need dropping, treat it like a regular goto.
                 let ty = callsite.callee.subst_mir(self.tcx, &place.ty(callee_body, tcx).ty);
-                if ty.needs_drop(tcx, self.param_env) && let Some(unwind) = unwind {
+                if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind {
                         work_list.push(unwind);
                     }
             } else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
@@ -500,7 +500,7 @@ impl<'tcx> Inliner<'tcx> {
     ) {
         let terminator = caller_body[callsite.block].terminator.take().unwrap();
         match terminator.kind {
-            TerminatorKind::Call { args, destination, cleanup, .. } => {
+            TerminatorKind::Call { args, destination, unwind, .. } => {
                 // If the call is something like `a[*i] = f(i)`, where
                 // `i : &mut usize`, then just duplicating the `a[*i]`
                 // Place could result in two different locations if `f`
@@ -571,7 +571,7 @@ impl<'tcx> Inliner<'tcx> {
                     destination: destination_local,
                     callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
                     callsite,
-                    cleanup_block: cleanup,
+                    cleanup_block: unwind,
                     in_cleanup_block: false,
                     tcx: self.tcx,
                     expn_data,
@@ -813,14 +813,14 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                 let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty);
                 if ty.needs_drop(tcx, self.param_env) {
                     self.cost += CALL_PENALTY;
-                    if unwind.is_some() {
+                    if let UnwindAction::Cleanup(_) = unwind {
                         self.cost += LANDINGPAD_PENALTY;
                     }
                 } else {
                     self.cost += INSTR_COST;
                 }
             }
-            TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => {
+            TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => {
                 let fn_ty = self.instance.subst_mir(tcx, &f.literal.ty());
                 self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) {
                     // Don't give intrinsics the extra penalty for calls
@@ -828,20 +828,20 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                 } else {
                     CALL_PENALTY
                 };
-                if cleanup.is_some() {
+                if let UnwindAction::Cleanup(_) = unwind {
                     self.cost += LANDINGPAD_PENALTY;
                 }
             }
-            TerminatorKind::Assert { cleanup, .. } => {
+            TerminatorKind::Assert { unwind, .. } => {
                 self.cost += CALL_PENALTY;
-                if cleanup.is_some() {
+                if let UnwindAction::Cleanup(_) = unwind {
                     self.cost += LANDINGPAD_PENALTY;
                 }
             }
             TerminatorKind::Resume => self.cost += RESUME_PENALTY,
-            TerminatorKind::InlineAsm { cleanup, .. } => {
+            TerminatorKind::InlineAsm { unwind, .. } => {
                 self.cost += INSTR_COST;
-                if cleanup.is_some() {
+                if let UnwindAction::Cleanup(_) = unwind {
                     self.cost += LANDINGPAD_PENALTY;
                 }
             }
@@ -979,7 +979,7 @@ struct Integrator<'a, 'tcx> {
     destination: Local,
     callsite_scope: SourceScopeData<'tcx>,
     callsite: &'a CallSite<'tcx>,
-    cleanup_block: Option,
+    cleanup_block: UnwindAction,
     in_cleanup_block: bool,
     tcx: TyCtxt<'tcx>,
     expn_data: LocalExpnId,
@@ -1014,18 +1014,20 @@ impl Integrator<'_, '_> {
         new
     }
 
-    fn map_unwind(&self, unwind: Option) -> Option {
+    fn map_unwind(&self, unwind: UnwindAction) -> UnwindAction {
         if self.in_cleanup_block {
-            if unwind.is_some() {
-                bug!("cleanup on cleanup block");
+            match unwind {
+                UnwindAction::Cleanup(_) => {
+                    bug!("cleanup on cleanup block");
+                }
+                UnwindAction::Continue => return unwind,
             }
-            return unwind;
         }
 
         match unwind {
-            Some(target) => Some(self.map_block(target)),
+            UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
             // Add an unwind edge to the original call's cleanup block
-            None => self.cleanup_block,
+            UnwindAction::Continue => self.cleanup_block,
         }
     }
 }
@@ -1116,15 +1118,15 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
                 *target = self.map_block(*target);
                 *unwind = self.map_unwind(*unwind);
             }
-            TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
+            TerminatorKind::Call { ref mut target, ref mut unwind, .. } => {
                 if let Some(ref mut tgt) = *target {
                     *tgt = self.map_block(*tgt);
                 }
-                *cleanup = self.map_unwind(*cleanup);
+                *unwind = self.map_unwind(*unwind);
             }
-            TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
+            TerminatorKind::Assert { ref mut target, ref mut unwind, .. } => {
                 *target = self.map_block(*target);
-                *cleanup = self.map_unwind(*cleanup);
+                *unwind = self.map_unwind(*unwind);
             }
             TerminatorKind::Return => {
                 terminator.kind = if let Some(tgt) = self.callsite.target {
@@ -1133,11 +1135,12 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
                     TerminatorKind::Unreachable
                 }
             }
-            TerminatorKind::Resume => {
-                if let Some(tgt) = self.cleanup_block {
-                    terminator.kind = TerminatorKind::Goto { target: tgt }
+            TerminatorKind::Resume => match self.cleanup_block {
+                UnwindAction::Cleanup(tgt) => {
+                    terminator.kind = TerminatorKind::Goto { target: tgt };
                 }
-            }
+                UnwindAction::Continue => (),
+            },
             TerminatorKind::Abort => {}
             TerminatorKind::Unreachable => {}
             TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
@@ -1149,11 +1152,11 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
             {
                 bug!("False unwinds should have been removed before inlining")
             }
-            TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => {
+            TerminatorKind::InlineAsm { ref mut destination, ref mut unwind, .. } => {
                 if let Some(ref mut tgt) = *destination {
                     *tgt = self.map_block(*tgt);
                 }
-                *cleanup = self.map_unwind(*cleanup);
+                *unwind = self.map_unwind(*unwind);
             }
         }
     }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index b52de4b72c9e..2e418c1dafc4 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -159,7 +159,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
                 ref mut args,
                 destination,
                 target,
-                cleanup,
+                unwind,
                 fn_span,
                 ..
             } if let ty::FnDef(def_id, _) = *literal.ty().kind()
@@ -196,7 +196,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
                     };
                     method(place)
                 }).collect();
-                terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, cleanup, from_hir_call: false, fn_span };
+                terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, unwind, from_hir_call: false, fn_span };
             }
             _ => {}
         }
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 101fae2f08c5..75a415d88eef 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -54,7 +54,7 @@ fn lower_slice_len_call<'tcx>(
             args,
             destination,
             target: Some(bb),
-            cleanup: None,
+            unwind: UnwindAction::Continue,
             from_hir_call: true,
             ..
         } => {
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index e962819b6917..b4d68f4a322e 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -103,11 +103,11 @@ impl RemoveNoopLandingPads {
         for bb in postorder {
             debug!("  processing {:?}", bb);
             if let Some(unwind) = body[bb].terminator_mut().unwind_mut() {
-                if let Some(unwind_bb) = *unwind {
+                if let UnwindAction::Cleanup(unwind_bb) = *unwind {
                     if nop_landing_pads.contains(unwind_bb) {
                         debug!("    removing noop landing pad");
                         landing_pads_removed += 1;
-                        *unwind = None;
+                        *unwind = UnwindAction::Continue;
                     }
                 }
             }
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 9e406eba0fca..f5a65e127054 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -499,7 +499,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
                 args: vec![Operand::Move(ref_loc)],
                 destination: dest,
                 target: Some(next),
-                cleanup: Some(cleanup),
+                unwind: UnwindAction::Cleanup(cleanup),
                 from_hir_call: true,
                 fn_span: self.span,
             },
@@ -540,7 +540,11 @@ impl<'tcx> CloneShimBuilder<'tcx> {
             self.make_clone_call(dest_field, src_field, ity, next_block, unwind);
             self.block(
                 vec![],
-                TerminatorKind::Drop { place: dest_field, target: unwind, unwind: None },
+                TerminatorKind::Drop {
+                    place: dest_field,
+                    target: unwind,
+                    unwind: UnwindAction::Continue,
+                },
                 true,
             );
             unwind = next_unwind;
@@ -776,10 +780,10 @@ fn build_call_shim<'tcx>(
             args,
             destination: Place::return_place(),
             target: Some(BasicBlock::new(1)),
-            cleanup: if let Some(Adjustment::RefMut) = rcvr_adjustment {
-                Some(BasicBlock::new(3))
+            unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
+                UnwindAction::Cleanup(BasicBlock::new(3))
             } else {
-                None
+                UnwindAction::Continue
             },
             from_hir_call: true,
             fn_span: span,
@@ -792,7 +796,11 @@ fn build_call_shim<'tcx>(
         block(
             &mut blocks,
             vec![],
-            TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(2), unwind: None },
+            TerminatorKind::Drop {
+                place: rcvr_place(),
+                target: BasicBlock::new(2),
+                unwind: UnwindAction::Continue,
+            },
             false,
         );
     }
@@ -803,7 +811,11 @@ fn build_call_shim<'tcx>(
         block(
             &mut blocks,
             vec![],
-            TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(4), unwind: None },
+            TerminatorKind::Drop {
+                place: rcvr_place(),
+                target: BasicBlock::new(4),
+                unwind: UnwindAction::Continue,
+            },
             true,
         );
 
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index d66640ba0b7a..ff195cd72880 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -318,7 +318,7 @@ fn check_terminator<'tcx>(
             from_hir_call: _,
             destination: _,
             target: _,
-            cleanup: _,
+            unwind: _,
             fn_span: _,
         } => {
             let fn_ty = func.ty(body, tcx);
@@ -361,7 +361,7 @@ fn check_terminator<'tcx>(
             expected: _,
             msg: _,
             target: _,
-            cleanup: _,
+            unwind: _,
         } => check_operand(tcx, cond, span, body),
 
         TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index cc1964de332c..621b90f0e572 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -868,7 +868,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     fn assert_panic(
         ecx: &mut MiriInterpCx<'mir, 'tcx>,
         msg: &mir::AssertMessage<'tcx>,
-        unwind: Option,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         ecx.assert_panic(msg, unwind)
     }
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index acc97c4b8a0a..c31194b4b935 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -189,7 +189,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn assert_panic(
         &mut self,
         msg: &mir::AssertMessage<'tcx>,
-        unwind: Option,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         use rustc_middle::mir::AssertKind::*;
         let this = self.eval_context_mut();

From 5e6ed132fa8a1bd1ec6b365e61e9e290528c90f5 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Mon, 10 Oct 2022 19:50:49 +0100
Subject: [PATCH 165/267] Add `UnwindAction::Unreachable`

This also makes eval machine's `StackPopUnwind`
redundant so that is replaced.
---
 compiler/rustc_borrowck/src/type_check/mod.rs | 47 ++++++++--------
 compiler/rustc_codegen_ssa/src/mir/block.rs   | 55 +++++++++++--------
 .../src/const_eval/machine.rs                 |  8 +--
 .../src/interpret/eval_context.rs             | 25 +++------
 .../rustc_const_eval/src/interpret/machine.rs | 10 ++--
 .../rustc_const_eval/src/interpret/mod.rs     |  4 +-
 .../src/interpret/terminator.rs               | 25 +++------
 compiler/rustc_middle/src/mir/patch.rs        |  5 +-
 compiler/rustc_middle/src/mir/syntax.rs       | 11 +++-
 compiler/rustc_middle/src/mir/terminator.rs   | 36 +++++++-----
 .../rustc_mir_dataflow/src/elaborate_drops.rs |  2 +-
 .../src/abort_unwinding_calls.rs              |  2 +-
 .../rustc_mir_transform/src/const_prop.rs     |  6 +-
 .../src/elaborate_drops.rs                    | 30 ++++++----
 compiler/rustc_mir_transform/src/generator.rs |  1 +
 compiler/rustc_mir_transform/src/inline.rs    |  6 +-
 .../src/lower_slice_len.rs                    |  2 +-
 src/tools/miri/src/helpers.rs                 |  2 +-
 src/tools/miri/src/machine.rs                 |  6 +-
 src/tools/miri/src/shims/foreign_items.rs     |  2 +-
 src/tools/miri/src/shims/intrinsics/mod.rs    |  2 +-
 src/tools/miri/src/shims/mod.rs               |  4 +-
 src/tools/miri/src/shims/panic.rs             | 18 ++----
 23 files changed, 160 insertions(+), 149 deletions(-)

diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 10332c6d9b5f..15d748a9e753 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1612,23 +1612,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             TerminatorKind::Drop { target, unwind, .. }
             | TerminatorKind::Assert { target, unwind, .. } => {
                 self.assert_iscleanup(body, block_data, target, is_cleanup);
-                if let UnwindAction::Cleanup(unwind) = unwind {
-                    if is_cleanup {
-                        span_mirbug!(self, block_data, "unwind on cleanup block")
-                    }
-                    self.assert_iscleanup(body, block_data, unwind, true);
-                }
+                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
             }
             TerminatorKind::Call { ref target, unwind, .. } => {
                 if let &Some(target) = target {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
-                if let UnwindAction::Cleanup(cleanup) = unwind {
-                    if is_cleanup {
-                        span_mirbug!(self, block_data, "cleanup on cleanup block")
-                    }
-                    self.assert_iscleanup(body, block_data, cleanup, true);
-                }
+                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
             }
             TerminatorKind::FalseEdge { real_target, imaginary_target } => {
                 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
@@ -1636,23 +1626,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::FalseUnwind { real_target, unwind } => {
                 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
-                if let UnwindAction::Cleanup(unwind) = unwind {
-                    if is_cleanup {
-                        span_mirbug!(self, block_data, "cleanup in cleanup block via false unwind");
-                    }
-                    self.assert_iscleanup(body, block_data, unwind, true);
-                }
+                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
             }
             TerminatorKind::InlineAsm { destination, unwind, .. } => {
                 if let Some(target) = destination {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
-                if let UnwindAction::Cleanup(cleanup) = unwind {
-                    if is_cleanup {
-                        span_mirbug!(self, block_data, "cleanup on cleanup block")
-                    }
-                    self.assert_iscleanup(body, block_data, cleanup, true);
-                }
+                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
             }
         }
     }
@@ -1669,6 +1649,25 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
+    fn assert_iscleanup_unwind(
+        &mut self,
+        body: &Body<'tcx>,
+        ctxt: &dyn fmt::Debug,
+        unwind: UnwindAction,
+        is_cleanup: bool,
+    ) {
+        match unwind {
+            UnwindAction::Cleanup(unwind) => {
+                if is_cleanup {
+                    span_mirbug!(self, ctxt, "unwind on cleanup block")
+                }
+                self.assert_iscleanup(body, ctxt, unwind, true);
+            }
+            UnwindAction::Continue => (),
+            UnwindAction::Unreachable => (),
+        }
+    }
+
     fn check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
         match body.local_kind(local) {
             LocalKind::ReturnPointer | LocalKind::Arg => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index a6891a8ff2f9..66bec6f30dea 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -156,7 +156,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         fn_ptr: Bx::Value,
         llargs: &[Bx::Value],
         destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
-        unwind: mir::UnwindAction,
+        mut unwind: mir::UnwindAction,
         copied_constant_arguments: &[PlaceRef<'tcx, ::Value>],
         mergeable_succ: bool,
     ) -> MergingSucc {
@@ -164,27 +164,28 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         // do an invoke, otherwise do a call.
         let fn_ty = bx.fn_decl_backend_type(&fn_abi);
 
-        let cleanup = match unwind {
-            mir::UnwindAction::Cleanup(cleanup) => Some(cleanup),
+        if !fn_abi.can_unwind {
+            unwind = mir::UnwindAction::Unreachable;
+        }
+
+        let unwind_block = match unwind {
+            mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
+            _ if fx.mir[self.bb].is_cleanup
+                && fn_abi.can_unwind
+                && !base::wants_msvc_seh(fx.cx.tcx().sess) =>
+            {
+                // Exception must not propagate out of the execution of a cleanup (doing so
+                // can cause undefined behaviour). We insert a double unwind guard for
+                // functions that can potentially unwind to protect against this.
+                //
+                // This is not necessary for SEH which does not use successive unwinding
+                // like Itanium EH. EH frames in SEH are different from normal function
+                // frames and SEH will abort automatically if an exception tries to
+                // propagate out from cleanup.
+                Some(fx.double_unwind_guard())
+            }
             mir::UnwindAction::Continue => None,
-        };
-        let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
-            Some(self.llbb_with_cleanup(fx, cleanup))
-        } else if fx.mir[self.bb].is_cleanup
-            && fn_abi.can_unwind
-            && !base::wants_msvc_seh(fx.cx.tcx().sess)
-        {
-            // Exception must not propagate out of the execution of a cleanup (doing so
-            // can cause undefined behaviour). We insert a double unwind guard for
-            // functions that can potentially unwind to protect against this.
-            //
-            // This is not necessary for SEH which does not use successive unwinding
-            // like Itanium EH. EH frames in SEH are different from normal function
-            // frames and SEH will abort automatically if an exception tries to
-            // propagate out from cleanup.
-            Some(fx.double_unwind_guard())
-        } else {
-            None
+            mir::UnwindAction::Unreachable => None,
         };
 
         if let Some(unwind_block) = unwind_block {
@@ -640,7 +641,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind);
 
         // Codegen the actual panic invoke/call.
-        let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &[], None, mir::UnwindAction::Continue, &[], false);
+        let merging_succ = helper.do_call(
+            self,
+            bx,
+            fn_abi,
+            llfn,
+            &[],
+            None,
+            mir::UnwindAction::Unreachable,
+            &[],
+            false,
+        );
         assert_eq!(merging_succ, MergingSucc::False);
     }
 
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 5fd99a9a84ac..a5dfd1072f0a 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -23,7 +23,7 @@ use rustc_target::spec::abi::Abi as CallAbi;
 
 use crate::interpret::{
     self, compile_time_machine, AllocId, ConstAllocation, FnVal, Frame, ImmTy, InterpCx,
-    InterpResult, OpTy, PlaceTy, Pointer, Scalar, StackPopUnwind,
+    InterpResult, OpTy, PlaceTy, Pointer, Scalar,
 };
 
 use super::error::*;
@@ -271,7 +271,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
                         /* with_caller_location = */ false,
                         dest,
                         ret,
-                        StackPopUnwind::NotAllowed,
+                        mir::UnwindAction::Unreachable,
                     )?;
                     Ok(ControlFlow::Break(()))
                 } else {
@@ -401,7 +401,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         args: &[OpTy<'tcx>],
         dest: &PlaceTy<'tcx>,
         ret: Option,
-        _unwind: StackPopUnwind, // unwinding is not supported in consts
+        _unwind: mir::UnwindAction, // unwinding is not supported in consts
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         debug!("find_mir_or_eval_fn: {:?}", instance);
 
@@ -450,7 +450,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         args: &[OpTy<'tcx>],
         dest: &PlaceTy<'tcx, Self::Provenance>,
         target: Option,
-        _unwind: StackPopUnwind,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         // Shared intrinsics.
         if ecx.emulate_intrinsic(instance, args, dest, target)? {
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 0918ffcd9821..94f3563cf762 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -139,17 +139,6 @@ pub struct FrameInfo<'tcx> {
     pub lint_root: Option,
 }
 
-/// Unwind information.
-#[derive(Clone, Copy, Eq, PartialEq, Debug)]
-pub enum StackPopUnwind {
-    /// The cleanup block.
-    Cleanup(mir::BasicBlock),
-    /// No cleanup needs to be done.
-    Skip,
-    /// Unwinding is not allowed (UB).
-    NotAllowed,
-}
-
 #[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these
 pub enum StackPopCleanup {
     /// Jump to the next block in the caller, or cause UB if None (that's a function
@@ -157,7 +146,7 @@ pub enum StackPopCleanup {
     /// we can validate it at that layout.
     /// `ret` stores the block we jump to on a normal return, while `unwind`
     /// stores the block used for cleanup during unwinding.
-    Goto { ret: Option, unwind: StackPopUnwind },
+    Goto { ret: Option, unwind: mir::UnwindAction },
     /// The root frame of the stack: nowhere else to jump to.
     /// `cleanup` says whether locals are deallocated. Static computation
     /// wants them leaked to intern what they need (and just throw away
@@ -735,16 +724,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// *Unwind* to the given `target` basic block.
     /// Do *not* use for returning! Use `return_to_block` instead.
     ///
-    /// If `target` is `StackPopUnwind::Skip`, that indicates the function does not need cleanup
+    /// If `target` is `UnwindAction::Continue`, that indicates the function does not need cleanup
     /// during unwinding, and we will just keep propagating that upwards.
     ///
-    /// If `target` is `StackPopUnwind::NotAllowed`, that indicates the function does not allow
+    /// If `target` is `UnwindAction::Unreachable`, that indicates the function does not allow
     /// unwinding, and doing so is UB.
-    pub fn unwind_to_block(&mut self, target: StackPopUnwind) -> InterpResult<'tcx> {
+    pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tcx> {
         self.frame_mut().loc = match target {
-            StackPopUnwind::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
-            StackPopUnwind::Skip => Right(self.frame_mut().body.span),
-            StackPopUnwind::NotAllowed => {
+            mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
+            mir::UnwindAction::Continue => Right(self.frame_mut().body.span),
+            mir::UnwindAction::Unreachable => {
                 throw_ub_format!("unwinding past a stack frame that does not allow unwinding")
             }
         };
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index ca4da29ebbd3..dda4f6e00f38 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment;
 
 use super::{
     AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx,
-    InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
+    InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
 };
 
 /// Data returned by Machine::stack_pop,
@@ -185,7 +185,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
         args: &[OpTy<'tcx, Self::Provenance>],
         destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>;
 
     /// Execute `fn_val`. It is the hook's responsibility to advance the instruction
@@ -197,7 +197,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
         args: &[OpTy<'tcx, Self::Provenance>],
         destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
 
     /// Directly process an intrinsic without pushing a stack frame. It is the hook's
@@ -208,7 +208,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
         args: &[OpTy<'tcx, Self::Provenance>],
         destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
 
     /// Called to evaluate `Assert` MIR terminators that trigger a panic.
@@ -487,7 +487,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
         _args: &[OpTy<$tcx>],
         _destination: &PlaceTy<$tcx, Self::Provenance>,
         _target: Option,
-        _unwind: StackPopUnwind,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<$tcx> {
         match fn_val {}
     }
diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index 86de4e4e32c2..898d62361ab2 100644
--- a/compiler/rustc_const_eval/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
@@ -20,9 +20,7 @@ mod visitor;
 
 pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here
 
-pub use self::eval_context::{
-    Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup, StackPopUnwind,
-};
+pub use self::eval_context::{Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup};
 pub use self::intern::{intern_const_alloc_recursive, InternKind};
 pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
 pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 2546423d4cce..c8be2603ae9a 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -13,7 +13,7 @@ use rustc_target::spec::abi::Abi;
 
 use super::{
     FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, Operand,
-    PlaceTy, Scalar, StackPopCleanup, StackPopUnwind,
+    PlaceTy, Scalar, StackPopCleanup,
 };
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
@@ -60,7 +60,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 ref args,
                 destination,
                 target,
-                ref unwind,
+                unwind,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -106,13 +106,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     with_caller_location,
                     &destination,
                     target,
-                    match (unwind, fn_abi.can_unwind) {
-                        (mir::UnwindAction::Cleanup(cleanup), true) => {
-                            StackPopUnwind::Cleanup(*cleanup)
-                        }
-                        (mir::UnwindAction::Continue, true) => StackPopUnwind::Skip,
-                        (_, false) => StackPopUnwind::NotAllowed,
-                    },
+                    if fn_abi.can_unwind { unwind } else { mir::UnwindAction::Unreachable },
                 )?;
                 // Sanity-check that `eval_fn_call` either pushed a new frame or
                 // did a jump to another block.
@@ -353,7 +347,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         with_caller_location: bool,
         destination: &PlaceTy<'tcx, M::Provenance>,
         target: Option,
-        mut unwind: StackPopUnwind,
+        mut unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         trace!("eval_fn_call: {:#?}", fn_val);
 
@@ -412,9 +406,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     }
                 }
 
-                if !matches!(unwind, StackPopUnwind::NotAllowed) && !callee_fn_abi.can_unwind {
-                    // The callee cannot unwind.
-                    unwind = StackPopUnwind::NotAllowed;
+                if !callee_fn_abi.can_unwind {
+                    // The callee cannot unwind, so force the `Unreachable` unwind handling.
+                    unwind = mir::UnwindAction::Unreachable;
                 }
 
                 self.push_stack_frame(
@@ -719,10 +713,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             false,
             &ret.into(),
             Some(target),
-            match unwind {
-                mir::UnwindAction::Cleanup(cleanup) => StackPopUnwind::Cleanup(cleanup),
-                mir::UnwindAction::Continue => StackPopUnwind::Skip,
-            },
+            unwind,
         )
     }
 }
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index eb860c04de20..0f533dbb5946 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -12,6 +12,8 @@ pub struct MirPatch<'tcx> {
     new_statements: Vec<(Location, StatementKind<'tcx>)>,
     new_locals: Vec>,
     resume_block: Option,
+    // Only for unreachable in cleanup path.
+    unreachable_block: Option,
     body_span: Span,
     next_local: usize,
 }
@@ -25,11 +27,12 @@ impl<'tcx> MirPatch<'tcx> {
             new_locals: vec![],
             next_local: body.local_decls.len(),
             resume_block: None,
+            unreachable_block: None,
             body_span: body.span,
         };
 
-        // Check if we already have a resume block
         for (bb, block) in body.basic_blocks.iter_enumerated() {
+            // Check if we already have a resume block
             if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() {
                 result.resume_block = Some(bb);
                 break;
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index c2a12bb3b662..f7f2fc59ca52 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -753,12 +753,17 @@ pub enum TerminatorKind<'tcx> {
 }
 
 /// Action to be taken when a stack unwind happens.
-#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub enum UnwindAction {
-    // No action is to be taken. Continue unwinding.
+    /// No action is to be taken. Continue unwinding.
+    ///
+    /// This is similar to `Cleanup(bb)` where `bb` does nothing but `Resume`, but they are not
+    /// equivalent, as presence of `Cleanup(_)` will make a frame non-POF.
     Continue,
-    // Cleanups to be done.
+    /// Triggers undefined behavior if unwind happens.
+    Unreachable,
+    /// Cleanups to be done.
     Cleanup(BasicBlock),
 }
 
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 19aa01c12bd4..1ef2a197d86e 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -270,11 +270,16 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
         let labels = self.fmt_successor_labels();
         assert_eq!(successor_count, labels.len());
 
-        match successor_count {
-            0 => Ok(()),
-
-            1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
+        let unwind = match self.unwind() {
+            // Not needed or included in successors
+            None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None,
+            Some(UnwindAction::Unreachable) => Some("unwind unreachable"),
+        };
 
+        match (successor_count, unwind) {
+            (0, None) => Ok(()),
+            (0, Some(unwind)) => write!(fmt, " -> {}", unwind),
+            (1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
             _ => {
                 write!(fmt, " -> [")?;
                 for (i, target) in self.successors().enumerate() {
@@ -283,6 +288,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
                     }
                     write!(fmt, "{}: {:?}", labels[i], target)?;
                 }
+                if let Some(unwind) = unwind {
+                    write!(fmt, ", {unwind}")?;
+                }
                 write!(fmt, "]")
             }
         }
@@ -391,30 +399,32 @@ impl<'tcx> TerminatorKind<'tcx> {
             Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
                 vec!["return".into(), "unwind".into()]
             }
-            Call { target: Some(_), unwind: UnwindAction::Continue, .. } => vec!["return".into()],
+            Call { target: Some(_), unwind: _, .. } => vec!["return".into()],
             Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()],
-            Call { target: None, unwind: UnwindAction::Continue, .. } => vec![],
+            Call { target: None, unwind: _, .. } => vec![],
             Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
             Yield { drop: None, .. } => vec!["resume".into()],
-            Drop { unwind: UnwindAction::Continue, .. } => vec!["return".into()],
             Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
-            Assert { unwind: UnwindAction::Continue, .. } => vec!["".into()],
-            Assert { .. } => vec!["success".into(), "unwind".into()],
+            Drop { unwind: _, .. } => vec!["return".into()],
+            Assert { unwind: UnwindAction::Cleanup(_), .. } => {
+                vec!["success".into(), "unwind".into()]
+            }
+            Assert { unwind: _, .. } => vec!["success".into()],
             FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
             FalseUnwind { unwind: UnwindAction::Cleanup(_), .. } => {
-                vec!["real".into(), "cleanup".into()]
+                vec!["real".into(), "unwind".into()]
             }
-            FalseUnwind { unwind: UnwindAction::Continue, .. } => vec!["real".into()],
+            FalseUnwind { unwind: _, .. } => vec!["real".into()],
             InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
                 vec!["return".into(), "unwind".into()]
             }
-            InlineAsm { destination: Some(_), unwind: UnwindAction::Continue, .. } => {
+            InlineAsm { destination: Some(_), unwind: _, .. } => {
                 vec!["return".into()]
             }
             InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
                 vec!["unwind".into()]
             }
-            InlineAsm { destination: None, unwind: UnwindAction::Continue, .. } => vec![],
+            InlineAsm { destination: None, unwind: _, .. } => vec![],
         }
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 70ed0c226404..f48016450604 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -946,7 +946,7 @@ where
             args,
             destination: unit_temp,
             target: Some(target),
-            unwind: UnwindAction::Continue,
+            unwind: UnwindAction::Unreachable,
             from_hir_call: false,
             fn_span: self.source_info.span,
         }; // FIXME(#43234)
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index 8fddbe4ad9f4..513499927b32 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -131,7 +131,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
 
         for id in cleanups_to_remove {
             let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
-            *cleanup = UnwindAction::Continue;
+            *cleanup = UnwindAction::Unreachable;
         }
 
         // We may have invalidated some `cleanup` blocks so clean those up now.
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index b9af74a2061d..92c07ef5193a 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -24,7 +24,7 @@ use crate::MirPass;
 use rustc_const_eval::interpret::{
     self, compile_time_machine, AllocId, ConstAllocation, ConstValue, CtfeValidationMode, Frame,
     ImmTy, Immediate, InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer,
-    Scalar, StackPopCleanup, StackPopUnwind,
+    Scalar, StackPopCleanup,
 };
 
 /// The maximum number of bytes that we'll allocate space for a local or the return value.
@@ -209,7 +209,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
         _args: &[OpTy<'tcx>],
         _destination: &PlaceTy<'tcx>,
         _target: Option,
-        _unwind: StackPopUnwind,
+        _unwind: UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
         Ok(None)
     }
@@ -220,7 +220,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
         _args: &[OpTy<'tcx>],
         _destination: &PlaceTy<'tcx>,
         _target: Option,
-        _unwind: StackPopUnwind,
+        _unwind: UnwindAction,
     ) -> InterpResult<'tcx> {
         throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
     }
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 9217c2dc81cc..7d4d33f74501 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -399,7 +399,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             let loc = Location { block: bb, statement_index: data.statements.len() };
             let terminator = data.terminator();
 
-            let resume_block = self.patch.resume_block();
             match terminator.kind {
                 TerminatorKind::Drop { mut place, target, unwind } => {
                     if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) {
@@ -408,22 +407,29 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
 
                     self.init_data.seek_before(loc);
                     match self.move_data().rev_lookup.find(place.as_ref()) {
-                        LookupResult::Exact(path) => elaborate_drop(
-                            &mut Elaborator { ctxt: self },
-                            terminator.source_info,
-                            place,
-                            path,
-                            target,
-                            if data.is_cleanup {
+                        LookupResult::Exact(path) => {
+                            let unwind = if data.is_cleanup {
                                 Unwind::InCleanup
                             } else {
                                 match unwind {
                                     UnwindAction::Cleanup(cleanup) => Unwind::To(cleanup),
-                                    UnwindAction::Continue => Unwind::To(resume_block),
+                                    UnwindAction::Continue => Unwind::To(self.patch.resume_block()),
+                                    UnwindAction::Unreachable => {
+                                        Unwind::To(self.patch.unreachable_block())
+                                    }
+                                    UnwindAction::Terminate => Unwind::To(self.patch.terminate_block()),
                                 }
-                            },
-                            bb,
-                        ),
+                            };
+                            elaborate_drop(
+                                &mut Elaborator { ctxt: self },
+                                terminator.source_info,
+                                place,
+                                path,
+                                target,
+                                unwind,
+                                bb,
+                            )
+                        }
                         LookupResult::Parent(..) => {
                             if !matches!(
                                 terminator.source_info.span.desugaring_kind(),
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index a83e6a5b6807..8a4c3cc247a9 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1063,6 +1063,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             Unwind::To(match *unwind {
                 UnwindAction::Cleanup(tgt) => tgt,
                 UnwindAction::Continue => elaborator.patch.resume_block(),
+                UnwindAction::Unreachable => elaborator.patch.unreachable_block(),
             })
         };
         elaborate_drop(
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index c46cb5e98df6..a4a1acfe4288 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -1020,11 +1020,12 @@ impl Integrator<'_, '_> {
                 UnwindAction::Cleanup(_) => {
                     bug!("cleanup on cleanup block");
                 }
-                UnwindAction::Continue => return unwind,
+                UnwindAction::Continue | UnwindAction::Unreachable => return unwind,
             }
         }
 
         match unwind {
+            UnwindAction::Unreachable => unwind,
             UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
             // Add an unwind edge to the original call's cleanup block
             UnwindAction::Continue => self.cleanup_block,
@@ -1140,6 +1141,9 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
                     terminator.kind = TerminatorKind::Goto { target: tgt };
                 }
                 UnwindAction::Continue => (),
+                UnwindAction::Unreachable => {
+                    terminator.kind = TerminatorKind::Unreachable;
+                }
             },
             TerminatorKind::Abort => {}
             TerminatorKind::Unreachable => {}
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 75a415d88eef..565fe4eb7204 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -54,7 +54,7 @@ fn lower_slice_len_call<'tcx>(
             args,
             destination,
             target: Some(bb),
-            unwind: UnwindAction::Continue,
+            unwind: UnwindAction::Unreachable,
             from_hir_call: true,
             ..
         } => {
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 21a413002d06..8f6ae7294917 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -951,7 +951,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if this.machine.panic_on_unsupported {
             // message is slightly different here to make automated analysis easier
             let error_msg = format!("unsupported Miri functionality: {}", error_msg.as_ref());
-            this.start_panic(error_msg.as_ref(), StackPopUnwind::Skip)?;
+            this.start_panic(error_msg.as_ref(), mir::UnwindAction::Continue)?;
             Ok(())
         } else {
             throw_unsup_format!("{}", error_msg.as_ref());
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 621b90f0e572..477d8d33ebba 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -834,7 +834,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         ecx.find_mir_or_eval_fn(instance, abi, args, dest, ret, unwind)
     }
@@ -847,7 +847,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option,
-        _unwind: StackPopUnwind,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         ecx.call_dlsym(fn_val, abi, args, dest, ret)
     }
@@ -859,7 +859,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         ecx.call_intrinsic(instance, args, dest, ret, unwind)
     }
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 73439133af21..fcee381ff713 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -258,7 +258,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         let this = self.eval_context_mut();
         let link_name = this.item_link_name(def_id);
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index 9ecbb18ef5ad..ca2c1652dc19 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -26,7 +26,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option,
-        _unwind: StackPopUnwind,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index dbc48876a4b0..918efda3777f 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -34,7 +34,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         let this = self.eval_context_mut();
         trace!("eval_fn_call: {:#?}, {:?}", instance, dest);
@@ -70,7 +70,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         align_op: &OpTy<'tcx, Provenance>,
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, bool> {
         let this = self.eval_context_mut();
         let ret = ret.unwrap();
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index c31194b4b935..4f898e62773a 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -53,7 +53,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         link_name: Symbol,
         args: &[OpTy<'tcx, Provenance>],
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -106,7 +106,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             &[data.into()],
             None,
             // Directly return to caller.
-            StackPopCleanup::Goto { ret: Some(ret), unwind: StackPopUnwind::Skip },
+            StackPopCleanup::Goto { ret: Some(ret), unwind: mir::UnwindAction::Continue },
         )?;
 
         // We ourselves will return `0`, eventually (will be overwritten if we catch a panic).
@@ -157,7 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 &[catch_unwind.data.into(), payload.into()],
                 None,
                 // Directly return to caller of `try`.
-                StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: StackPopUnwind::Skip },
+                StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: mir::UnwindAction::Continue },
             )?;
 
             // We pushed a new stack frame, the engine should not do any jumping now!
@@ -168,7 +168,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 
     /// Start a panic in the interpreter with the given message as payload.
-    fn start_panic(&mut self, msg: &str, unwind: StackPopUnwind) -> InterpResult<'tcx> {
+    fn start_panic(&mut self, msg: &str, unwind: mir::UnwindAction) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         // First arg: message.
@@ -213,10 +213,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     None,
                     StackPopCleanup::Goto {
                         ret: None,
-                        unwind: match unwind {
-                            Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
-                            None => StackPopUnwind::Skip,
-                        },
+                        unwind,
                     },
                 )?;
             }
@@ -252,10 +249,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // Forward everything else to `panic` lang item.
                 this.start_panic(
                     msg.description(),
-                    match unwind {
-                        Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
-                        None => StackPopUnwind::Skip,
-                    },
+                    unwind,
                 )?;
             }
         }

From 0a5dac3062ffc80a283943e49e2ada08f0b0eaf7 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Mon, 10 Oct 2022 22:40:40 +0100
Subject: [PATCH 166/267] Add `UnwindAction::Terminate`

---
 compiler/rustc_borrowck/src/type_check/mod.rs |   8 +-
 compiler/rustc_codegen_ssa/src/mir/block.rs   | 156 +++++++++---------
 compiler/rustc_codegen_ssa/src/mir/mod.rs     |   4 +-
 .../src/interpret/eval_context.rs             |   3 +
 compiler/rustc_middle/src/mir/patch.rs        |   2 +
 compiler/rustc_middle/src/mir/syntax.rs       |   4 +
 compiler/rustc_middle/src/mir/terminator.rs   |   1 +
 .../rustc_mir_build/src/build/expr/into.rs    |   6 +-
 compiler/rustc_mir_build/src/build/scope.rs   |   2 +-
 .../rustc_mir_dataflow/src/elaborate_drops.rs |   4 +-
 .../src/abort_unwinding_calls.rs              |  28 +---
 .../src/elaborate_drops.rs                    |   6 +-
 compiler/rustc_mir_transform/src/generator.rs |   1 +
 compiler/rustc_mir_transform/src/inline.rs    |  11 +-
 .../src/lower_slice_len.rs                    |   1 -
 compiler/rustc_monomorphize/src/collector.rs  |  10 ++
 16 files changed, 126 insertions(+), 121 deletions(-)

diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 15d748a9e753..1fec2c9fcabb 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1663,8 +1663,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
                 self.assert_iscleanup(body, ctxt, unwind, true);
             }
-            UnwindAction::Continue => (),
-            UnwindAction::Unreachable => (),
+            UnwindAction::Continue => {
+                if is_cleanup {
+                    span_mirbug!(self, ctxt, "unwind on cleanup block")
+                }
+            }
+            UnwindAction::Unreachable | UnwindAction::Terminate => (),
         }
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 66bec6f30dea..5bc78e5dbacf 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -170,22 +170,17 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
 
         let unwind_block = match unwind {
             mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
-            _ if fx.mir[self.bb].is_cleanup
-                && fn_abi.can_unwind
-                && !base::wants_msvc_seh(fx.cx.tcx().sess) =>
-            {
-                // Exception must not propagate out of the execution of a cleanup (doing so
-                // can cause undefined behaviour). We insert a double unwind guard for
-                // functions that can potentially unwind to protect against this.
-                //
-                // This is not necessary for SEH which does not use successive unwinding
-                // like Itanium EH. EH frames in SEH are different from normal function
-                // frames and SEH will abort automatically if an exception tries to
-                // propagate out from cleanup.
-                Some(fx.double_unwind_guard())
-            }
             mir::UnwindAction::Continue => None,
             mir::UnwindAction::Unreachable => None,
+            mir::UnwindAction::Terminate => {
+                if fx.mir[self.bb].is_cleanup && base::wants_msvc_seh(fx.cx.tcx().sess) {
+                    // SEH will abort automatically if an exception tries to
+                    // propagate out from cleanup.
+                    None
+                } else {
+                    Some(fx.terminate_block())
+                }
+            }
         };
 
         if let Some(unwind_block) = unwind_block {
@@ -253,7 +248,14 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         instance: Instance<'_>,
         mergeable_succ: bool,
     ) -> MergingSucc {
-        if let mir::UnwindAction::Cleanup(cleanup) = unwind {
+        let unwind_target = match unwind {
+            mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
+            mir::UnwindAction::Terminate => Some(fx.terminate_block()),
+            mir::UnwindAction::Continue => None,
+            mir::UnwindAction::Unreachable => None,
+        };
+
+        if let Some(cleanup) = unwind_target {
             let ret_llbb = if let Some(target) = destination {
                 fx.llbb(target)
             } else {
@@ -266,7 +268,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
                 options,
                 line_spans,
                 instance,
-                Some((ret_llbb, self.llbb_with_cleanup(fx, cleanup), self.funclet(fx))),
+                Some((ret_llbb, cleanup, self.funclet(fx))),
             );
             MergingSucc::False
         } else {
@@ -1551,62 +1553,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
         let llbb = self.llbb(bb);
         if base::wants_msvc_seh(self.cx.sess()) {
-            let funclet;
-            let ret_llbb;
-            match self.mir[bb].terminator.as_ref().map(|t| &t.kind) {
-                // This is a basic block that we're aborting the program for,
-                // notably in an `extern` function. These basic blocks are inserted
-                // so that we assert that `extern` functions do indeed not panic,
-                // and if they do we abort the process.
-                //
-                // On MSVC these are tricky though (where we're doing funclets). If
-                // we were to do a cleanuppad (like below) the normal functions like
-                // `longjmp` would trigger the abort logic, terminating the
-                // program. Instead we insert the equivalent of `catch(...)` for C++
-                // which magically doesn't trigger when `longjmp` files over this
-                // frame.
-                //
-                // Lots more discussion can be found on #48251 but this codegen is
-                // modeled after clang's for:
-                //
-                //      try {
-                //          foo();
-                //      } catch (...) {
-                //          bar();
-                //      }
-                Some(&mir::TerminatorKind::Abort) => {
-                    let cs_llbb =
-                        Bx::append_block(self.cx, self.llfn, &format!("cs_funclet{:?}", bb));
-                    let cp_llbb =
-                        Bx::append_block(self.cx, self.llfn, &format!("cp_funclet{:?}", bb));
-                    ret_llbb = cs_llbb;
-
-                    let mut cs_bx = Bx::build(self.cx, cs_llbb);
-                    let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
-
-                    // The "null" here is actually a RTTI type descriptor for the
-                    // C++ personality function, but `catch (...)` has no type so
-                    // it's null. The 64 here is actually a bitfield which
-                    // represents that this is a catch-all block.
-                    let mut cp_bx = Bx::build(self.cx, cp_llbb);
-                    let null = cp_bx.const_null(
-                        cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space),
-                    );
-                    let sixty_four = cp_bx.const_i32(64);
-                    funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
-                    cp_bx.br(llbb);
-                }
-                _ => {
-                    let cleanup_llbb =
-                        Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb));
-                    ret_llbb = cleanup_llbb;
-                    let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
-                    funclet = cleanup_bx.cleanup_pad(None, &[]);
-                    cleanup_bx.br(llbb);
-                }
-            }
+            let cleanup_bb = Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb));
+            let mut cleanup_bx = Bx::build(self.cx, cleanup_bb);
+            let funclet = cleanup_bx.cleanup_pad(None, &[]);
+            cleanup_bx.br(llbb);
             self.funclets[bb] = Some(funclet);
-            ret_llbb
+            cleanup_bb
         } else {
             let cleanup_llbb = Bx::append_block(self.cx, self.llfn, "cleanup");
             let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
@@ -1633,26 +1585,68 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         })
     }
 
-    fn double_unwind_guard(&mut self) -> Bx::BasicBlock {
-        self.double_unwind_guard.unwrap_or_else(|| {
-            assert!(!base::wants_msvc_seh(self.cx.sess()));
+    fn terminate_block(&mut self) -> Bx::BasicBlock {
+        self.terminate_block.unwrap_or_else(|| {
+            let funclet;
+            let llbb;
+            let mut bx;
+            if base::wants_msvc_seh(self.cx.sess()) {
+                // This is a basic block that we're aborting the program for,
+                // notably in an `extern` function. These basic blocks are inserted
+                // so that we assert that `extern` functions do indeed not panic,
+                // and if they do we abort the process.
+                //
+                // On MSVC these are tricky though (where we're doing funclets). If
+                // we were to do a cleanuppad (like below) the normal functions like
+                // `longjmp` would trigger the abort logic, terminating the
+                // program. Instead we insert the equivalent of `catch(...)` for C++
+                // which magically doesn't trigger when `longjmp` files over this
+                // frame.
+                //
+                // Lots more discussion can be found on #48251 but this codegen is
+                // modeled after clang's for:
+                //
+                //      try {
+                //          foo();
+                //      } catch (...) {
+                //          bar();
+                //      }
+                llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
+                let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
+
+                let mut cs_bx = Bx::build(self.cx, llbb);
+                let cs = cs_bx.catch_switch(None, None, &[llbb]);
+
+                // The "null" here is actually a RTTI type descriptor for the
+                // C++ personality function, but `catch (...)` has no type so
+                // it's null. The 64 here is actually a bitfield which
+                // represents that this is a catch-all block.
+                bx = Bx::build(self.cx, cp_llbb);
+                let null =
+                    bx.const_null(bx.type_i8p_ext(bx.cx().data_layout().instruction_address_space));
+                let sixty_four = bx.const_i32(64);
+                funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null]));
+            } else {
+                llbb = Bx::append_block(self.cx, self.llfn, "terminate");
+                bx = Bx::build(self.cx, llbb);
+
+                let llpersonality = self.cx.eh_personality();
+                bx.cleanup_landing_pad(llpersonality);
+
+                funclet = None;
+            }
 
-            let llbb = Bx::append_block(self.cx, self.llfn, "abort");
-            let mut bx = Bx::build(self.cx, llbb);
             self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
 
-            let llpersonality = self.cx.eh_personality();
-            bx.cleanup_landing_pad(llpersonality);
-
             let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind);
             let fn_ty = bx.fn_decl_backend_type(&fn_abi);
 
-            let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], None);
+            let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], funclet.as_ref());
             bx.do_not_inline(llret);
 
             bx.unreachable();
 
-            self.double_unwind_guard = Some(llbb);
+            self.terminate_block = Some(llbb);
             llbb
         })
     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 189549953d94..0b4456dba30d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -74,7 +74,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
     unreachable_block: Option,
 
     /// Cached double unwind guarding block
-    double_unwind_guard: Option,
+    terminate_block: Option,
 
     /// The location where each MIR arg/var/tmp/ret is stored. This is
     /// usually an `PlaceRef` representing an alloca, but not always:
@@ -189,7 +189,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         personality_slot: None,
         cached_llbbs,
         unreachable_block: None,
-        double_unwind_guard: None,
+        terminate_block: None,
         cleanup_kinds,
         landing_pads: IndexVec::from_elem(None, &mir.basic_blocks),
         funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()),
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 94f3563cf762..209656cdf5c5 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -736,6 +736,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             mir::UnwindAction::Unreachable => {
                 throw_ub_format!("unwinding past a stack frame that does not allow unwinding")
             }
+            mir::UnwindAction::Terminate => {
+                M::abort(self, "panic in a function that cannot unwind".to_owned())?;
+            }
         };
         Ok(())
     }
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index 0f533dbb5946..0eae5fe69d6f 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -14,6 +14,7 @@ pub struct MirPatch<'tcx> {
     resume_block: Option,
     // Only for unreachable in cleanup path.
     unreachable_block: Option,
+    terminate_block: Option,
     body_span: Span,
     next_local: usize,
 }
@@ -28,6 +29,7 @@ impl<'tcx> MirPatch<'tcx> {
             next_local: body.local_decls.len(),
             resume_block: None,
             unreachable_block: None,
+            terminate_block: None,
             body_span: body.span,
         };
 
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index f7f2fc59ca52..f8804f7e5acb 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -763,6 +763,10 @@ pub enum UnwindAction {
     Continue,
     /// Triggers undefined behavior if unwind happens.
     Unreachable,
+    /// Terminates the execution if unwind happens.
+    ///
+    /// Depending on the platform and situation this may cause a non-unwindable panic or abort.
+    Terminate,
     /// Cleanups to be done.
     Cleanup(BasicBlock),
 }
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 1ef2a197d86e..dbe82a799c6f 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -274,6 +274,7 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
             // Not needed or included in successors
             None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None,
             Some(UnwindAction::Unreachable) => Some("unwind unreachable"),
+            Some(UnwindAction::Terminate) => Some("unwind terminate"),
         };
 
         match (successor_count, unwind) {
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index bafe7ede3d90..05a723a6b675 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -469,7 +469,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         } else {
                             Some(destination_block)
                         },
-                        unwind: UnwindAction::Continue,
+                        unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) {
+                            UnwindAction::Continue
+                        } else {
+                            UnwindAction::Unreachable
+                        },
                     },
                 );
                 if options.contains(InlineAsmOptions::MAY_UNWIND) {
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index f67659ac6bf0..6d6b726263b8 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -369,7 +369,7 @@ impl DropTree {
                     let terminator = TerminatorKind::Drop {
                         target: blocks[drop_data.1].unwrap(),
                         // The caller will handle this if needed.
-                        unwind: UnwindAction::Continue,
+                        unwind: UnwindAction::Terminate,
                         place: drop_data.0.local.into(),
                     };
                     cfg.terminate(block, drop_data.0.source_info, terminator);
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index f48016450604..ba51adee3084 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -80,7 +80,7 @@ impl Unwind {
     fn into_action(self) -> UnwindAction {
         match self {
             Unwind::To(bb) => UnwindAction::Cleanup(bb),
-            Unwind::InCleanup => UnwindAction::Continue,
+            Unwind::InCleanup => UnwindAction::Terminate,
         }
     }
 
@@ -946,7 +946,7 @@ where
             args,
             destination: unit_temp,
             target: Some(target),
-            unwind: UnwindAction::Unreachable,
+            unwind: UnwindAction::Terminate,
             from_hir_call: false,
             fn_span: self.source_info.span,
         }; // FIXME(#43234)
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index 513499927b32..5aed89139e2f 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -34,11 +34,6 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
             return;
         }
 
-        // This pass only runs on functions which themselves cannot unwind,
-        // forcibly changing the body of the function to structurally provide
-        // this guarantee by aborting on an unwind. If this function can unwind,
-        // then there's nothing to do because it already should work correctly.
-        //
         // Here we test for this function itself whether its ABI allows
         // unwinding or not.
         let body_ty = tcx.type_of(def_id).skip_binder();
@@ -107,26 +102,9 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
             }
         }
 
-        // For call instructions which need to be terminated, we insert a
-        // singular basic block which simply terminates, and then configure the
-        // `cleanup` attribute for all calls we found to this basic block we
-        // insert which means that any unwinding that happens in the functions
-        // will force an abort of the process.
-        if !calls_to_terminate.is_empty() {
-            let bb = BasicBlockData {
-                statements: Vec::new(),
-                is_cleanup: true,
-                terminator: Some(Terminator {
-                    source_info: SourceInfo::outermost(body.span),
-                    kind: TerminatorKind::Abort,
-                }),
-            };
-            let abort_bb = body.basic_blocks_mut().push(bb);
-
-            for bb in calls_to_terminate {
-                let cleanup = body.basic_blocks_mut()[bb].terminator_mut().unwind_mut().unwrap();
-                *cleanup = UnwindAction::Cleanup(abort_bb);
-            }
+        for id in calls_to_terminate {
+            let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
+            *cleanup = UnwindAction::Terminate;
         }
 
         for id in cleanups_to_remove {
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 7d4d33f74501..76fdbcdddd9e 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -417,7 +417,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                                     UnwindAction::Unreachable => {
                                         Unwind::To(self.patch.unreachable_block())
                                     }
-                                    UnwindAction::Terminate => Unwind::To(self.patch.terminate_block()),
+                                    UnwindAction::Terminate => {
+                                        Unwind::To(self.patch.terminate_block())
+                                    }
                                 }
                             };
                             elaborate_drop(
@@ -558,7 +560,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             if let TerminatorKind::Call {
                 destination,
                 target: Some(_),
-                unwind: UnwindAction::Continue,
+                unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate,
                 ..
             } = data.terminator().kind
             {
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 8a4c3cc247a9..bc147d38405c 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1064,6 +1064,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                 UnwindAction::Cleanup(tgt) => tgt,
                 UnwindAction::Continue => elaborator.patch.resume_block(),
                 UnwindAction::Unreachable => elaborator.patch.unreachable_block(),
+                UnwindAction::Terminate => elaborator.patch.terminate_block(),
             })
         };
         elaborate_drop(
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index a4a1acfe4288..b1480a524e51 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -1017,15 +1017,15 @@ impl Integrator<'_, '_> {
     fn map_unwind(&self, unwind: UnwindAction) -> UnwindAction {
         if self.in_cleanup_block {
             match unwind {
-                UnwindAction::Cleanup(_) => {
+                UnwindAction::Cleanup(_) | UnwindAction::Continue => {
                     bug!("cleanup on cleanup block");
                 }
-                UnwindAction::Continue | UnwindAction::Unreachable => return unwind,
+                UnwindAction::Unreachable | UnwindAction::Terminate => return unwind,
             }
         }
 
         match unwind {
-            UnwindAction::Unreachable => unwind,
+            UnwindAction::Unreachable | UnwindAction::Terminate => unwind,
             UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
             // Add an unwind edge to the original call's cleanup block
             UnwindAction::Continue => self.cleanup_block,
@@ -1141,7 +1141,10 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
                     terminator.kind = TerminatorKind::Goto { target: tgt };
                 }
                 UnwindAction::Continue => (),
-                UnwindAction::Unreachable => {
+                UnwindAction::Unreachable | UnwindAction::Terminate => {
+                    // If the action is terminate, then we would have mapped marked
+                    // all our call-sites as `UnwindAction::Terminate` and no cleanup
+                    // blocks would ever be executed.
                     terminator.kind = TerminatorKind::Unreachable;
                 }
             },
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 565fe4eb7204..7dc5878e0470 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -54,7 +54,6 @@ fn lower_slice_len_call<'tcx>(
             args,
             destination,
             target: Some(bb),
-            unwind: UnwindAction::Unreachable,
             from_hir_call: true,
             ..
         } => {
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index f41edff8513d..05253bb65ac9 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -872,6 +872,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             | mir::TerminatorKind::FalseUnwind { .. } => bug!(),
         }
 
+        if let Some(mir::UnwindAction::Terminate) = terminator.unwind() {
+            let instance = Instance::mono(
+                tcx,
+                tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
+            );
+            if should_codegen_locally(tcx, &instance) {
+                self.output.push(create_fn_mono_item(tcx, instance, source));
+            }
+        }
+
         self.super_terminator(terminator, location);
     }
 

From e3f2edc75bf2becb57d7d770bba20606da1c4224 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Mon, 31 Oct 2022 01:01:24 +0000
Subject: [PATCH 167/267] Rename `Abort` terminator to `Terminate`

Unify terminology used in unwind action and terminator, and reflect
the fact that a nounwind panic is triggered instead of an immediate
abort is triggered for this terminator.
---
 compiler/rustc_borrowck/src/invalidation.rs   |  2 +-
 compiler/rustc_borrowck/src/lib.rs            |  4 +-
 compiler/rustc_borrowck/src/type_check/mod.rs |  4 +-
 compiler/rustc_codegen_cranelift/src/base.rs  |  2 +-
 .../rustc_codegen_cranelift/src/constant.rs   |  2 +-
 compiler/rustc_codegen_ssa/src/mir/analyze.rs |  2 +-
 compiler/rustc_codegen_ssa/src/mir/block.rs   |  6 +--
 compiler/rustc_codegen_ssa/src/mir/mod.rs     |  2 +-
 .../rustc_const_eval/src/interpret/machine.rs |  2 +-
 .../src/interpret/terminator.rs               |  2 +-
 .../src/transform/check_consts/check.rs       |  4 +-
 .../check_consts/post_drop_elaboration.rs     |  2 +-
 .../src/transform/validate.rs                 |  7 ++-
 compiler/rustc_middle/src/mir/patch.rs        | 48 ++++++++++++++++++-
 compiler/rustc_middle/src/mir/spanview.rs     |  2 +-
 compiler/rustc_middle/src/mir/syntax.rs       |  8 ++--
 compiler/rustc_middle/src/mir/terminator.rs   | 12 ++---
 compiler/rustc_middle/src/mir/visit.rs        |  2 +-
 compiler/rustc_mir_build/src/build/scope.rs   |  2 +-
 compiler/rustc_mir_build/src/lints.rs         |  2 +-
 .../src/framework/direction.rs                |  2 +-
 .../src/impls/borrowed_locals.rs              |  2 +-
 .../src/impls/storage_liveness.rs             |  4 +-
 .../src/move_paths/builder.rs                 |  2 +-
 .../rustc_mir_transform/src/check_unsafety.rs |  2 +-
 .../rustc_mir_transform/src/const_prop.rs     |  2 +-
 .../src/const_prop_lint.rs                    |  2 +-
 .../rustc_mir_transform/src/coverage/debug.rs |  2 +-
 .../rustc_mir_transform/src/coverage/graph.rs |  4 +-
 .../rustc_mir_transform/src/coverage/spans.rs |  2 +-
 compiler/rustc_mir_transform/src/dest_prop.rs |  4 +-
 compiler/rustc_mir_transform/src/generator.rs |  4 +-
 compiler/rustc_mir_transform/src/inline.rs    | 22 ++++-----
 .../src/remove_noop_landing_pads.rs           |  2 +-
 .../src/separate_const_switch.rs              |  4 +-
 compiler/rustc_monomorphize/src/collector.rs  |  2 +-
 36 files changed, 112 insertions(+), 67 deletions(-)

diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index f69b35549b41..498d254da653 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -198,7 +198,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 }
             }
             TerminatorKind::Goto { target: _ }
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Unreachable
             | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
             | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 4787b0ea4e9d..3d876155fc95 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -801,7 +801,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
             }
 
             TerminatorKind::Goto { target: _ }
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Unreachable
             | TerminatorKind::Resume
             | TerminatorKind::Return
@@ -845,7 +845,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                 }
             }
 
-            TerminatorKind::Abort
+            TerminatorKind::Terminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Call { .. }
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 1fec2c9fcabb..fb8055230423 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1300,7 +1300,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         match &term.kind {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
@@ -1584,7 +1584,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     span_mirbug!(self, block_data, "resume on non-cleanup block!")
                 }
             }
-            TerminatorKind::Abort => {
+            TerminatorKind::Terminate => {
                 if !is_cleanup {
                     span_mirbug!(self, block_data, "abort on non-cleanup block!")
                 }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 94413318492f..f5301f9f7f10 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -488,7 +488,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                     *destination,
                 );
             }
-            TerminatorKind::Abort => {
+            TerminatorKind::Terminate => {
                 codegen_panic_cannot_unwind(fx, source_info);
             }
             TerminatorKind::Resume => {
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index ebb4de33f990..e87f4e258911 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -549,7 +549,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
                     TerminatorKind::Goto { .. }
                     | TerminatorKind::SwitchInt { .. }
                     | TerminatorKind::Resume
-                    | TerminatorKind::Abort
+                    | TerminatorKind::Terminate
                     | TerminatorKind::Return
                     | TerminatorKind::Unreachable
                     | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 7d1c80ba88f8..115a41050d2a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -284,7 +284,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec> FunctionCx<'a, 'tcx, Bx> {
         MergingSucc::False
     }
 
-    fn codegen_abort_terminator(
+    fn codegen_terminate_terminator(
         &mut self,
         helper: TerminatorCodegenHelper<'tcx>,
         bx: &mut Bx,
@@ -1263,8 +1263,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 MergingSucc::False
             }
 
-            mir::TerminatorKind::Abort => {
-                self.codegen_abort_terminator(helper, bx, terminator);
+            mir::TerminatorKind::Terminate => {
+                self.codegen_terminate_terminator(helper, bx, terminator);
                 MergingSucc::False
             }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 0b4456dba30d..c06b53445146 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -73,7 +73,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
     /// Cached unreachable block
     unreachable_block: Option,
 
-    /// Cached double unwind guarding block
+    /// Cached terminate upon unwinding block
     terminate_block: Option,
 
     /// The location where each MIR arg/var/tmp/ret is stored. This is
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index dda4f6e00f38..0291cca7378a 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -218,7 +218,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
 
-    /// Called to evaluate `Abort` MIR terminator.
+    /// Called to abort evaluation.
     fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: String) -> InterpResult<'tcx, !> {
         throw_unsup_format!("aborting execution is not supported")
     }
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index c8be2603ae9a..eef5518a1f83 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -144,7 +144,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
             }
 
-            Abort => {
+            Terminate => {
                 M::abort(self, "the program aborted execution".to_owned())?;
             }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 20c0852fe33a..9dad94790539 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -1031,9 +1031,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 self.check_op(ops::Generator(hir::GeneratorKind::Gen))
             }
 
-            TerminatorKind::Abort => {
+            TerminatorKind::Terminate => {
                 // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
-                span_bug!(self.span, "`Abort` terminator outside of cleanup block")
+                span_bug!(self.span, "`Terminate` terminator outside of cleanup block")
             }
 
             TerminatorKind::Assert { .. }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
index f01ab4c5d611..1f1640fd80ae 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
@@ -104,7 +104,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
                 }
             }
 
-            mir::TerminatorKind::Abort
+            mir::TerminatorKind::Terminate
             | mir::TerminatorKind::Call { .. }
             | mir::TerminatorKind::Assert { .. }
             | mir::TerminatorKind::FalseEdge { .. }
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index be840ef6f7f7..18372b5df011 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -1015,10 +1015,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            TerminatorKind::Resume | TerminatorKind::Abort => {
+            TerminatorKind::Resume | TerminatorKind::Terminate => {
                 let bb = location.block;
                 if !self.body.basic_blocks[bb].is_cleanup {
-                    self.fail(location, "Cannot `Resume` or `Abort` from non-cleanup basic block")
+                    self.fail(
+                        location,
+                        "Cannot `Resume` or `Terminate` from non-cleanup basic block",
+                    )
                 }
             }
             TerminatorKind::Return => {
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index 0eae5fe69d6f..d7e699e085db 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -37,7 +37,19 @@ impl<'tcx> MirPatch<'tcx> {
             // Check if we already have a resume block
             if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() {
                 result.resume_block = Some(bb);
-                break;
+                continue;
+            }
+
+            // Check if we already have an unreachable block
+            if let TerminatorKind::Unreachable = block.terminator().kind && block.statements.is_empty() {
+                result.unreachable_block = Some(bb);
+                continue;
+            }
+
+            // Check if we already have a terminate block
+            if let TerminatorKind::Terminate = block.terminator().kind && block.statements.is_empty() {
+                result.terminate_block = Some(bb);
+                continue;
             }
         }
 
@@ -61,6 +73,40 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
+    pub fn unreachable_block(&mut self) -> BasicBlock {
+        if let Some(bb) = self.unreachable_block {
+            return bb;
+        }
+
+        let bb = self.new_block(BasicBlockData {
+            statements: vec![],
+            terminator: Some(Terminator {
+                source_info: SourceInfo::outermost(self.body_span),
+                kind: TerminatorKind::Unreachable,
+            }),
+            is_cleanup: true,
+        });
+        self.unreachable_block = Some(bb);
+        bb
+    }
+
+    pub fn terminate_block(&mut self) -> BasicBlock {
+        if let Some(bb) = self.terminate_block {
+            return bb;
+        }
+
+        let bb = self.new_block(BasicBlockData {
+            statements: vec![],
+            terminator: Some(Terminator {
+                source_info: SourceInfo::outermost(self.body_span),
+                kind: TerminatorKind::Terminate,
+            }),
+            is_cleanup: true,
+        });
+        self.terminate_block = Some(bb);
+        bb
+    }
+
     pub fn is_patched(&self, bb: BasicBlock) -> bool {
         self.patch_map[bb].is_some()
     }
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 1a23f9dadd4f..2165403da267 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -262,7 +262,7 @@ pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str {
         Goto { .. } => "Goto",
         SwitchInt { .. } => "SwitchInt",
         Resume => "Resume",
-        Abort => "Abort",
+        Terminate => "Terminate",
         Return => "Return",
         Unreachable => "Unreachable",
         Drop { .. } => "Drop",
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index f8804f7e5acb..2dfa116ecefc 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -522,8 +522,8 @@ pub struct CopyNonOverlapping<'tcx> {
 ///
 /// The basic block pointed to by a `Cleanup` unwind action must have its `cleanup` flag set.
 /// `cleanup` basic blocks have a couple restrictions:
-///  1. All `unwind` fields in them must be `UnwindAction::Continue`.
-///  2. `Return` terminators are not allowed in them. `Abort` and `Unwind` terminators are.
+///  1. All `unwind` fields in them must be `UnwindAction::Terminate` or `UnwindAction::Unreachable`.
+///  2. `Return` terminators are not allowed in them. `Terminate` and `Unwind` terminators are.
 ///  3. All other basic blocks (in the current body) that are reachable from `cleanup` basic blocks
 ///     must also be `cleanup`. This is a part of the type system and checked statically, so it is
 ///     still an error to have such an edge in the CFG even if it's known that it won't be taken at
@@ -565,11 +565,11 @@ pub enum TerminatorKind<'tcx> {
     /// deaggregation runs.
     Resume,
 
-    /// Indicates that the landing pad is finished and that the process should abort.
+    /// Indicates that the landing pad is finished and that the process should terminate.
     ///
     /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in
     /// cleanup blocks.
-    Abort,
+    Terminate,
 
     /// Returns from the function.
     ///
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index dbe82a799c6f..2c6126cdd29c 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -155,7 +155,7 @@ impl<'tcx> TerminatorKind<'tcx> {
                 Some(t).into_iter().chain((&[]).into_iter().copied())
             }
             Resume
-            | Abort
+            | Terminate
             | GeneratorDrop
             | Return
             | Unreachable
@@ -197,7 +197,7 @@ impl<'tcx> TerminatorKind<'tcx> {
                 Some(t).into_iter().chain(&mut [])
             }
             Resume
-            | Abort
+            | Terminate
             | GeneratorDrop
             | Return
             | Unreachable
@@ -214,7 +214,7 @@ impl<'tcx> TerminatorKind<'tcx> {
         match *self {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -233,7 +233,7 @@ impl<'tcx> TerminatorKind<'tcx> {
         match *self {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -310,7 +310,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             Return => write!(fmt, "return"),
             GeneratorDrop => write!(fmt, "generator_drop"),
             Resume => write!(fmt, "resume"),
-            Abort => write!(fmt, "abort"),
+            Terminate => write!(fmt, "abort"),
             Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value),
             Unreachable => write!(fmt, "unreachable"),
             Drop { place, .. } => write!(fmt, "drop({:?})", place),
@@ -389,7 +389,7 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn fmt_successor_labels(&self) -> Vec> {
         use self::TerminatorKind::*;
         match *self {
-            Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
+            Return | Resume | Terminate | Unreachable | GeneratorDrop => vec![],
             Goto { .. } => vec!["".into()],
             SwitchInt { ref targets, .. } => targets
                 .values
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 243c62f4a9c2..6c4ea065abeb 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -462,7 +462,7 @@ macro_rules! make_mir_visitor {
                 match kind {
                     TerminatorKind::Goto { .. } |
                     TerminatorKind::Resume |
-                    TerminatorKind::Abort |
+                    TerminatorKind::Terminate |
                     TerminatorKind::GeneratorDrop |
                     TerminatorKind::Unreachable |
                     TerminatorKind::FalseEdge { .. } |
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 6d6b726263b8..2c401405f928 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -1454,7 +1454,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Yield { .. }
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 910db7f676d7..8e41957af0eb 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -108,7 +108,7 @@ impl<'mir, 'tcx> TriColorVisitor> for Search<'mir, 'tcx> {
 
         match self.body[bb].terminator().kind {
             // These terminators return control flow to the caller.
-            TerminatorKind::Abort
+            TerminatorKind::Terminate
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Resume
             | TerminatorKind::Return
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index a078c6b550e1..c8fe1af6674c 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -474,7 +474,7 @@ impl Direction for Forward {
     {
         use mir::TerminatorKind::*;
         match bb_data.terminator().kind {
-            Return | Resume | Abort | GeneratorDrop | Unreachable => {}
+            Return | Resume | Terminate | GeneratorDrop | Unreachable => {}
 
             Goto { target } => propagate(target, exit_state),
 
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 08fadfe68a17..92d30f254a6a 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -125,7 +125,7 @@ where
                 }
             }
 
-            TerminatorKind::Abort
+            TerminatorKind::Terminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Call { .. }
             | TerminatorKind::FalseEdge { .. }
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 99988b29e8a5..4a5d9d520108 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -200,7 +200,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
-            TerminatorKind::Abort
+            TerminatorKind::Terminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
@@ -237,7 +237,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
             TerminatorKind::Yield { .. }
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 9f9a5c94b560..64ed7a29f6f3 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -375,7 +375,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             // need recording.
             | TerminatorKind::Return
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. } => {}
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index c4d058e8ecbf..d908f6b3a9b5 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -57,7 +57,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
             | TerminatorKind::Assert { .. }
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::FalseEdge { .. }
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 92c07ef5193a..f0266051f378 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -959,7 +959,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
             // None of these have Operands to const-propagate.
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 942ccd5a9d19..1a96fddcd730 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -686,7 +686,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
             // None of these have Operands to const-propagate.
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index 0e7dc171a5d0..725883b83fa9 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -818,7 +818,7 @@ pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str {
         TerminatorKind::Goto { .. } => "Goto",
         TerminatorKind::SwitchInt { .. } => "SwitchInt",
         TerminatorKind::Resume => "Resume",
-        TerminatorKind::Abort => "Abort",
+        TerminatorKind::Terminate => "Terminate",
         TerminatorKind::Return => "Return",
         TerminatorKind::Unreachable => "Unreachable",
         TerminatorKind::Drop { .. } => "Drop",
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 6a73f2a65781..7391a77b0a66 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -122,7 +122,7 @@ impl CoverageGraph {
 
             match term.kind {
                 TerminatorKind::Return { .. }
-                | TerminatorKind::Abort
+                | TerminatorKind::Terminate
                 | TerminatorKind::Yield { .. }
                 | TerminatorKind::SwitchInt { .. } => {
                     // The `bb` has more than one _outgoing_ edge, or exits the function. Save the
@@ -136,7 +136,7 @@ impl CoverageGraph {
                     debug!("  because term.kind = {:?}", term.kind);
                     // Note that this condition is based on `TerminatorKind`, even though it
                     // theoretically boils down to `successors().len() != 1`; that is, either zero
-                    // (e.g., `Return`, `Abort`) or multiple successors (e.g., `SwitchInt`), but
+                    // (e.g., `Return`, `Terminate`) or multiple successors (e.g., `SwitchInt`), but
                     // since the BCB CFG ignores things like unwind branches (which exist in the
                     // `Terminator`s `successors()` list) checking the number of successors won't
                     // work.
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 2f1202586594..287ae2170875 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -869,7 +869,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option (),
             TerminatorKind::Drop { .. } => {
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index bc147d38405c..c77ea6e34727 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1194,7 +1194,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
             // These never unwind.
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -1701,7 +1701,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
             | TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index b1480a524e51..f0cb317f449f 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -1136,19 +1136,15 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
                     TerminatorKind::Unreachable
                 }
             }
-            TerminatorKind::Resume => match self.cleanup_block {
-                UnwindAction::Cleanup(tgt) => {
-                    terminator.kind = TerminatorKind::Goto { target: tgt };
-                }
-                UnwindAction::Continue => (),
-                UnwindAction::Unreachable | UnwindAction::Terminate => {
-                    // If the action is terminate, then we would have mapped marked
-                    // all our call-sites as `UnwindAction::Terminate` and no cleanup
-                    // blocks would ever be executed.
-                    terminator.kind = TerminatorKind::Unreachable;
-                }
-            },
-            TerminatorKind::Abort => {}
+            TerminatorKind::Resume => {
+                terminator.kind = match self.cleanup_block {
+                    UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt },
+                    UnwindAction::Continue => TerminatorKind::Resume,
+                    UnwindAction::Unreachable => TerminatorKind::Unreachable,
+                    UnwindAction::Terminate => TerminatorKind::Terminate,
+                };
+            }
+            TerminatorKind::Terminate => {}
             TerminatorKind::Unreachable => {}
             TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
                 *real_target = self.map_block(*real_target);
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index b4d68f4a322e..4941c9edce30 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -72,7 +72,7 @@ impl RemoveNoopLandingPads {
             TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::Return
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Unreachable
             | TerminatorKind::Call { .. }
             | TerminatorKind::Assert { .. }
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index d76ab95faba9..ef367faf6a70 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -112,7 +112,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
                         | TerminatorKind::Assert { .. }
                         | TerminatorKind::FalseUnwind { .. }
                         | TerminatorKind::Yield { .. }
-                        | TerminatorKind::Abort
+                        | TerminatorKind::Terminate
                         | TerminatorKind::Return
                         | TerminatorKind::Unreachable
                         | TerminatorKind::InlineAsm { .. }
@@ -164,7 +164,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
             }
 
             TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 05253bb65ac9..7bcff7e07fb3 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -852,7 +852,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                     self.output.push(create_fn_mono_item(tcx, instance, source));
                 }
             }
-            mir::TerminatorKind::Abort { .. } => {
+            mir::TerminatorKind::Terminate { .. } => {
                 let instance = Instance::mono(
                     tcx,
                     tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),

From 3af45d6c571ab634dfb3dcc941b32afe4119e934 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Tue, 15 Nov 2022 17:00:40 +0000
Subject: [PATCH 168/267] Address review feedback

---
 compiler/rustc_codegen_ssa/src/mir/block.rs   |  4 +-
 .../src/transform/validate.rs                 | 38 +++++++++++--------
 compiler/rustc_middle/src/mir/patch.rs        | 17 +++++----
 compiler/rustc_middle/src/mir/syntax.rs       |  4 +-
 .../src/elaborate_drops.rs                    |  2 +-
 compiler/rustc_mir_transform/src/generator.rs |  2 +-
 compiler/rustc_mir_transform/src/shim.rs      |  4 +-
 7 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 65b20142efee..7f220681a94c 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -147,7 +147,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
     }
 
     /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional
-    /// return destination `destination` and the cleanup function `cleanup`.
+    /// return destination `destination` and the unwind action `unwind`.
     fn do_call>(
         &self,
         fx: &mut FunctionCx<'a, 'tcx, Bx>,
@@ -234,7 +234,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         }
     }
 
-    /// Generates inline assembly with optional `destination` and `cleanup`.
+    /// Generates inline assembly with optional `destination` and `unwind`.
     fn do_inlineasm>(
         &self,
         fx: &mut FunctionCx<'a, 'tcx, Bx>,
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 18372b5df011..0f56fda18f56 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -232,6 +232,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
+    fn check_unwind_edge(&mut self, location: Location, unwind: UnwindAction) {
+        let is_cleanup = self.body.basic_blocks[location.block].is_cleanup;
+        match unwind {
+            UnwindAction::Cleanup(unwind) => {
+                if is_cleanup {
+                    self.fail(location, "unwind on cleanup block");
+                }
+                self.check_edge(location, unwind, EdgeKind::Unwind);
+            }
+            UnwindAction::Continue => {
+                if is_cleanup {
+                    self.fail(location, "unwind on cleanup block");
+                }
+            }
+            UnwindAction::Unreachable | UnwindAction::Terminate => (),
+        }
+    }
+
     /// Check if src can be assigned into dest.
     /// This is not precise, it will accept some incorrect assignments.
     fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
@@ -902,9 +920,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::Drop { target, unwind, .. } => {
                 self.check_edge(location, *target, EdgeKind::Normal);
-                if let UnwindAction::Cleanup(unwind) = unwind {
-                    self.check_edge(location, *unwind, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
             }
             TerminatorKind::Call { func, args, destination, target, unwind, .. } => {
                 let func_ty = func.ty(&self.body.local_decls, self.tcx);
@@ -918,9 +934,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 if let Some(target) = target {
                     self.check_edge(location, *target, EdgeKind::Normal);
                 }
-                if let UnwindAction::Cleanup(cleanup) = unwind {
-                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
 
                 // The call destination place and Operand::Move place used as an argument might be
                 // passed by a reference to the callee. Consequently they must be non-overlapping.
@@ -958,9 +972,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
                 self.check_edge(location, *target, EdgeKind::Normal);
-                if let UnwindAction::Cleanup(cleanup) = unwind {
-                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
             }
             TerminatorKind::Yield { resume, drop, .. } => {
                 if self.body.generator.is_none() {
@@ -992,17 +1004,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
                 self.check_edge(location, *real_target, EdgeKind::Normal);
-                if let UnwindAction::Cleanup(unwind) = unwind {
-                    self.check_edge(location, *unwind, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
             }
             TerminatorKind::InlineAsm { destination, unwind, .. } => {
                 if let Some(destination) = destination {
                     self.check_edge(location, *destination, EdgeKind::Normal);
                 }
-                if let UnwindAction::Cleanup(cleanup) = unwind {
-                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
             }
             TerminatorKind::GeneratorDrop => {
                 if self.body.generator.is_none() {
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index d7e699e085db..b898e85fa71b 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -13,7 +13,7 @@ pub struct MirPatch<'tcx> {
     new_locals: Vec>,
     resume_block: Option,
     // Only for unreachable in cleanup path.
-    unreachable_block: Option,
+    unreachable_cleanup_block: Option,
     terminate_block: Option,
     body_span: Span,
     next_local: usize,
@@ -28,7 +28,7 @@ impl<'tcx> MirPatch<'tcx> {
             new_locals: vec![],
             next_local: body.local_decls.len(),
             resume_block: None,
-            unreachable_block: None,
+            unreachable_cleanup_block: None,
             terminate_block: None,
             body_span: body.span,
         };
@@ -41,8 +41,11 @@ impl<'tcx> MirPatch<'tcx> {
             }
 
             // Check if we already have an unreachable block
-            if let TerminatorKind::Unreachable = block.terminator().kind && block.statements.is_empty() {
-                result.unreachable_block = Some(bb);
+            if let TerminatorKind::Unreachable = block.terminator().kind
+                && block.statements.is_empty()
+                && block.is_cleanup
+            {
+                result.unreachable_cleanup_block = Some(bb);
                 continue;
             }
 
@@ -73,8 +76,8 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
-    pub fn unreachable_block(&mut self) -> BasicBlock {
-        if let Some(bb) = self.unreachable_block {
+    pub fn unreachable_cleanup_block(&mut self) -> BasicBlock {
+        if let Some(bb) = self.unreachable_cleanup_block {
             return bb;
         }
 
@@ -86,7 +89,7 @@ impl<'tcx> MirPatch<'tcx> {
             }),
             is_cleanup: true,
         });
-        self.unreachable_block = Some(bb);
+        self.unreachable_cleanup_block = Some(bb);
         bb
     }
 
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 2dfa116ecefc..135889d0da81 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -523,7 +523,7 @@ pub struct CopyNonOverlapping<'tcx> {
 /// The basic block pointed to by a `Cleanup` unwind action must have its `cleanup` flag set.
 /// `cleanup` basic blocks have a couple restrictions:
 ///  1. All `unwind` fields in them must be `UnwindAction::Terminate` or `UnwindAction::Unreachable`.
-///  2. `Return` terminators are not allowed in them. `Terminate` and `Unwind` terminators are.
+///  2. `Return` terminators are not allowed in them. `Terminate` and `Resume` terminators are.
 ///  3. All other basic blocks (in the current body) that are reachable from `cleanup` basic blocks
 ///     must also be `cleanup`. This is a part of the type system and checked statically, so it is
 ///     still an error to have such an edge in the CFG even if it's known that it won't be taken at
@@ -721,8 +721,6 @@ pub enum TerminatorKind<'tcx> {
         /// consider it in borrowck. We don't want to accept programs which
         /// pass borrowck only when `panic=abort` or some assertions are disabled
         /// due to release vs. debug mode builds.
-        /// This field does not necessary have to be `UnwindAction::Cleanup` because
-        /// of the `remove_noop_landing_pads` and `abort_unwinding_calls` passes.
         unwind: UnwindAction,
     },
 
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 76fdbcdddd9e..dd7fd2524e0a 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -415,7 +415,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                                     UnwindAction::Cleanup(cleanup) => Unwind::To(cleanup),
                                     UnwindAction::Continue => Unwind::To(self.patch.resume_block()),
                                     UnwindAction::Unreachable => {
-                                        Unwind::To(self.patch.unreachable_block())
+                                        Unwind::To(self.patch.unreachable_cleanup_block())
                                     }
                                     UnwindAction::Terminate => {
                                         Unwind::To(self.patch.terminate_block())
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index c77ea6e34727..4352d34cb897 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1063,7 +1063,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             Unwind::To(match *unwind {
                 UnwindAction::Cleanup(tgt) => tgt,
                 UnwindAction::Continue => elaborator.patch.resume_block(),
-                UnwindAction::Unreachable => elaborator.patch.unreachable_block(),
+                UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(),
                 UnwindAction::Terminate => elaborator.patch.terminate_block(),
             })
         };
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index f5a65e127054..2787fe2ce42c 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -543,7 +543,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
                 TerminatorKind::Drop {
                     place: dest_field,
                     target: unwind,
-                    unwind: UnwindAction::Continue,
+                    unwind: UnwindAction::Terminate,
                 },
                 true,
             );
@@ -814,7 +814,7 @@ fn build_call_shim<'tcx>(
             TerminatorKind::Drop {
                 place: rcvr_place(),
                 target: BasicBlock::new(4),
-                unwind: UnwindAction::Continue,
+                unwind: UnwindAction::Terminate,
             },
             true,
         );

From 5cbda2a55e40c9d978850ebc3175d9a9e1dbea92 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Mon, 10 Oct 2022 23:17:07 +0100
Subject: [PATCH 169/267] Fix tools

---
 compiler/rustc_const_eval/src/interpret/eval_context.rs   | 1 +
 src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 209656cdf5c5..3e58a58aef7d 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -737,6 +737,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 throw_ub_format!("unwinding past a stack frame that does not allow unwinding")
             }
             mir::UnwindAction::Terminate => {
+                self.frame_mut().loc = Right(self.frame_mut().body.span);
                 M::abort(self, "panic in a function that cannot unwind".to_owned())?;
             }
         };
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index ff195cd72880..354b6d71aa46 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -301,13 +301,13 @@ fn check_terminator<'tcx>(
         | TerminatorKind::Goto { .. }
         | TerminatorKind::Return
         | TerminatorKind::Resume
+        | TerminatorKind::Terminate
         | TerminatorKind::Unreachable => Ok(()),
 
         TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body),
 
         TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
 
-        TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
         TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
             Err((span, "const fn generators are unstable".into()))
         },

From bf6b84b10a5d17f4f3a8c75a04bc042920a313d8 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Tue, 15 Nov 2022 18:27:21 +0000
Subject: [PATCH 170/267] Fix new usage of old api

---
 compiler/rustc_mir_dataflow/src/value_analysis.rs       | 2 +-
 compiler/rustc_mir_transform/src/check_alignment.rs     | 2 +-
 compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 6 +++---
 compiler/rustc_smir/src/rustc_smir/mod.rs               | 2 +-
 src/tools/miri/src/shims/panic.rs                       | 5 +----
 5 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 33a15a8d224f..98bebc9b13bc 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -238,7 +238,7 @@ pub trait ValueAnalysis<'tcx> {
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Assert { .. }
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 5815887e5bbb..8086a4557b70 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -221,7 +221,7 @@ fn insert_alignment_check<'tcx>(
                 required: Operand::Copy(alignment),
                 found: Operand::Copy(addr),
             },
-            cleanup: None,
+            unwind: UnwindAction::Terminate,
         },
     });
 }
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 15f5df41153b..d4db7e2de403 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -567,7 +567,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
         _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>],
         _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>,
         _target: Option,
-        _unwind: rustc_const_eval::interpret::StackPopUnwind,
+        _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
         unimplemented!()
     }
@@ -578,7 +578,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
         _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>],
         _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>,
         _target: Option,
-        _unwind: rustc_const_eval::interpret::StackPopUnwind,
+        _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx> {
         unimplemented!()
     }
@@ -586,7 +586,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
     fn assert_panic(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _msg: &rustc_middle::mir::AssertMessage<'tcx>,
-        _unwind: Option,
+        _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx> {
         unimplemented!()
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 86e30dd0f6a2..0befff894ef3 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -143,7 +143,7 @@ fn rustc_terminator_to_terminator(
             otherwise: targets.otherwise().as_usize(),
         },
         Resume => Terminator::Resume,
-        Abort => Terminator::Abort,
+        Terminate => Terminator::Abort,
         Return => Terminator::Return,
         Unreachable => Terminator::Unreachable,
         Drop { .. } => todo!(),
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 4f898e62773a..2cca2f3f3914 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -237,10 +237,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     None,
                     StackPopCleanup::Goto {
                         ret: None,
-                        unwind: match unwind {
-                            Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
-                            None => StackPopUnwind::Skip,
-                        },
+                        unwind,
                     },
                 )?;
             }

From de3f8a157809bd1972be268fbb0f663f7dfa6657 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Thu, 17 Nov 2022 02:58:42 +0000
Subject: [PATCH 171/267] Fix MSVC build

---
 compiler/rustc_codegen_ssa/src/mir/block.rs | 2 +-
 compiler/rustc_codegen_ssa/src/mir/mod.rs   | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 7f220681a94c..dd86977817fb 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1615,7 +1615,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
 
                 let mut cs_bx = Bx::build(self.cx, llbb);
-                let cs = cs_bx.catch_switch(None, None, &[llbb]);
+                let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
 
                 // The "null" here is actually a RTTI type descriptor for the
                 // C++ personality function, but `catch (...)` has no type so
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index c06b53445146..3dadb33c9691 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -166,7 +166,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     let start_llbb = Bx::append_block(cx, llfn, "start");
     let mut start_bx = Bx::build(cx, start_llbb);
 
-    if mir.basic_blocks.iter().any(|bb| bb.is_cleanup) {
+    if mir.basic_blocks.iter().any(|bb| {
+        bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate))
+    }) {
         start_bx.set_personality_fn(cx.eh_personality());
     }
 

From 5ae3a53a447bab9501ecb86b3fa686488c9f48dd Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Thu, 17 Nov 2022 16:07:45 +0000
Subject: [PATCH 172/267] Revert box_free unwind action

---
 compiler/rustc_mir_dataflow/src/elaborate_drops.rs | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index ba51adee3084..bd8ec82dffd1 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -946,7 +946,11 @@ where
             args,
             destination: unit_temp,
             target: Some(target),
-            unwind: UnwindAction::Terminate,
+            unwind: if unwind.is_cleanup() {
+                UnwindAction::Terminate
+            } else {
+                UnwindAction::Continue
+            },
             from_hir_call: false,
             fn_span: self.source_info.span,
         }; // FIXME(#43234)

From e29b5badbcf1d2f5e16bca00d067e07c18770f12 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Sat, 19 Nov 2022 18:44:21 +0000
Subject: [PATCH 173/267] Fix mir interp of `TerminatorKind::Terminate`

---
 compiler/rustc_const_eval/src/interpret/terminator.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index eef5518a1f83..a07702f7d9bb 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -145,7 +145,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
 
             Terminate => {
-                M::abort(self, "the program aborted execution".to_owned())?;
+                // FIXME: maybe should call `panic_no_unwind` lang item instead.
+                M::abort(self, "panic in a function that cannot unwind".to_owned())?;
             }
 
             // When we encounter Resume, we've finished unwinding

From c5829c2ee544eb9931ce0d34f46b113b0a1e7f04 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Mon, 6 Mar 2023 16:36:42 +0000
Subject: [PATCH 174/267] Fix new usage of old api

---
 .../rustc_mir_build/src/build/custom/parse/instruction.rs     | 4 ++--
 compiler/rustc_mir_build/src/build/scope.rs                   | 4 ++--
 compiler/rustc_mir_transform/src/elaborate_drops.rs           | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 33b73928704a..54028dfe87b7 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -56,7 +56,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                 Ok(TerminatorKind::Drop {
                     place: self.parse_place(args[0])?,
                     target: self.parse_block(args[1])?,
-                    unwind: None,
+                    unwind: UnwindAction::Continue,
                 })
             },
             @call("mir_call", args) => {
@@ -126,7 +126,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                     args,
                     destination,
                     target: Some(target),
-                    cleanup: None,
+                    unwind: UnwindAction::Continue,
                     from_hir_call: *from_hir_call,
                     fn_span: *fn_span,
                 })
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 2c401405f928..f32d2db4e712 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -1438,11 +1438,11 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
         let term = &mut cfg.block_data_mut(from).terminator_mut();
         match &mut term.kind {
             TerminatorKind::Drop { unwind, .. } => {
-                if let Some(unwind) = *unwind {
+                if let UnwindAction::Cleanup(unwind) = *unwind {
                     let source_info = term.source_info;
                     cfg.terminate(unwind, source_info, TerminatorKind::Goto { target: to });
                 } else {
-                    *unwind = Some(to);
+                    *unwind = UnwindAction::Cleanup(to);
                 }
             }
             TerminatorKind::FalseUnwind { unwind, .. }
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index dd7fd2524e0a..a702113bd999 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -160,7 +160,7 @@ fn remove_dead_unwinds<'tcx>(
     let basic_blocks = body.basic_blocks.as_mut();
     for &bb in dead_unwinds.iter() {
         if let Some(unwind) = basic_blocks[bb].terminator_mut().unwind_mut() {
-            *unwind = None;
+            *unwind = UnwindAction::Unreachable;
         }
     }
 }

From 2a9d710d999e629c064908076420635096eb39de Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Wed, 5 Apr 2023 09:17:40 +0100
Subject: [PATCH 175/267] Bless tests

---
 src/tools/miri/tests/fail/abort-terminator.rs |  2 +-
 .../miri/tests/fail/abort-terminator.stderr   |  4 +-
 .../exported_symbol_bad_unwind2.both.stderr   |  4 +-
 ...orted_symbol_bad_unwind2.definition.stderr |  4 +-
 .../exported_symbol_bad_unwind2.rs            |  4 +-
 ...c_abort.main.AbortUnwindingCalls.after.mir |  6 +--
 .../basic_assignment.main.ElaborateDrops.diff | 10 +++--
 ...ignment.main.SimplifyCfg-initial.after.mir |  6 +--
 .../box_expr.main.ElaborateDrops.before.mir   |  6 +--
 ...await.b-{closure#0}.generator_resume.0.mir | 16 +++----
 .../building/enum_cast.droppy.built.after.mir |  2 +-
 .../building/issue_49232.main.built.after.mir |  2 +-
 ...e_out.move_out_by_subslice.built.after.mir |  6 +--
 ...move_out.move_out_from_end.built.after.mir |  6 +--
 ...primitives.{impl#0}-clone.InstCombine.diff |  2 +-
 ...transmutes.adt_transmutes.InstCombine.diff |  2 +-
 ...mutes.identity_transmutes.InstCombine.diff |  4 +-
 .../string.foo.PreCodegen.after.mir           |  8 ++--
 .../derefer_inline_test.main.Derefer.diff     |  2 +-
 .../dont_yeet_assert.generic.InstCombine.diff |  2 +-
 ...main-{closure#0}.StateTransform.before.mir |  4 +-
 ...ny.main-{closure#0}.generator_resume.0.mir |  2 +-
 .../inline/asm_unwind.main.Inline.diff        |  2 +-
 tests/mir-opt/inline/cycle.f.Inline.diff      |  2 +-
 tests/mir-opt/inline/cycle.g.Inline.diff      |  2 +-
 tests/mir-opt/inline/cycle.main.Inline.diff   |  2 +-
 .../inline/inline_diverging.h.Inline.diff     |  4 +-
 ...inline_instruction_set.default.Inline.diff | 10 ++---
 .../inline_instruction_set.t32.Inline.diff    | 10 ++---
 .../inline_into_box_place.main.Inline.diff    |  2 +-
 .../inline/issue_78442.bar.Inline.diff        |  4 +-
 .../inline/issue_78442.bar.RevealAll.diff     |  2 +-
 ...unchecked_shl_unsigned_smaller.Inline.diff |  2 +-
 ..._shl_unsigned_smaller.PreCodegen.after.mir |  2 +-
 ...s.unchecked_shr_signed_smaller.Inline.diff |  2 +-
 ...ed_shr_signed_smaller.PreCodegen.after.mir |  2 +-
 ...ment_coverage.main.InstrumentCoverage.diff |  2 +-
 ...intrinsic_asserts.generic.InstCombine.diff |  6 +--
 .../intrinsic_asserts.panics.InstCombine.diff | 12 +++---
 ...trinsic_asserts.removable.InstCombine.diff |  6 +--
 .../mir-opt/issue_101973.inner.ConstProp.diff |  2 +-
 ...e_38669.main.SimplifyCfg-initial.after.mir |  2 +-
 .../issue_41110.main.ElaborateDrops.diff      |  8 ++--
 .../issue_41110.test.ElaborateDrops.diff      | 18 ++++----
 .../issue_41888.main.ElaborateDrops.diff      | 42 ++++++++++---------
 ...issue_62289.test.ElaborateDrops.before.mir |  4 +-
 tests/mir-opt/issue_91633.bar.built.after.mir |  2 +-
 tests/mir-opt/issue_91633.foo.built.after.mir |  2 +-
 ....main.SimplifyCfg-promote-consts.after.mir |  2 +-
 ...r_intrinsics.align_of.LowerIntrinsics.diff |  2 +-
 ...wer_intrinsics.assume.LowerIntrinsics.diff |  2 +-
 ...trinsics.discriminant.LowerIntrinsics.diff |  8 ++--
 ...f_copy_nonoverlapping.LowerIntrinsics.diff |  2 +-
 ...wer_intrinsics.forget.LowerIntrinsics.diff |  2 +-
 ..._intrinsics.non_const.LowerIntrinsics.diff |  2 +-
 ...insics.option_payload.LowerIntrinsics.diff |  4 +-
 ...ad_via_copy_primitive.LowerIntrinsics.diff |  2 +-
 ..._via_copy_uninhabited.LowerIntrinsics.diff |  2 +-
 ...er_intrinsics.size_of.LowerIntrinsics.diff |  2 +-
 ...s.transmute_inhabited.LowerIntrinsics.diff |  2 +-
 ...ics.transmute_ref_dst.LowerIntrinsics.diff |  2 +-
 ...te_to_box_uninhabited.LowerIntrinsics.diff |  2 +-
 ...te_to_mut_uninhabited.LowerIntrinsics.diff |  2 +-
 ...te_to_ref_uninhabited.LowerIntrinsics.diff |  2 +-
 ...transmute_uninhabited.LowerIntrinsics.diff |  2 +-
 ...ntrinsics.unreachable.LowerIntrinsics.diff |  2 +-
 ...rinsics.with_overflow.LowerIntrinsics.diff |  6 +--
 ...r_intrinsics.wrapping.LowerIntrinsics.diff |  6 +--
 ..._intrinsics_e2e.f_u64.PreCodegen.after.mir |  2 +-
 ...intrinsics_e2e.f_unit.PreCodegen.after.mir |  2 +-
 ...fg-initial.after-ElaborateDrops.after.diff |  2 +-
 ..._after_call.main.ElaborateDrops.before.mir |  2 +-
 ...main.SimplifyCfg-elaborate-drops.after.mir |  2 +-
 ...main.SimplifyCfg-elaborate-drops.after.mir |  4 +-
 ...simplify_cfg.main.SimplifyCfg-initial.diff |  4 +-
 ...[String].AddMovesForPackedDrops.before.mir |  2 +-
 ...mes.foo.ScalarReplacementOfAggregates.diff | 16 +++----
 ...ropping.ScalarReplacementOfAggregates.diff |  6 +--
 ...scaping.ScalarReplacementOfAggregates.diff |  4 +-
 ...Vec_i32_.AddMovesForPackedDrops.before.mir |  2 +-
 .../expected_show_coverage.abort.txt          |  2 +-
 tests/run-make/coverage/abort.rs              |  2 +-
 82 files changed, 187 insertions(+), 179 deletions(-)

diff --git a/src/tools/miri/tests/fail/abort-terminator.rs b/src/tools/miri/tests/fail/abort-terminator.rs
index c954443a2762..876b9a9ab0ab 100644
--- a/src/tools/miri/tests/fail/abort-terminator.rs
+++ b/src/tools/miri/tests/fail/abort-terminator.rs
@@ -1,7 +1,7 @@
 #![feature(c_unwind)]
 
 extern "C" fn panic_abort() {
-    //~^ ERROR: the program aborted
+    //~^ ERROR: panic in a function that cannot unwind
     panic!()
 }
 
diff --git a/src/tools/miri/tests/fail/abort-terminator.stderr b/src/tools/miri/tests/fail/abort-terminator.stderr
index 2d3275f6b190..966435ef92d5 100644
--- a/src/tools/miri/tests/fail/abort-terminator.stderr
+++ b/src/tools/miri/tests/fail/abort-terminator.stderr
@@ -1,13 +1,13 @@
 thread 'main' panicked at 'explicit panic', $DIR/abort-terminator.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: the program aborted execution
+error: abnormal termination: panic in a function that cannot unwind
   --> $DIR/abort-terminator.rs:LL:CC
    |
 LL | / extern "C" fn panic_abort() {
 LL | |
 LL | |     panic!()
 LL | | }
-   | |_^ the program aborted execution
+   | |_^ panic in a function that cannot unwind
    |
    = note: inside `panic_abort` at $DIR/abort-terminator.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
index 484f703f9c1b..e1631471ae2b 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
@@ -1,6 +1,6 @@
 thread 'main' panicked at 'explicit panic', $DIR/exported_symbol_bad_unwind2.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: the program aborted execution
+error: abnormal termination: panic in a function that cannot unwind
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL | / extern "C-unwind" fn nounwind() {
@@ -8,7 +8,7 @@ LL | |
 LL | |
 LL | |     panic!();
 LL | | }
-   | |_^ the program aborted execution
+   | |_^ panic in a function that cannot unwind
    |
    = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
index 484f703f9c1b..e1631471ae2b 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
@@ -1,6 +1,6 @@
 thread 'main' panicked at 'explicit panic', $DIR/exported_symbol_bad_unwind2.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: the program aborted execution
+error: abnormal termination: panic in a function that cannot unwind
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL | / extern "C-unwind" fn nounwind() {
@@ -8,7 +8,7 @@ LL | |
 LL | |
 LL | |     panic!();
 LL | | }
-   | |_^ the program aborted execution
+   | |_^ panic in a function that cannot unwind
    |
    = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
index 554cbe09cf03..65ba3433c28c 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
@@ -4,8 +4,8 @@
 #[cfg_attr(any(definition, both), rustc_nounwind)]
 #[no_mangle]
 extern "C-unwind" fn nounwind() {
-    //~[definition]^ ERROR: abnormal termination: the program aborted execution
-    //~[both]^^ ERROR: abnormal termination: the program aborted execution
+    //~[definition]^ ERROR: abnormal termination: panic in a function that cannot unwind
+    //~[both]^^ ERROR: abnormal termination: panic in a function that cannot unwind
     panic!();
 }
 
diff --git a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
index 2487ef5c2150..f6954ab35263 100644
--- a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
+++ b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
@@ -9,7 +9,7 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49
         _1 = const ();                   // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49
-        asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb2]; // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49
+        asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate]; // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49
     }
 
     bb1: {
@@ -17,8 +17,4 @@ fn main() -> () {
         _0 = const ();                   // scope 1 at $DIR/asm_unwind_panic_abort.rs:+1:5: +3:6
         return;                          // scope 0 at $DIR/asm_unwind_panic_abort.rs:+4:2: +4:2
     }
-
-    bb2 (cleanup): {
-        abort;                           // scope 0 at $DIR/asm_unwind_panic_abort.rs:+0:1: +4:2
-    }
 }
diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
index 61a934685cdb..d663c343515b 100644
--- a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
+++ b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
@@ -47,7 +47,7 @@
   
       bb2 (cleanup): {
           _5 = move _6;                    // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
-          drop(_6) -> bb6;                 // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
+          drop(_6) -> [return: bb6, unwind terminate]; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
       }
   
       bb3: {
@@ -70,16 +70,20 @@
       }
   
       bb6 (cleanup): {
-          drop(_5) -> bb7;                 // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
+          drop(_5) -> [return: bb7, unwind terminate]; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
       }
   
       bb7 (cleanup): {
--         drop(_4) -> bb8;                 // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
+-         drop(_4) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
 +         goto -> bb8;                     // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
       }
   
       bb8 (cleanup): {
           resume;                          // scope 0 at $DIR/basic_assignment.rs:+0:1: +14:2
++     }
++ 
++     bb9 (cleanup): {
++         unreachable;                     // scope 0 at $DIR/basic_assignment.rs:+0:1: +14:2
       }
   }
   
diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
index 6d1c7bd18dce..d63497e3a98d 100644
--- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
@@ -51,7 +51,7 @@ fn main() -> () {
 
     bb2 (cleanup): {
         _5 = move _6;                    // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
-        drop(_6) -> bb6;                 // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
+        drop(_6) -> [return: bb6, unwind terminate]; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
     }
 
     bb3: {
@@ -73,11 +73,11 @@ fn main() -> () {
     }
 
     bb6 (cleanup): {
-        drop(_5) -> bb7;                 // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
+        drop(_5) -> [return: bb7, unwind terminate]; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
     }
 
     bb7 (cleanup): {
-        drop(_4) -> bb8;                 // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
+        drop(_4) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
     }
 
     bb8 (cleanup): {
diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir
index 1bbf8f37f292..bac5b21dfad1 100644
--- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir
+++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir
@@ -63,15 +63,15 @@ fn main() -> () {
     }
 
     bb6 (cleanup): {
-        drop(_7) -> bb7;                 // scope 1 at $DIR/box_expr.rs:+3:11: +3:12
+        drop(_7) -> [return: bb7, unwind terminate]; // scope 1 at $DIR/box_expr.rs:+3:11: +3:12
     }
 
     bb7 (cleanup): {
-        drop(_1) -> bb9;                 // scope 0 at $DIR/box_expr.rs:+4:1: +4:2
+        drop(_1) -> [return: bb9, unwind terminate]; // scope 0 at $DIR/box_expr.rs:+4:1: +4:2
     }
 
     bb8 (cleanup): {
-        drop(_5) -> bb9;                 // scope 0 at $DIR/box_expr.rs:+2:22: +2:23
+        drop(_5) -> [return: bb9, unwind terminate]; // scope 0 at $DIR/box_expr.rs:+2:22: +2:23
     }
 
     bb9 (cleanup): {
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
index fd6485de863c..7cce3415fa1b 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
@@ -98,14 +98,14 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
         StorageLive(_3);                 // scope 0 at $DIR/async_await.rs:+1:5: +1:14
         StorageLive(_4);                 // scope 0 at $DIR/async_await.rs:+1:8: +1:14
         StorageLive(_5);                 // scope 0 at $DIR/async_await.rs:+1:5: +1:8
-        _5 = a() -> bb2;                 // scope 0 at $DIR/async_await.rs:+1:5: +1:8
+        _5 = a() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+1:5: +1:8
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:15:5: 15:6
                                          // + literal: Const { ty: fn() -> impl Future {a}, val: Value() }
     }
 
     bb2: {
-        _4 =  as IntoFuture>::into_future(move _5) -> bb3; // scope 0 at $DIR/async_await.rs:+1:8: +1:14
+        _4 =  as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+1:8: +1:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:15:8: 15:14
                                          // + literal: Const { ty: fn(impl Future) ->  as IntoFuture>::IntoFuture { as IntoFuture>::into_future}, val: Value() }
@@ -126,7 +126,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
         StorageLive(_12);                // scope 2 at $DIR/async_await.rs:+1:8: +1:14
         _12 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#3).0: impl std::future::Future); // scope 2 at $DIR/async_await.rs:+1:8: +1:14
         _11 = &mut (*_12);               // scope 2 at $DIR/async_await.rs:+1:8: +1:14
-        _10 = Pin::<&mut impl Future>::new_unchecked(move _11) -> bb5; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        _10 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:15:8: 15:14
                                          // + literal: Const { ty: unsafe fn(&mut impl Future) -> Pin<&mut impl Future> {Pin::<&mut impl Future>::new_unchecked}, val: Value() }
@@ -145,7 +145,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
     bb6: {
         _13 = &mut (*_14);               // scope 2 at $DIR/async_await.rs:+1:5: +1:14
         StorageDead(_15);                // scope 2 at $DIR/async_await.rs:+1:13: +1:14
-        _9 =  as Future>::poll(move _10, move _13) -> bb7; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        _9 =  as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:15:8: 15:14
                                          // + literal: Const { ty: for<'a, 'b, 'c> fn(Pin<&'a mut impl Future>, &'b mut Context<'c>) -> Poll< as Future>::Output> { as Future>::poll}, val: Value() }
@@ -206,14 +206,14 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
         StorageDead(_3);                 // scope 0 at $DIR/async_await.rs:+1:14: +1:15
         StorageLive(_21);                // scope 0 at $DIR/async_await.rs:+2:8: +2:14
         StorageLive(_22);                // scope 0 at $DIR/async_await.rs:+2:5: +2:8
-        _22 = a() -> bb14;               // scope 0 at $DIR/async_await.rs:+2:5: +2:8
+        _22 = a() -> [return: bb14, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+2:5: +2:8
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:16:5: 16:6
                                          // + literal: Const { ty: fn() -> impl Future {a}, val: Value() }
     }
 
     bb14: {
-        _21 =  as IntoFuture>::into_future(move _22) -> bb15; // scope 0 at $DIR/async_await.rs:+2:8: +2:14
+        _21 =  as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+2:8: +2:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:16:8: 16:14
                                          // + literal: Const { ty: fn(impl Future) ->  as IntoFuture>::IntoFuture { as IntoFuture>::into_future}, val: Value() }
@@ -234,7 +234,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
         StorageLive(_28);                // scope 5 at $DIR/async_await.rs:+2:8: +2:14
         _28 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#4).0: impl std::future::Future); // scope 5 at $DIR/async_await.rs:+2:8: +2:14
         _27 = &mut (*_28);               // scope 5 at $DIR/async_await.rs:+2:8: +2:14
-        _26 = Pin::<&mut impl Future>::new_unchecked(move _27) -> bb17; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        _26 = Pin::<&mut impl Future>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:16:8: 16:14
                                          // + literal: Const { ty: unsafe fn(&mut impl Future) -> Pin<&mut impl Future> {Pin::<&mut impl Future>::new_unchecked}, val: Value() }
@@ -253,7 +253,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
     bb18: {
         _29 = &mut (*_30);               // scope 5 at $DIR/async_await.rs:+2:5: +2:14
         StorageDead(_31);                // scope 5 at $DIR/async_await.rs:+2:13: +2:14
-        _25 =  as Future>::poll(move _26, move _29) -> bb19; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        _25 =  as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:16:8: 16:14
                                          // + literal: Const { ty: for<'a, 'b, 'c> fn(Pin<&'a mut impl Future>, &'b mut Context<'c>) -> Poll< as Future>::Output> { as Future>::poll}, val: Value() }
diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
index 5231c2eab957..1112177fbbf4 100644
--- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
@@ -63,7 +63,7 @@ fn droppy() -> () {
     }
 
     bb4 (cleanup): {
-        drop(_2) -> bb5;                 // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
+        drop(_2) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
     }
 
     bb5 (cleanup): {
diff --git a/tests/mir-opt/building/issue_49232.main.built.after.mir b/tests/mir-opt/building/issue_49232.main.built.after.mir
index de5e4c0f6ed4..cc135f417215 100644
--- a/tests/mir-opt/building/issue_49232.main.built.after.mir
+++ b/tests/mir-opt/building/issue_49232.main.built.after.mir
@@ -17,7 +17,7 @@ fn main() -> () {
     }
 
     bb1: {
-        falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/issue_49232.rs:+1:5: +9:6
+        falseUnwind -> [real: bb2, unwind: bb11]; // scope 0 at $DIR/issue_49232.rs:+1:5: +9:6
     }
 
     bb2: {
diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir
index ed72726c5ae0..54f0ea2d8942 100644
--- a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir
+++ b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir
@@ -95,15 +95,15 @@ fn move_out_by_subslice() -> () {
     }
 
     bb9 (cleanup): {
-        drop(_1) -> bb12;                // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2
+        drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2
     }
 
     bb10 (cleanup): {
-        drop(_7) -> bb11;                // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
+        drop(_7) -> [return: bb11, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
     }
 
     bb11 (cleanup): {
-        drop(_2) -> bb12;                // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
+        drop(_2) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
     }
 
     bb12 (cleanup): {
diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir
index eca874130f69..5090a4ba6751 100644
--- a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir
+++ b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir
@@ -95,15 +95,15 @@ fn move_out_from_end() -> () {
     }
 
     bb9 (cleanup): {
-        drop(_1) -> bb12;                // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2
+        drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2
     }
 
     bb10 (cleanup): {
-        drop(_7) -> bb11;                // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
+        drop(_7) -> [return: bb11, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
     }
 
     bb11 (cleanup): {
-        drop(_2) -> bb12;                // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
+        drop(_2) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
     }
 
     bb12 (cleanup): {
diff --git a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
index 20b0fb9643ee..b715a544ffea 100644
--- a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
+++ b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
@@ -72,7 +72,7 @@
       }
   
       bb4 (cleanup): {
-          drop(_2) -> bb5;                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
+          drop(_2) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
       }
   
       bb5 (cleanup): {
diff --git a/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff b/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff
index c44a14075ef6..168e8c610316 100644
--- a/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff
+++ b/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff
@@ -128,7 +128,7 @@
           StorageDead(_22);                // scope 10 at $DIR/combine_transmutes.rs:+11:47: +11:48
           StorageLive(_23);                // scope 11 at $DIR/combine_transmutes.rs:+12:9: +12:11
           StorageLive(_24);                // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
-          _24 = MaybeUninit::::uninit() -> bb1; // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
+          _24 = MaybeUninit::::uninit() -> [return: bb1, unwind unreachable]; // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
                                            // mir::Constant
                                            // + span: $DIR/combine_transmutes.rs:46:46: 46:75
                                            // + user_ty: UserType(23)
diff --git a/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff b/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff
index c83c9f5acf48..ae1185c7f712 100644
--- a/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff
+++ b/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff
@@ -19,7 +19,7 @@
 +         _1 = const 1_i32;                // scope 0 at $DIR/combine_transmutes.rs:+2:14: +2:38
           StorageLive(_2);                 // scope 1 at $DIR/combine_transmutes.rs:+3:9: +3:11
           StorageLive(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+3:46: +3:56
-          _3 = Vec::::new() -> bb1;   // scope 1 at $DIR/combine_transmutes.rs:+3:46: +3:56
+          _3 = Vec::::new() -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/combine_transmutes.rs:+3:46: +3:56
                                            // mir::Constant
                                            // + span: $DIR/combine_transmutes.rs:15:46: 15:54
                                            // + user_ty: UserType(0)
@@ -31,7 +31,7 @@
 +         _2 = move _3;                    // scope 1 at $DIR/combine_transmutes.rs:+3:14: +3:57
           StorageDead(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+3:56: +3:57
           _0 = const ();                   // scope 0 at $DIR/combine_transmutes.rs:+0:37: +4:2
-          drop(_2) -> bb2;                 // scope 1 at $DIR/combine_transmutes.rs:+4:1: +4:2
+          drop(_2) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/combine_transmutes.rs:+4:1: +4:2
       }
   
       bb2: {
diff --git a/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir b/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
index 9597a0c835fd..97826ed19a25 100644
--- a/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
+++ b/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
@@ -25,19 +25,19 @@ fn foo(_1: Option) -> i32 {
         _7 = const false;                // scope 0 at $DIR/string.rs:+3:9: +3:10
         _6 = move _1;                    // scope 0 at $DIR/string.rs:+3:9: +3:10
         _0 = const 4321_i32;             // scope 1 at $DIR/string.rs:+3:14: +3:18
-        drop(_6) -> bb6;                 // scope 0 at $DIR/string.rs:+3:17: +3:18
+        drop(_6) -> [return: bb6, unwind unreachable]; // scope 0 at $DIR/string.rs:+3:17: +3:18
     }
 
     bb2: {
         _2 = &((_1 as Some).0: std::string::String); // scope 0 at $DIR/string.rs:+2:14: +2:17
-        _3 = ::deref(move _2) -> bb3; // scope 0 at $DIR/string.rs:+2:14: +2:17
+        _3 = ::deref(move _2) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17
                                          // mir::Constant
                                          // + span: $DIR/string.rs:9:14: 9:17
                                          // + literal: Const { ty: for<'a> fn(&'a String) -> &'a ::Target {::deref}, val: Value() }
     }
 
     bb3: {
-        _4 = ::eq(_3, const "a") -> bb4; // scope 0 at $DIR/string.rs:+2:14: +2:17
+        _4 = ::eq(_3, const "a") -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17
                                          // mir::Constant
                                          // + span: $DIR/string.rs:9:14: 9:17
                                          // + literal: Const { ty: for<'a, 'b> fn(&'a str, &'b str) -> bool {::eq}, val: Value() }
@@ -65,7 +65,7 @@ fn foo(_1: Option) -> i32 {
     }
 
     bb8: {
-        drop(_1) -> bb7;                 // scope 0 at $DIR/string.rs:+5:1: +5:2
+        drop(_1) -> [return: bb7, unwind unreachable]; // scope 0 at $DIR/string.rs:+5:1: +5:2
     }
 
     bb9: {
diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.diff
index ec9cbb25322c..426d4fb213cd 100644
--- a/tests/mir-opt/derefer_inline_test.main.Derefer.diff
+++ b/tests/mir-opt/derefer_inline_test.main.Derefer.diff
@@ -35,7 +35,7 @@
       }
   
       bb4 (cleanup): {
-          drop(_2) -> bb5;                 // scope 0 at $DIR/derefer_inline_test.rs:+1:17: +1:18
+          drop(_2) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/derefer_inline_test.rs:+1:17: +1:18
       }
   
       bb5 (cleanup): {
diff --git a/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff
index c1a42a47ed21..c0fc1fb1df37 100644
--- a/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff
+++ b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff
@@ -7,7 +7,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61
-          _1 = assert_mem_uninitialized_valid::<&T>() -> bb1; // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61
+          _1 = assert_mem_uninitialized_valid::<&T>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61
                                            // mir::Constant
                                            // + span: $DIR/dont_yeet_assert.rs:10:5: 10:59
                                            // + user_ty: UserType(0)
diff --git a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
index cfbe0aaf252d..32b472ebeeb5 100644
--- a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
+++ b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
@@ -110,7 +110,7 @@ yields ()
 
     bb13 (cleanup): {
         StorageDead(_3);                 // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
-        drop(_1) -> bb14;                // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
+        drop(_1) -> [return: bb14, unwind terminate]; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
     }
 
     bb14 (cleanup): {
@@ -119,6 +119,6 @@ yields ()
 
     bb15 (cleanup): {
         StorageDead(_3);                 // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
-        drop(_1) -> bb14;                // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
+        drop(_1) -> [return: bb14, unwind terminate]; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
     }
 }
diff --git a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
index 7efda05d2b88..dc9bb533f132 100644
--- a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
@@ -63,7 +63,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24
         StorageDead(_7);                 // scope 1 at $DIR/generator_tiny.rs:+3:17: +3:18
         StorageDead(_6);                 // scope 1 at $DIR/generator_tiny.rs:+3:18: +3:19
         StorageLive(_8);                 // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21
-        _8 = callee() -> bb4;            // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21
+        _8 = callee() -> [return: bb4, unwind unreachable]; // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21
                                          // mir::Constant
                                          // + span: $DIR/generator_tiny.rs:23:13: 23:19
                                          // + literal: Const { ty: fn() {callee}, val: Value() }
diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.diff
index ed290063a930..ba1bfec05d21 100644
--- a/tests/mir-opt/inline/asm_unwind.main.Inline.diff
+++ b/tests/mir-opt/inline/asm_unwind.main.Inline.diff
@@ -35,7 +35,7 @@
 +     }
 + 
 +     bb3 (cleanup): {
-+         drop(_2) -> bb4;                 // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2
++         drop(_2) -> [return: bb4, unwind terminate]; // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2
 +     }
 + 
 +     bb4 (cleanup): {
diff --git a/tests/mir-opt/inline/cycle.f.Inline.diff b/tests/mir-opt/inline/cycle.f.Inline.diff
index 501390c3bf10..8da597577431 100644
--- a/tests/mir-opt/inline/cycle.f.Inline.diff
+++ b/tests/mir-opt/inline/cycle.f.Inline.diff
@@ -33,7 +33,7 @@
       }
   
       bb3 (cleanup): {
-          drop(_1) -> bb4;                 // scope 0 at $DIR/cycle.rs:+2:1: +2:2
+          drop(_1) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/cycle.rs:+2:1: +2:2
       }
   
       bb4 (cleanup): {
diff --git a/tests/mir-opt/inline/cycle.g.Inline.diff b/tests/mir-opt/inline/cycle.g.Inline.diff
index 20d313aecf58..1e6e30f9e9be 100644
--- a/tests/mir-opt/inline/cycle.g.Inline.diff
+++ b/tests/mir-opt/inline/cycle.g.Inline.diff
@@ -42,7 +42,7 @@
 +     }
 + 
 +     bb2 (cleanup): {
-+         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
++         drop(_2) -> [return: bb3, unwind terminate]; // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
 +     bb3 (cleanup): {
diff --git a/tests/mir-opt/inline/cycle.main.Inline.diff b/tests/mir-opt/inline/cycle.main.Inline.diff
index dacc5f4be9d7..315634945e43 100644
--- a/tests/mir-opt/inline/cycle.main.Inline.diff
+++ b/tests/mir-opt/inline/cycle.main.Inline.diff
@@ -42,7 +42,7 @@
 +     }
 + 
 +     bb2 (cleanup): {
-+         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
++         drop(_2) -> [return: bb3, unwind terminate]; // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
 +     bb3 (cleanup): {
diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.diff
index 31208e0052c6..d501b6ca8d2c 100644
--- a/tests/mir-opt/inline/inline_diverging.h.Inline.diff
+++ b/tests/mir-opt/inline/inline_diverging.h.Inline.diff
@@ -58,11 +58,11 @@
 +     }
 + 
 +     bb3 (cleanup): {
-+         drop(_3) -> bb4;                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++         drop(_3) -> [return: bb4, unwind terminate]; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
 +     }
 + 
 +     bb4 (cleanup): {
-+         drop(_2) -> bb5;                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++         drop(_2) -> [return: bb5, unwind terminate]; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
 +     }
 + 
 +     bb5 (cleanup): {
diff --git a/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff
index f1988ea4bd67..a1d2423ae270 100644
--- a/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff
+++ b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff
@@ -16,7 +16,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
-          _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
+          _1 = instruction_set_a32() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
                                            // mir::Constant
                                            // + span: $DIR/inline_instruction_set.rs:57:5: 57:24
                                            // + literal: Const { ty: fn() {instruction_set_a32}, val: Value() }
@@ -25,7 +25,7 @@
       bb1: {
           StorageDead(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27
           StorageLive(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
-          _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
+          _2 = instruction_set_t32() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
                                            // mir::Constant
                                            // + span: $DIR/inline_instruction_set.rs:58:5: 58:24
                                            // + literal: Const { ty: fn() {instruction_set_t32}, val: Value() }
@@ -34,7 +34,7 @@
       bb2: {
           StorageDead(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27
           StorageLive(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
--         _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
+-         _3 = instruction_set_default() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline_instruction_set.rs:59:5: 59:28
 -                                          // + literal: Const { ty: fn() {instruction_set_default}, val: Value() }
@@ -43,11 +43,11 @@
 -     bb3: {
           StorageDead(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
           StorageLive(_4);                 // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
--         _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
+-         _4 = inline_always_and_using_inline_asm() -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline_instruction_set.rs:60:5: 60:39
 -                                          // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value() }
-+         asm!("/* do nothing */", options((empty))) -> bb3; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38
++         asm!("/* do nothing */", options((empty))) -> [return: bb3, unwind unreachable]; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38
       }
   
 -     bb4: {
diff --git a/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff b/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff
index e777b2cc29eb..36aec4f47b08 100644
--- a/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff
+++ b/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff
@@ -14,7 +14,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
-          _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
+          _1 = instruction_set_a32() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
                                            // mir::Constant
                                            // + span: $DIR/inline_instruction_set.rs:49:5: 49:24
                                            // + literal: Const { ty: fn() {instruction_set_a32}, val: Value() }
@@ -23,7 +23,7 @@
       bb1: {
           StorageDead(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27
           StorageLive(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
--         _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
+-         _2 = instruction_set_t32() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline_instruction_set.rs:50:5: 50:24
 -                                          // + literal: Const { ty: fn() {instruction_set_t32}, val: Value() }
@@ -32,7 +32,7 @@
 -     bb2: {
           StorageDead(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27
           StorageLive(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
--         _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
+-         _3 = instruction_set_default() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline_instruction_set.rs:51:5: 51:28
 -                                          // + literal: Const { ty: fn() {instruction_set_default}, val: Value() }
@@ -41,8 +41,8 @@
 -     bb3: {
           StorageDead(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
           StorageLive(_4);                 // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
--         _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
-+         _4 = inline_always_and_using_inline_asm() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
+-         _4 = inline_always_and_using_inline_asm() -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
++         _4 = inline_always_and_using_inline_asm() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
                                            // mir::Constant
                                            // + span: $DIR/inline_instruction_set.rs:52:5: 52:39
                                            // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value() }
diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
index a4f0ad465e21..a5129e0e8c8e 100644
--- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
@@ -75,7 +75,7 @@
   
       bb4 (cleanup): {
 -         resume;                          // scope 0 at $DIR/inline_into_box_place.rs:+0:1: +2:2
-+         drop(_2) -> bb2;                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         drop(_2) -> [return: bb2, unwind terminate]; // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
       }
   }
   
diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.diff
index aa62e4a165e1..dc3fe75559e9 100644
--- a/tests/mir-opt/inline/issue_78442.bar.Inline.diff
+++ b/tests/mir-opt/inline/issue_78442.bar.Inline.diff
@@ -46,11 +46,11 @@
 -     bb3: {
 -         return;                          // scope 0 at $DIR/issue_78442.rs:+5:2: +5:2
 +     bb3 (cleanup): {
-+         drop(_1) -> bb4;                 // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
++         drop(_1) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
       }
   
       bb4 (cleanup): {
--         drop(_1) -> bb5;                 // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
+-         drop(_1) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
 +         resume;                          // scope 0 at $DIR/issue_78442.rs:+0:1: +5:2
       }
   
diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff
index 21055c6bfb57..8f56ef2585ce 100644
--- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff
+++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff
@@ -47,7 +47,7 @@
       }
   
       bb4 (cleanup): {
-          drop(_1) -> bb5;                 // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
+          drop(_1) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
       }
   
       bb5 (cleanup): {
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
index 5fd918b3aa53..537be1c2ae47 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
@@ -106,7 +106,7 @@
 +         _5 = move ((_6 as Some).0: u16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
 +         StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         _0 = unchecked_shl::(_3, move _5) -> bb3; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         _0 = unchecked_shl::(_3, move _5) -> [return: bb3, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +                                          // mir::Constant
 +                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::}, val: Value() }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
index c5501cef743e..517440af9f2e 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
@@ -94,7 +94,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
         _3 = move ((_4 as Some).0: u16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
         StorageDead(_8);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        _0 = unchecked_shl::(_1, move _3) -> bb3; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _0 = unchecked_shl::(_1, move _3) -> [return: bb3, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::}, val: Value() }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
index 68d3b21fc2a4..021ff67f5219 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
@@ -106,7 +106,7 @@
 +         _5 = move ((_6 as Some).0: i16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
 +         StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         _0 = unchecked_shr::(_3, move _5) -> bb3; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         _0 = unchecked_shr::(_3, move _5) -> [return: bb3, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +                                          // mir::Constant
 +                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::}, val: Value() }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
index ed3a89ceace1..0d56e9a68eb4 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
@@ -94,7 +94,7 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
         _3 = move ((_4 as Some).0: i16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
         StorageDead(_8);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        _0 = unchecked_shr::(_1, move _3) -> bb3; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _0 = unchecked_shr::(_1, move _3) -> [return: bb3, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::}, val: Value() }
diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
index 2f6f5f87efcc..49006e012dde 100644
--- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
@@ -14,7 +14,7 @@
   
       bb1: {
 +         Coverage::Expression(4294967295) = 1 + 2 for /the/src/instrument_coverage.rs:12:5 - 13:17; // scope 0 at /the/src/instrument_coverage.rs:+1:5: +5:6
-          falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:+1:5: +5:6
+          falseUnwind -> [real: bb2, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:+1:5: +5:6
       }
   
       bb2: {
diff --git a/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff
index 7031c3f3e699..09fc145e734d 100644
--- a/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff
+++ b/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff
@@ -9,7 +9,7 @@
   
       bb0: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46
-          _1 = assert_inhabited::() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46
+          _1 = assert_inhabited::() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:25:5: 25:44
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::}, val: Value() }
@@ -18,7 +18,7 @@
       bb1: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:46: +1:47
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47
-          _2 = assert_zero_valid::() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47
+          _2 = assert_zero_valid::() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:26:5: 26:45
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_zero_valid::}, val: Value() }
@@ -27,7 +27,7 @@
       bb2: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:47: +2:48
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60
-          _3 = assert_mem_uninitialized_valid::() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60
+          _3 = assert_mem_uninitialized_valid::() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:27:5: 27:58
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::}, val: Value() }
diff --git a/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff
index 4caa9971fef8..c52174ef5ea2 100644
--- a/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff
+++ b/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff
@@ -9,8 +9,8 @@
   
       bb0: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
--         _1 = assert_inhabited::() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
-+         _1 = assert_inhabited::(); // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
+-         _1 = assert_inhabited::() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
++         _1 = assert_inhabited::() -> unwind unreachable; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:17:5: 17:48
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::}, val: Value() }
@@ -19,8 +19,8 @@
       bb1: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:50: +1:51
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
--         _2 = assert_zero_valid::<&u8>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
-+         _2 = assert_zero_valid::<&u8>(); // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
+-         _2 = assert_zero_valid::<&u8>() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
++         _2 = assert_zero_valid::<&u8>() -> unwind unreachable; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:18:5: 18:47
                                            // + user_ty: UserType(0)
@@ -30,8 +30,8 @@
       bb2: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:49: +2:50
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
--         _3 = assert_mem_uninitialized_valid::<&u8>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
-+         _3 = assert_mem_uninitialized_valid::<&u8>(); // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
+-         _3 = assert_mem_uninitialized_valid::<&u8>() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
++         _3 = assert_mem_uninitialized_valid::<&u8>() -> unwind unreachable; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:19:5: 19:60
                                            // + user_ty: UserType(1)
diff --git a/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff
index b0bec9573697..d059d47ee586 100644
--- a/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff
+++ b/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff
@@ -9,7 +9,7 @@
   
       bb0: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
--         _1 = assert_inhabited::<()>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
+-         _1 = assert_inhabited::<()>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
 -                                          // mir::Constant
 -                                          // + span: $DIR/intrinsic_asserts.rs:7:5: 7:45
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<()>}, val: Value() }
@@ -19,7 +19,7 @@
       bb1: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:47: +1:48
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
--         _2 = assert_zero_valid::() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
+-         _2 = assert_zero_valid::() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/intrinsic_asserts.rs:8:5: 8:46
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_zero_valid::}, val: Value() }
@@ -29,7 +29,7 @@
       bb2: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:48: +2:49
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
--         _3 = assert_mem_uninitialized_valid::() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
+-         _3 = assert_mem_uninitialized_valid::() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
 -                                          // mir::Constant
 -                                          // + span: $DIR/intrinsic_asserts.rs:9:5: 9:59
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::}, val: Value() }
diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff
index b377a65b9641..b96c80b42161 100644
--- a/tests/mir-opt/issue_101973.inner.ConstProp.diff
+++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff
@@ -66,7 +66,7 @@
       bb2: {
           _6 = Shl(move _7, const 1_i32);  // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
           StorageDead(_7);                 // scope 0 at $DIR/issue_101973.rs:+1:56: +1:57
-          _3 = rotate_right::(_4, _6) -> bb3; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+          _3 = rotate_right::(_4, _6) -> [return: bb3, unwind unreachable]; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                            // + literal: Const { ty: extern "rust-intrinsic" fn(u32, u32) -> u32 {rotate_right::}, val: Value() }
diff --git a/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
index b0d5b291b6cb..ccaa508c13b5 100644
--- a/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
@@ -19,7 +19,7 @@ fn main() -> () {
     }
 
     bb1: {
-        falseUnwind -> [real: bb2, cleanup: bb5]; // scope 1 at $DIR/issue_38669.rs:+2:5: +7:6
+        falseUnwind -> [real: bb2, unwind: bb5]; // scope 1 at $DIR/issue_38669.rs:+2:5: +7:6
     }
 
     bb2: {
diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.diff
index 7ac75b51a370..ac2520249285 100644
--- a/tests/mir-opt/issue_41110.main.ElaborateDrops.diff
+++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.diff
@@ -46,17 +46,17 @@
       }
   
       bb3 (cleanup): {
--         drop(_3) -> bb5;                 // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+-         drop(_3) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
 +         goto -> bb5;                     // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
       }
   
       bb4 (cleanup): {
--         drop(_4) -> bb5;                 // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
+-         drop(_4) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
 +         goto -> bb5;                     // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
       }
   
       bb5 (cleanup): {
--         drop(_2) -> bb6;                 // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+-         drop(_2) -> [return: bb6, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
 +         goto -> bb8;                     // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
       }
   
@@ -65,7 +65,7 @@
 +     }
 + 
 +     bb7 (cleanup): {
-+         drop(_2) -> bb6;                 // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
++         drop(_2) -> [return: bb6, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
 +     }
 + 
 +     bb8 (cleanup): {
diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
index 3dd1a9bbab58..a4a07ad12434 100644
--- a/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
+++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
@@ -50,7 +50,7 @@
   
       bb3 (cleanup): {
           _2 = move _5;                    // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
-          drop(_5) -> bb8;                 // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
+          drop(_5) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
       }
   
       bb4: {
@@ -72,18 +72,18 @@
       }
   
       bb7 (cleanup): {
--         drop(_4) -> bb8;                 // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
+-         drop(_4) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
 +         goto -> bb8;                     // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
       }
   
       bb8 (cleanup): {
--         drop(_2) -> bb9;                 // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
+-         drop(_2) -> [return: bb9, unwind terminate]; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
 +         goto -> bb9;                     // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   
       bb9 (cleanup): {
--         drop(_1) -> bb10;                // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
-+         goto -> bb12;                    // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+-         drop(_1) -> [return: bb10, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++         goto -> bb13;                    // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   
       bb10 (cleanup): {
@@ -91,11 +91,15 @@
 +     }
 + 
 +     bb11 (cleanup): {
-+         drop(_1) -> bb10;                // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++         unreachable;                     // scope 0 at $DIR/issue_41110.rs:+0:1: +5:2
 +     }
 + 
 +     bb12 (cleanup): {
-+         switchInt(_6) -> [0: bb10, otherwise: bb11]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++         drop(_1) -> [return: bb10, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++     }
++ 
++     bb13 (cleanup): {
++         switchInt(_6) -> [0: bb10, otherwise: bb12]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   }
   
diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
index 4e38659a90be..d98f75e7502d 100644
--- a/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
+++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
@@ -58,7 +58,7 @@
   
       bb4 (cleanup): {
           _1 = move _3;                    // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-          drop(_3) -> bb11;                // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
+          drop(_3) -> [return: bb11, unwind terminate]; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
       }
   
       bb5: {
@@ -89,7 +89,7 @@
       bb9: {
           StorageDead(_2);                 // scope 1 at $DIR/issue_41888.rs:+8:5: +8:6
 -         drop(_1) -> bb10;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         goto -> bb18;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         goto -> bb19;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
       }
   
       bb10: {
@@ -101,7 +101,7 @@
       }
   
       bb11 (cleanup): {
--         drop(_1) -> bb12;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+-         drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +         goto -> bb12;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
       }
   
@@ -109,39 +109,43 @@
           resume;                          // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2
 +     }
 + 
-+     bb13: {
++     bb13 (cleanup): {
++         unreachable;                     // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2
++     }
++ 
++     bb14: {
 +         _7 = const false;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +         goto -> bb10;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb14 (cleanup): {
++     bb15 (cleanup): {
 +         goto -> bb12;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb15: {
-+         drop(_1) -> [return: bb13, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb16: {
++         drop(_1) -> [return: bb14, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb16 (cleanup): {
-+         drop(_1) -> bb12;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+     }
-+ 
-+     bb17: {
-+         _10 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         switchInt(move _10) -> [0: bb13, otherwise: bb15]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb17 (cleanup): {
++         drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
 +     bb18: {
-+         switchInt(_7) -> [0: bb13, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         _10 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         switchInt(move _10) -> [0: bb14, otherwise: bb16]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb19 (cleanup): {
-+         _11 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         switchInt(move _11) -> [0: bb14, otherwise: bb16]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb19: {
++         switchInt(_7) -> [0: bb14, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
 +     bb20 (cleanup): {
-+         switchInt(_7) -> [0: bb12, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         _11 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         switchInt(move _11) -> [0: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     }
++ 
++     bb21 (cleanup): {
++         switchInt(_7) -> [0: bb12, otherwise: bb20]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
       }
   }
   
diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir
index 22b34975d66a..8ed9101500e4 100644
--- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir
+++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir
@@ -109,11 +109,11 @@ fn test() -> Option> {
     }
 
     bb11 (cleanup): {
-        drop(_1) -> bb13;                // scope 0 at $DIR/issue_62289.rs:+4:5: +4:6
+        drop(_1) -> [return: bb13, unwind terminate]; // scope 0 at $DIR/issue_62289.rs:+4:5: +4:6
     }
 
     bb12 (cleanup): {
-        drop(_5) -> bb13;                // scope 0 at $DIR/issue_62289.rs:+3:23: +3:24
+        drop(_5) -> [return: bb13, unwind terminate]; // scope 0 at $DIR/issue_62289.rs:+3:23: +3:24
     }
 
     bb13 (cleanup): {
diff --git a/tests/mir-opt/issue_91633.bar.built.after.mir b/tests/mir-opt/issue_91633.bar.built.after.mir
index 760e5a8f90a8..88a383015b09 100644
--- a/tests/mir-opt/issue_91633.bar.built.after.mir
+++ b/tests/mir-opt/issue_91633.bar.built.after.mir
@@ -31,7 +31,7 @@ fn bar(_1: Box<[T]>) -> () {
     }
 
     bb3 (cleanup): {
-        drop(_1) -> bb4;                 // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3
+        drop(_1) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3
     }
 
     bb4 (cleanup): {
diff --git a/tests/mir-opt/issue_91633.foo.built.after.mir b/tests/mir-opt/issue_91633.foo.built.after.mir
index 4e3dd365e924..569135803ea3 100644
--- a/tests/mir-opt/issue_91633.foo.built.after.mir
+++ b/tests/mir-opt/issue_91633.foo.built.after.mir
@@ -48,7 +48,7 @@ fn foo(_1: Box<[T]>) -> T {
     }
 
     bb5 (cleanup): {
-        drop(_1) -> bb6;                 // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3
+        drop(_1) -> [return: bb6, unwind terminate]; // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3
     }
 
     bb6 (cleanup): {
diff --git a/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir b/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
index 4ee2dae49b3f..43d00b29e74e 100644
--- a/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
+++ b/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
@@ -35,7 +35,7 @@ fn main() -> () {
     }
 
     bb3: {
-        falseUnwind -> [real: bb4, cleanup: bb5]; // scope 0 at $DIR/loop_test.rs:+7:5: +10:6
+        falseUnwind -> [real: bb4, unwind: bb5]; // scope 0 at $DIR/loop_test.rs:+7:5: +10:6
     }
 
     bb4: {
diff --git a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
index 3389db733b99..dd742d87a295 100644
--- a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
@@ -5,7 +5,7 @@
       let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:25: +0:30
   
       bb0: {
--         _0 = std::intrinsics::min_align_of::() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
+-         _0 = std::intrinsics::min_align_of::() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:21:5: 21:40
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
index 5c5a9e90a9da..935eccfc6f4f 100644
--- a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
@@ -9,7 +9,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
--         _1 = std::intrinsics::assume(const true) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
+-         _1 = std::intrinsics::assume(const true) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:105:9: 105:32
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(bool) {std::intrinsics::assume}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
index 87960521bb45..1f03b7b0baf4 100644
--- a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
@@ -29,7 +29,7 @@
           StorageLive(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44
           _4 = &_1;                        // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44
           _3 = &(*_4);                     // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44
--         _2 = discriminant_value::(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
+-         _2 = discriminant_value::(move _3) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:82:5: 82:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a T) -> ::Discriminant {discriminant_value::}, val: Value() }
@@ -50,7 +50,7 @@
                                            // + literal: Const { ty: &i32, val: Unevaluated(discriminant, [T], Some(promoted[2])) }
           _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
           _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
--         _5 = discriminant_value::(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
+-         _5 = discriminant_value::(move _6) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:83:5: 83:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a i32) -> ::Discriminant {discriminant_value::}, val: Value() }
@@ -71,7 +71,7 @@
                                            // + literal: Const { ty: &(), val: Unevaluated(discriminant, [T], Some(promoted[1])) }
           _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
           _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
--         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
+-         _9 = discriminant_value::<()>(move _10) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:84:5: 84:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value() }
@@ -92,7 +92,7 @@
                                            // + literal: Const { ty: &E, val: Unevaluated(discriminant, [T], Some(promoted[0])) }
           _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
           _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
--         _13 = discriminant_value::(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
+-         _13 = discriminant_value::(move _14) -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:85:5: 85:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a E) -> ::Discriminant {discriminant_value::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
index 15cce7f4a2c0..b0c32e4b21a7 100644
--- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
@@ -47,7 +47,7 @@
           _9 = _10;                        // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79
           _8 = move _9 as *mut i32 (PtrToPtr); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91
           StorageDead(_9);                 // scope 3 at $DIR/lower_intrinsics.rs:+4:90: +4:91
--         _3 = copy_nonoverlapping::(move _4, move _8, const 0_usize) -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
+-         _3 = copy_nonoverlapping::(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable]; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:98:9: 98:28
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, *mut i32, usize) {copy_nonoverlapping::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
index 4cbbc02c9433..bfb000ccdb5c 100644
--- a/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
@@ -9,7 +9,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
           _2 = move _1;                    // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
--         _0 = std::intrinsics::forget::(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
+-         _0 = std::intrinsics::forget::(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:26:5: 26:29
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
index d8cd5f59a353..64d82907c7e3 100644
--- a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
@@ -17,7 +17,7 @@
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::}, val: Value() }
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14
           _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14
--         _0 = move _2() -> bb1;           // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16
+-         _0 = move _2() -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16
 +         _0 = SizeOf(T);                  // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16
 +         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16
       }
diff --git a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff
index c563703b250d..93863fca344a 100644
--- a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff
@@ -22,7 +22,7 @@
           StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:13: +2:15
           StorageLive(_4);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:55: +2:56
           _4 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+2:55: +2:56
--         _3 = option_payload_ptr::(move _4) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
+-         _3 = option_payload_ptr::(move _4) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:132:18: 132:54
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option) -> *const usize {option_payload_ptr::}, val: Value() }
@@ -35,7 +35,7 @@
           StorageLive(_5);                 // scope 2 at $DIR/lower_intrinsics.rs:+3:13: +3:15
           StorageLive(_6);                 // scope 2 at $DIR/lower_intrinsics.rs:+3:55: +3:56
           _6 = &raw const (*_2);           // scope 2 at $DIR/lower_intrinsics.rs:+3:55: +3:56
--         _5 = option_payload_ptr::(move _6) -> bb2; // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
+-         _5 = option_payload_ptr::(move _6) -> [return: bb2, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:133:18: 133:54
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option) -> *const String {option_payload_ptr::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
index f2f676843b2c..f816678b4b3a 100644
--- a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
           _2 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
--         _0 = read_via_copy::(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
+-         _0 = read_via_copy::(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:118:14: 118:45
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32) -> i32 {read_via_copy::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
index 3ad21283fa47..f34164189220 100644
--- a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
           _2 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
--         _0 = read_via_copy::(move _2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
+-         _0 = read_via_copy::(move _2) -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:123:14: 123:45
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Never) -> Never {read_via_copy::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff
index cf0ab73a5d4b..27e8accea8be 100644
--- a/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff
@@ -5,7 +5,7 @@
       let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:24: +0:29
   
       bb0: {
--         _0 = std::intrinsics::size_of::() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
+-         _0 = std::intrinsics::size_of::() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:16:5: 16:35
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff
index 814368ec021e..1b3b7685185b 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
           _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
--         _0 = transmute::(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
+-         _0 = transmute::(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:43:14: 43:33
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(std::cmp::Ordering) -> i8 {transmute::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff
index 5440c7a4c8ec..c6a7d2287e75 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
           _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
--         _0 = transmute::<&T, *const T>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
+-         _0 = transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:53:14: 53:33
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&T) -> *const T {transmute::<&T, *const T>}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
index 43ddccc1ef7d..8735a7500603 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
@@ -13,7 +13,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+-         _2 = transmute::>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:70:25: 70:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> Box {transmute::>}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
index bf529a9ca678..a772132770c3 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
@@ -13,7 +13,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+-         _2 = transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:64:25: 64:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &mut Never {transmute::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
index 4940a99021f4..c4d53d4e8c74 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
@@ -13,7 +13,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
+-         _2 = transmute::(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:58:21: 58:40
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &Never {transmute::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff
index f3a12b9ba5f2..f0b76127dd5e 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:47: +1:48
           _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+1:47: +1:48
--         _0 = transmute::<(), Never>(move _2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:49
+-         _0 = transmute::<(), Never>(move _2) -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:49
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:48:14: 48:46
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Never {transmute::<(), Never>}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
index 6f17d44516de..c0cc698c4818 100644
--- a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
@@ -12,7 +12,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:47
           StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
--         _3 = std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+-         _3 = std::intrinsics::unreachable() -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:31:14: 31:43
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
index 3b9a41249a4b..fb12d3dfa6e9 100644
--- a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
@@ -30,7 +30,7 @@
           _4 = _1;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:50: +1:51
           StorageLive(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54
           _5 = _2;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54
--         _3 = add_with_overflow::(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
+-         _3 = add_with_overflow::(move _4, move _5) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:111:14: 111:49
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {add_with_overflow::}, val: Value() }
@@ -46,7 +46,7 @@
           _7 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:50: +2:51
           StorageLive(_8);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54
           _8 = _2;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54
--         _6 = sub_with_overflow::(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
+-         _6 = sub_with_overflow::(move _7, move _8) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:112:14: 112:49
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {sub_with_overflow::}, val: Value() }
@@ -62,7 +62,7 @@
           _10 = _1;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:50: +3:51
           StorageLive(_11);                // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54
           _11 = _2;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54
--         _9 = mul_with_overflow::(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
+-         _9 = mul_with_overflow::(move _10, move _11) -> [return: bb3, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:113:14: 113:49
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {mul_with_overflow::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff
index 22ef75fd8046..0bfb34acac2d 100644
--- a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff
@@ -30,7 +30,7 @@
           _4 = _1;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:45: +1:46
           StorageLive(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:48: +1:49
           _5 = _2;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:48: +1:49
--         _3 = wrapping_add::(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
+-         _3 = wrapping_add::(move _4, move _5) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:9:14: 9:44
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_add::}, val: Value() }
@@ -46,7 +46,7 @@
           _7 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:45: +2:46
           StorageLive(_8);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:48: +2:49
           _8 = _2;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:48: +2:49
--         _6 = wrapping_sub::(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
+-         _6 = wrapping_sub::(move _7, move _8) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:10:14: 10:44
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_sub::}, val: Value() }
@@ -62,7 +62,7 @@
           _10 = _1;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:45: +3:46
           StorageLive(_11);                // scope 2 at $DIR/lower_intrinsics.rs:+3:48: +3:49
           _11 = _2;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:48: +3:49
--         _9 = wrapping_mul::(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
+-         _9 = wrapping_mul::(move _10, move _11) -> [return: bb3, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:11:14: 11:44
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_mul::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir b/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
index adfc6b2731c1..4f5df1331812 100644
--- a/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
+++ b/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
@@ -12,7 +12,7 @@ fn f_u64() -> () {
 
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
-        _2 = f_non_zst::(const 0_u64) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+        _2 = f_non_zst::(const 0_u64) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
                                          // mir::Constant
                                          // + span: $DIR/lower_intrinsics_e2e.rs:23:9: 23:18
                                          // + literal: Const { ty: fn(u64) {f_non_zst::}, val: Value() }
diff --git a/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir b/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir
index 302ca09aac4b..8654e80cd7c8 100644
--- a/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir
+++ b/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir
@@ -10,7 +10,7 @@ fn f_unit() -> () {
     }
 
     bb0: {
-        _1 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
+        _1 = f_zst::<()>(const ()) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
                                          // mir::Constant
                                          // + span: $DIR/lower_intrinsics_e2e.rs:21:9: 21:14
                                          // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value() }
diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 84e4d35f9081..3081e78f26db 100644
--- a/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -243,7 +243,7 @@
       }
   
 -     bb25 (cleanup): {
--         drop(_2) -> bb26;                // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2
+-         drop(_2) -> [return: bb26, unwind terminate]; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2
 +     bb22 (cleanup): {
 +         goto -> bb27;                    // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2
       }
diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
index 0cb34a2f2747..950f8758e31c 100644
--- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
+++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
@@ -40,7 +40,7 @@ fn main() -> () {
     }
 
     bb3 (cleanup): {
-        drop(_2) -> bb4;                 // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:34: +1:35
+        drop(_2) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:34: +1:35
     }
 
     bb4 (cleanup): {
diff --git a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
index 56cb9166c374..81b96e3b6315 100644
--- a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
@@ -33,7 +33,7 @@ fn main() -> () {
 
     bb1 (cleanup): {
         (_1.0: Aligned) = move _4;       // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
-        drop(_1) -> bb3;                 // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
+        drop(_1) -> [return: bb3, unwind terminate]; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
     }
 
     bb2: {
diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
index 2eb2a0980ce2..4eef028e1ccb 100644
--- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
@@ -186,11 +186,11 @@ fn main() -> () {
     }
 
     bb7 (cleanup): {
-        drop(_21) -> bb9;                // scope 7 at $DIR/retag.rs:+18:24: +18:25
+        drop(_21) -> [return: bb9, unwind terminate]; // scope 7 at $DIR/retag.rs:+18:24: +18:25
     }
 
     bb8 (cleanup): {
-        drop(_5) -> bb9;                 // scope 1 at $DIR/retag.rs:+3:36: +3:37
+        drop(_5) -> [return: bb9, unwind terminate]; // scope 1 at $DIR/retag.rs:+3:36: +3:37
     }
 
     bb9 (cleanup): {
diff --git a/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff b/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
index 1e66b1f703e3..c61107d25e00 100644
--- a/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
+++ b/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
@@ -12,8 +12,8 @@
       }
   
       bb1: {
--         falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6
-+         falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6
+-         falseUnwind -> [real: bb2, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6
++         falseUnwind -> [real: bb2, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6
       }
   
       bb2: {
diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
index 3884d29db417..11115c96e23e 100644
--- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
+++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
@@ -24,7 +24,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
     bb3 (cleanup): {
         _4 = &raw mut (*_1)[_3];         // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _3 = Add(move _3, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        drop((*_4)) -> bb4;              // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        drop((*_4)) -> [return: bb4, unwind terminate]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb4 (cleanup): {
diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
index f6f2344e82fa..579587a430b2 100644
--- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
@@ -58,7 +58,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/lifetimes.rs:+2:12: +2:31
           StorageLive(_3);                 // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
           StorageLive(_4);                 // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
-          _4 = Box::::new(const 5_u32) -> bb1; // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
+          _4 = Box::::new(const 5_u32) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
                                            // mir::Constant
                                            // + span: $DIR/lifetimes.rs:19:15: 19:23
                                            // + user_ty: UserType(1)
@@ -113,7 +113,7 @@
           StorageLive(_22);                // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
           _22 = &_8;                       // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
           _21 = &(*_22);                   // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
-          _20 = core::fmt::ArgumentV1::<'_>::new_display::>(move _21) -> bb3; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
+          _20 = core::fmt::ArgumentV1::<'_>::new_display::>(move _21) -> [return: bb3, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
                                            // mir::Constant
                                            // + span: $DIR/lifetimes.rs:27:20: 27:23
                                            // + user_ty: UserType(4)
@@ -127,7 +127,7 @@
           StorageLive(_25);                // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
           _25 = &_6;                       // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
           _24 = &(*_25);                   // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
-          _23 = core::fmt::ArgumentV1::<'_>::new_display::(move _24) -> bb4; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
+          _23 = core::fmt::ArgumentV1::<'_>::new_display::(move _24) -> [return: bb4, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
                                            // mir::Constant
                                            // + span: $DIR/lifetimes.rs:27:24: 27:27
                                            // + user_ty: UserType(5)
@@ -143,7 +143,7 @@
           _17 = &(*_18);                   // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _16 = move _17 as &[core::fmt::ArgumentV1<'_>] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           StorageDead(_17);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _11 = Arguments::<'_>::new_v1(move _12, move _16) -> bb5; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _11 = Arguments::<'_>::new_v1(move _12, move _16) -> [return: bb5, unwind unreachable]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + user_ty: UserType(3)
@@ -153,7 +153,7 @@
       bb5: {
           StorageDead(_16);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           StorageDead(_12);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _10 = _eprint(move _11) -> bb6;  // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _10 = _eprint(move _11) -> [return: bb6, unwind unreachable]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'a> fn(Arguments<'a>) {_eprint}, val: Value() }
@@ -170,7 +170,7 @@
           _9 = const ();                   // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           StorageDead(_9);                 // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _0 = const ();                   // scope 4 at $DIR/lifetimes.rs:+9:22: +11:6
-          drop(_8) -> bb8;                 // scope 3 at $DIR/lifetimes.rs:+11:5: +11:6
+          drop(_8) -> [return: bb8, unwind unreachable]; // scope 3 at $DIR/lifetimes.rs:+11:5: +11:6
       }
   
       bb7: {
@@ -204,11 +204,11 @@
       }
   
       bb12: {
-          drop(((_5 as Ok).0: std::boxed::Box)) -> bb10; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+          drop(((_5 as Ok).0: std::boxed::Box)) -> [return: bb10, unwind unreachable]; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
       }
   
       bb13: {
-          drop(_5) -> bb10;                // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+          drop(_5) -> [return: bb10, unwind unreachable]; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
       }
   }
   
diff --git a/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff
index b6439c00a005..d378c260a004 100644
--- a/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff
@@ -23,11 +23,11 @@
           StorageDead(_4);                 // scope 0 at $DIR/structs.rs:+1:29: +1:30
           StorageDead(_3);                 // scope 0 at $DIR/structs.rs:+1:29: +1:30
           _1 = move (_2.1: Tag);           // scope 0 at $DIR/structs.rs:+1:5: +1:32
-          drop(_1) -> bb1;                 // scope 0 at $DIR/structs.rs:+1:32: +1:33
+          drop(_1) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:32: +1:33
       }
   
       bb1: {
-          drop((_2.0: Tag)) -> bb3;        // scope 0 at $DIR/structs.rs:+1:32: +1:33
+          drop((_2.0: Tag)) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:32: +1:33
       }
   
       bb2: {
@@ -38,7 +38,7 @@
       }
   
       bb3: {
-          drop((_2.2: Tag)) -> bb2;        // scope 0 at $DIR/structs.rs:+1:32: +1:33
+          drop((_2.2: Tag)) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:32: +1:33
       }
   }
   
diff --git a/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff
index d45823d4bac5..3074fcbdf531 100644
--- a/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff
@@ -15,7 +15,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/structs.rs:+1:7: +1:41
           StorageLive(_4);                 // scope 0 at $DIR/structs.rs:+1:8: +1:39
           StorageLive(_5);                 // scope 0 at $DIR/structs.rs:+1:34: +1:37
-          _5 = g() -> bb1;                 // scope 0 at $DIR/structs.rs:+1:34: +1:37
+          _5 = g() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:34: +1:37
                                            // mir::Constant
                                            // + span: $DIR/structs.rs:78:34: 78:35
                                            // + literal: Const { ty: fn() -> u32 {g}, val: Value() }
@@ -26,7 +26,7 @@
           StorageDead(_5);                 // scope 0 at $DIR/structs.rs:+1:38: +1:39
           _3 = &(_4.0: u32);               // scope 0 at $DIR/structs.rs:+1:7: +1:41
           _2 = &raw const (*_3);           // scope 0 at $DIR/structs.rs:+1:7: +1:41
-          _1 = f(move _2) -> bb2;          // scope 0 at $DIR/structs.rs:+1:5: +1:42
+          _1 = f(move _2) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:5: +1:42
                                            // mir::Constant
                                            // + span: $DIR/structs.rs:78:5: 78:6
                                            // + literal: Const { ty: fn(*const u32) {f}, val: Value() }
diff --git a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
index ed9f3bdbdf4d..c27a93e91f89 100644
--- a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
+++ b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
@@ -22,7 +22,7 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () {
     }
 
     bb4 (cleanup): {
-        drop(((*_1).0: alloc::raw_vec::RawVec)) -> bb2; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb2, unwind terminate]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb5: {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
index 00f46f42a078..ca7741f21e80 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
+++ b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
@@ -32,7 +32,7 @@
    30|       |// Notes:
    31|       |//   1. Compare this program and its coverage results to those of the similar tests
    32|       |//      `panic_unwind.rs` and `try_error_result.rs`.
-   33|       |//   2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
+   33|       |//   2. This test confirms the coverage generated when a program includes  `UnwindAction::Terminate`.
    34|       |//   3. The test does not invoke the abort. By executing to a successful completion, the coverage
    35|       |//      results show where the program did and did not execute.
    36|       |//   4. If the program actually aborted, the coverage counters would not be saved (which "works as
diff --git a/tests/run-make/coverage/abort.rs b/tests/run-make/coverage/abort.rs
index 3dac43df8f30..98264bdc1afe 100644
--- a/tests/run-make/coverage/abort.rs
+++ b/tests/run-make/coverage/abort.rs
@@ -30,7 +30,7 @@ fn main() -> Result<(), u8> {
 // Notes:
 //   1. Compare this program and its coverage results to those of the similar tests
 //      `panic_unwind.rs` and `try_error_result.rs`.
-//   2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
+//   2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`.
 //   3. The test does not invoke the abort. By executing to a successful completion, the coverage
 //      results show where the program did and did not execute.
 //   4. If the program actually aborted, the coverage counters would not be saved (which "works as

From e06de16a8242ce55b84ad273de25c8d8696a9e4d Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Sat, 19 Nov 2022 23:03:22 +0000
Subject: [PATCH 176/267] Add miri tests for terminate terminator

---
 .../miri/tests/fail/terminate-terminator.rs   | 27 +++++++++++++++++++
 .../tests/fail/terminate-terminator.stderr    | 27 +++++++++++++++++++
 ...rminator.rs => unwind-action-terminate.rs} |  0
 ....stderr => unwind-action-terminate.stderr} |  8 +++---
 4 files changed, 58 insertions(+), 4 deletions(-)
 create mode 100644 src/tools/miri/tests/fail/terminate-terminator.rs
 create mode 100644 src/tools/miri/tests/fail/terminate-terminator.stderr
 rename src/tools/miri/tests/fail/{abort-terminator.rs => unwind-action-terminate.rs} (100%)
 rename src/tools/miri/tests/fail/{abort-terminator.stderr => unwind-action-terminate.stderr} (66%)

diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs
new file mode 100644
index 000000000000..f4931659fc82
--- /dev/null
+++ b/src/tools/miri/tests/fail/terminate-terminator.rs
@@ -0,0 +1,27 @@
+//@compile-flags: -Zmir-opt-level=3
+// Enable MIR inlining to ensure that `TerminatorKind::Terminate` is generated
+// instead of just `UnwindAction::Terminate`.
+
+#![feature(c_unwind)]
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+#[inline(always)]
+fn has_cleanup() {
+    //~^ ERROR: panic in a function that cannot unwind
+    // FIXME(nbdd0121): The error should be reported at the call site.
+    let _f = Foo;
+    panic!();
+}
+
+extern "C" fn panic_abort() {
+    has_cleanup();
+}
+
+fn main() {
+    panic_abort();
+}
diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr
new file mode 100644
index 000000000000..3befd83007bf
--- /dev/null
+++ b/src/tools/miri/tests/fail/terminate-terminator.stderr
@@ -0,0 +1,27 @@
+thread 'main' panicked at 'explicit panic', $DIR/terminate-terminator.rs:LL:CC
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+error: abnormal termination: panic in a function that cannot unwind
+  --> $DIR/terminate-terminator.rs:LL:CC
+   |
+LL | / fn has_cleanup() {
+LL | |
+LL | |     // FIXME(nbdd0121): The error should be reported at the call site.
+LL | |     let _f = Foo;
+LL | |     panic!();
+LL | | }
+   | |_^ panic in a function that cannot unwind
+...
+LL |       has_cleanup();
+   |       ------------- in this inlined function call
+   |
+   = note: inside `panic_abort` at $DIR/terminate-terminator.rs:LL:CC
+note: inside `main`
+  --> $DIR/terminate-terminator.rs:LL:CC
+   |
+LL |     panic_abort();
+   |     ^^^^^^^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/abort-terminator.rs b/src/tools/miri/tests/fail/unwind-action-terminate.rs
similarity index 100%
rename from src/tools/miri/tests/fail/abort-terminator.rs
rename to src/tools/miri/tests/fail/unwind-action-terminate.rs
diff --git a/src/tools/miri/tests/fail/abort-terminator.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
similarity index 66%
rename from src/tools/miri/tests/fail/abort-terminator.stderr
rename to src/tools/miri/tests/fail/unwind-action-terminate.stderr
index 966435ef92d5..52a1879cb5fe 100644
--- a/src/tools/miri/tests/fail/abort-terminator.stderr
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
@@ -1,7 +1,7 @@
-thread 'main' panicked at 'explicit panic', $DIR/abort-terminator.rs:LL:CC
+thread 'main' panicked at 'explicit panic', $DIR/unwind-action-terminate.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 error: abnormal termination: panic in a function that cannot unwind
-  --> $DIR/abort-terminator.rs:LL:CC
+  --> $DIR/unwind-action-terminate.rs:LL:CC
    |
 LL | / extern "C" fn panic_abort() {
 LL | |
@@ -9,9 +9,9 @@ LL | |     panic!()
 LL | | }
    | |_^ panic in a function that cannot unwind
    |
-   = note: inside `panic_abort` at $DIR/abort-terminator.rs:LL:CC
+   = note: inside `panic_abort` at $DIR/unwind-action-terminate.rs:LL:CC
 note: inside `main`
-  --> $DIR/abort-terminator.rs:LL:CC
+  --> $DIR/unwind-action-terminate.rs:LL:CC
    |
 LL |     panic_abort();
    |     ^^^^^^^^^^^^^

From 04126398c227d3ba9994bbb303e6c2a26d9198b2 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Wed, 5 Apr 2023 09:44:20 +0100
Subject: [PATCH 177/267] Ignore many tests on wasm32

---
 ...main.SimplifyCfg-elaborate-drops.after.mir |  2 +-
 tests/mir-opt/array_index_is_temporary.rs     |  1 +
 tests/mir-opt/combine_array_len.rs            |  1 +
 .../const_prop/aggregate.main.ConstProp.diff  |  2 +-
 .../aggregate.main.PreCodegen.after.mir       |  2 +-
 tests/mir-opt/const_prop/aggregate.rs         |  1 +
 tests/mir-opt/const_prop/array_index.rs       |  1 +
 .../mir-opt/const_prop/bad_op_div_by_zero.rs  |  1 +
 .../mir-opt/const_prop/bad_op_mod_by_zero.rs  |  1 +
 ...e_oob_for_slices.main.ConstProp.32bit.diff |  2 +-
 ...e_oob_for_slices.main.ConstProp.64bit.diff |  2 +-
 .../bad_op_unsafe_oob_for_slices.rs           |  1 +
 tests/mir-opt/const_prop/checked_add.rs       |  1 +
 ..._prop_fails_gracefully.main.ConstProp.diff |  4 +-
 .../const_prop/const_prop_fails_gracefully.rs |  1 +
 .../const_prop/control_flow_simplification.rs |  1 +
 tests/mir-opt/const_prop/indirect.rs          |  1 +
 .../inherit_overflow.main.ConstProp.diff      |  2 +-
 tests/mir-opt/const_prop/inherit_overflow.rs  |  1 +
 .../issue_66971.main.ConstProp.diff           |  2 +-
 tests/mir-opt/const_prop/issue_66971.rs       |  1 +
 .../issue_67019.main.ConstProp.diff           |  2 +-
 tests/mir-opt/const_prop/issue_67019.rs       |  1 +
 tests/mir-opt/const_prop/large_array_index.rs |  1 +
 ...aggregate_partial_read.main.ConstProp.diff |  2 +-
 ...mutable_variable_aggregate_partial_read.rs |  1 +
 ...variable_unprop_assign.main.ConstProp.diff |  2 +-
 .../mutable_variable_unprop_assign.rs         |  1 +
 .../const_prop/optimizes_into_variable.rs     |  1 +
 tests/mir-opt/const_prop/repeat.rs            |  1 +
 tests/mir-opt/const_prop/return_place.rs      |  1 +
 ...ar_literal_propagation.main.ConstProp.diff |  2 +-
 .../const_prop/scalar_literal_propagation.rs  |  1 +
 .../slice_len.main.ConstProp.32bit.diff       |  2 +-
 .../slice_len.main.ConstProp.64bit.diff       |  2 +-
 tests/mir-opt/const_prop/slice_len.rs         |  1 +
 .../const_prop/switch_int.main.ConstProp.diff |  4 +-
 ...mplifyConstCondition-after-const-prop.diff |  4 +-
 tests/mir-opt/const_prop/switch_int.rs        |  1 +
 ...le_literal_propagation.main.ConstProp.diff |  2 +-
 .../const_prop/tuple_literal_propagation.rs   |  1 +
 .../copy-prop/borrowed_local.f.CopyProp.diff  |  4 +-
 tests/mir-opt/copy-prop/borrowed_local.rs     |  1 +
 .../copy-prop/branch.foo.CopyProp.diff        |  6 +-
 tests/mir-opt/copy-prop/branch.rs             |  1 +
 .../copy_propagation_arg.bar.CopyProp.diff    |  2 +-
 .../copy_propagation_arg.foo.CopyProp.diff    |  2 +-
 .../mir-opt/copy-prop/copy_propagation_arg.rs |  1 +
 .../copy-prop/custom_move_arg.f.CopyProp.diff |  4 +-
 tests/mir-opt/copy-prop/custom_move_arg.rs    |  1 +
 .../copy-prop/cycle.main.CopyProp.diff        |  4 +-
 tests/mir-opt/copy-prop/cycle.rs              |  1 +
 .../dead_stores_79191.f.CopyProp.after.mir    |  2 +-
 tests/mir-opt/copy-prop/dead_stores_79191.rs  |  1 +
 .../dead_stores_better.f.CopyProp.after.mir   |  2 +-
 tests/mir-opt/copy-prop/dead_stores_better.rs |  1 +
 .../copy-prop/issue_107511.main.CopyProp.diff |  6 +-
 tests/mir-opt/copy-prop/issue_107511.rs       |  1 +
 .../copy-prop/move_arg.f.CopyProp.diff        |  2 +-
 tests/mir-opt/copy-prop/move_arg.rs           |  1 +
 .../copy-prop/move_projection.f.CopyProp.diff |  4 +-
 tests/mir-opt/copy-prop/move_projection.rs    |  1 +
 .../copy-prop/reborrow.demiraw.CopyProp.diff  |  2 +-
 .../copy-prop/reborrow.miraw.CopyProp.diff    |  2 +-
 .../copy-prop/reborrow.remut.CopyProp.diff    |  2 +-
 .../copy-prop/reborrow.reraw.CopyProp.diff    |  2 +-
 tests/mir-opt/copy-prop/reborrow.rs           |  1 +
 tests/mir-opt/dataflow-const-prop/checked.rs  |  1 +
 ...herit_overflow.main.DataflowConstProp.diff |  2 +-
 .../dataflow-const-prop/inherit_overflow.rs   |  1 +
 ...ref_without_sb.main.DataflowConstProp.diff |  4 +-
 .../dataflow-const-prop/ref_without_sb.rs     |  1 +
 .../sibling_ptr.main.DataflowConstProp.diff   |  2 +-
 .../dataflow-const-prop/sibling_ptr.rs        |  1 +
 .../terminator.main.DataflowConstProp.diff    |  2 +-
 .../mir-opt/dataflow-const-prop/terminator.rs |  1 +
 .../cycle.cycle.DeadStoreElimination.diff     |  2 +-
 tests/mir-opt/dead-store-elimination/cycle.rs |  1 +
 ..._line_doc_comment_2.DeduplicateBlocks.diff |  2 +-
 tests/mir-opt/deduplicate_blocks.rs           |  1 +
 .../branch.foo.DestinationPropagation.diff    |  6 +-
 tests/mir-opt/dest-prop/branch.rs             |  1 +
 ...gation_arg.bar.DestinationPropagation.diff |  2 +-
 ...gation_arg.foo.DestinationPropagation.diff |  2 +-
 .../mir-opt/dest-prop/copy_propagation_arg.rs |  1 +
 .../cycle.main.DestinationPropagation.diff    |  4 +-
 tests/mir-opt/dest-prop/cycle.rs              |  1 +
 ...s_79191.f.DestinationPropagation.after.mir |  2 +-
 tests/mir-opt/dest-prop/dead_stores_79191.rs  |  1 +
 ..._better.f.DestinationPropagation.after.mir |  2 +-
 tests/mir-opt/dest-prop/dead_stores_better.rs |  1 +
 tests/mir-opt/dest-prop/simple.rs             |  1 +
 .../union.main.DestinationPropagation.diff    |  4 +-
 tests/mir-opt/dest-prop/union.rs              |  1 +
 .../unreachable.f.DestinationPropagation.diff |  4 +-
 tests/mir-opt/dest-prop/unreachable.rs        |  1 +
 tests/mir-opt/div_overflow.rs                 |  1 +
 ...float_to_exponential_common.ConstProp.diff |  8 +--
 tests/mir-opt/funky_arms.rs                   |  1 +
 .../inline/dyn_trait.get_query.Inline.diff    | 24 ++++----
 .../inline/dyn_trait.mk_cycle.Inline.diff     |  2 +-
 tests/mir-opt/inline/dyn_trait.rs             |  1 +
 .../dyn_trait.try_execute_query.Inline.diff   | 10 ++--
 .../exponential_runtime.main.Inline.diff      | 60 +++++++++----------
 tests/mir-opt/inline/exponential_runtime.rs   |  1 +
 .../inline/inline_cycle.one.Inline.diff       | 12 ++--
 tests/mir-opt/inline/inline_cycle.rs          |  1 +
 .../inline/inline_cycle.two.Inline.diff       | 20 +++----
 .../inline_cycle_generic.main.Inline.diff     | 10 ++--
 tests/mir-opt/inline/inline_cycle_generic.rs  |  1 +
 .../inline_options.main.Inline.after.mir      | 22 +++----
 tests/mir-opt/inline/inline_options.rs        |  1 +
 .../inline_specialization.main.Inline.diff    |  6 +-
 tests/mir-opt/inline/inline_specialization.rs |  1 +
 tests/mir-opt/inline/inline_trait_method.rs   |  1 +
 .../inline_trait_method.test.Inline.after.mir |  2 +-
 tests/mir-opt/inline/inline_trait_method_2.rs |  1 +
 ...line_trait_method_2.test2.Inline.after.mir |  8 +--
 .../inline/issue_106141.outer.Inline.diff     | 38 ++++++------
 tests/mir-opt/inline/issue_106141.rs          |  1 +
 tests/mir-opt/inline/unchecked_shifts.rs      |  1 +
 ...unchecked_shl_unsigned_smaller.Inline.diff |  4 +-
 ..._shl_unsigned_smaller.PreCodegen.after.mir |  2 +-
 ...s.unchecked_shr_signed_smaller.Inline.diff |  4 +-
 ...ed_shr_signed_smaller.PreCodegen.after.mir |  2 +-
 .../mir-opt/issue_101973.inner.ConstProp.diff | 26 ++++----
 tests/mir-opt/issue_101973.rs                 |  1 +
 tests/mir-opt/issue_76432.rs                  |  1 +
 ...ue_59352.num_to_digit.PreCodegen.after.mir |  6 +-
 tests/mir-opt/issues/issue_59352.rs           |  1 +
 tests/mir-opt/lower_array_len.rs              |  1 +
 ...er_slice_len.bound.LowerSliceLenCalls.diff |  2 +-
 tests/mir-opt/lower_slice_len.rs              |  1 +
 tests/mir-opt/nrvo_simple.rs                  |  1 +
 ...age_markers.main.RemoveStorageMarkers.diff |  4 +-
 tests/mir-opt/remove_storage_markers.rs       |  1 +
 ...mplifyConstCondition-after-const-prop.diff |  2 +-
 tests/mir-opt/simplify_if.rs                  |  1 +
 tests/mir-opt/simplify_locals_fixedpoint.rs   |  1 +
 ...main.SimplifyLocals-before-const-prop.diff |  4 +-
 .../simplify_locals_removes_unused_consts.rs  |  1 +
 .../simplify_match.main.ConstProp.diff        |  2 +-
 tests/mir-opt/simplify_match.rs               |  1 +
 ...reachable.main.UnreachablePropagation.diff |  2 +-
 tests/mir-opt/unreachable.rs                  |  1 +
 ...diverging.main.UnreachablePropagation.diff |  4 +-
 tests/mir-opt/unreachable_diverging.rs        |  1 +
 tests/mir-opt/while_storage.rs                |  1 +
 ...le_storage.while_loop.PreCodegen.after.mir |  4 +-
 149 files changed, 284 insertions(+), 208 deletions(-)

diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir
index af5178d4079d..4be382fac8c3 100644
--- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir
@@ -38,7 +38,7 @@ fn main() -> () {
         _6 = _3;                         // scope 4 at $DIR/array_index_is_temporary.rs:+4:25: +4:26
         _5 = foo(move _6) -> bb1;        // scope 4 at $DIR/array_index_is_temporary.rs:+4:21: +4:27
                                          // mir::Constant
-                                         // + span: $DIR/array_index_is_temporary.rs:16:21: 16:24
+                                         // + span: $DIR/array_index_is_temporary.rs:17:21: 17:24
                                          // + literal: Const { ty: unsafe fn(*mut usize) -> u32 {foo}, val: Value() }
     }
 
diff --git a/tests/mir-opt/array_index_is_temporary.rs b/tests/mir-opt/array_index_is_temporary.rs
index e7bde81d4ca3..702b9c70e592 100644
--- a/tests/mir-opt/array_index_is_temporary.rs
+++ b/tests/mir-opt/array_index_is_temporary.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Retagging (from Stacked Borrows) relies on the array index being a fresh
 // temporary, so that side-effects cannot change it.
 // Test that this is indeed the case.
diff --git a/tests/mir-opt/combine_array_len.rs b/tests/mir-opt/combine_array_len.rs
index 3ef3bd09afde..08c5f1a1fc55 100644
--- a/tests/mir-opt/combine_array_len.rs
+++ b/tests/mir-opt/combine_array_len.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: InstCombine
 // EMIT_MIR combine_array_len.norm2.InstCombine.diff
 
diff --git a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff
index f6e58955b4f6..0411972661eb 100644
--- a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff
@@ -29,7 +29,7 @@
 +         _5 = const 1_u8;                 // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
           _4 = foo(move _5) -> bb1;        // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
                                            // mir::Constant
-                                           // + span: $DIR/aggregate.rs:8:5: 8:8
+                                           // + span: $DIR/aggregate.rs:9:5: 9:8
                                            // + literal: Const { ty: fn(u8) {foo}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir
index 4706af92cba9..05d4bf8b52e7 100644
--- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir
+++ b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir
@@ -25,7 +25,7 @@ fn main() -> () {
         _5 = const 1_u8;                 // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
         _4 = foo(move _5) -> bb1;        // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
                                          // mir::Constant
-                                         // + span: $DIR/aggregate.rs:8:5: 8:8
+                                         // + span: $DIR/aggregate.rs:9:5: 9:8
                                          // + literal: Const { ty: fn(u8) {foo}, val: Value() }
     }
 
diff --git a/tests/mir-opt/const_prop/aggregate.rs b/tests/mir-opt/const_prop/aggregate.rs
index aa123b7a8664..ed5a4ab594d5 100644
--- a/tests/mir-opt/const_prop/aggregate.rs
+++ b/tests/mir-opt/const_prop/aggregate.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -O
 
diff --git a/tests/mir-opt/const_prop/array_index.rs b/tests/mir-opt/const_prop/array_index.rs
index d31c2827b4e0..f36cf2213486 100644
--- a/tests/mir-opt/const_prop/array_index.rs
+++ b/tests/mir-opt/const_prop/array_index.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs
index a6fd325ece03..38f1a993dc03 100644
--- a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs
+++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs
index cc16a4a5aa74..a1078472cbf8 100644
--- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs
+++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR bad_op_mod_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
index 38d402b8f216..e711babf0357 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
@@ -25,7 +25,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _8 = const _;                    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
                                            // mir::Constant
-                                           // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
+                                           // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35
                                            // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _2 = &raw const (*_8);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
index 38d402b8f216..e711babf0357 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
@@ -25,7 +25,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _8 = const _;                    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
                                            // mir::Constant
-                                           // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
+                                           // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35
                                            // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _2 = &raw const (*_8);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
index cf22b06d5e57..3d252f2d221b 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR bad_op_unsafe_oob_for_slices.main.ConstProp.diff
 #[allow(unconditional_panic)]
diff --git a/tests/mir-opt/const_prop/checked_add.rs b/tests/mir-opt/const_prop/checked_add.rs
index b9860da4c822..007defd10379 100644
--- a/tests/mir-opt/const_prop/checked_add.rs
+++ b/tests/mir-opt/const_prop/checked_add.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
index bea7114c7df3..d75fae30b538 100644
--- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
@@ -18,7 +18,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
           _3 = const _;                    // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
                                            // mir::Constant
-                                           // + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16
+                                           // + span: $DIR/const_prop_fails_gracefully.rs:9:13: 9:16
                                            // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
           _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39
@@ -29,7 +29,7 @@
           _5 = _1;                         // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11
           _4 = read(move _5) -> bb1;       // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12
                                            // mir::Constant
-                                           // + span: $DIR/const_prop_fails_gracefully.rs:9:5: 9:9
+                                           // + span: $DIR/const_prop_fails_gracefully.rs:10:5: 10:9
                                            // + literal: Const { ty: fn(usize) {read}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs b/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs
index 0a3dcbd380fa..44d4878424dd 100644
--- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs
+++ b/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 #[inline(never)]
 fn read(_: usize) { }
diff --git a/tests/mir-opt/const_prop/control_flow_simplification.rs b/tests/mir-opt/const_prop/control_flow_simplification.rs
index 7dbe8e7344b1..b2ca045e89f9 100644
--- a/tests/mir-opt/const_prop/control_flow_simplification.rs
+++ b/tests/mir-opt/const_prop/control_flow_simplification.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Zmir-opt-level=1
 
diff --git a/tests/mir-opt/const_prop/indirect.rs b/tests/mir-opt/const_prop/indirect.rs
index 44916cbfe743..46fd8082d308 100644
--- a/tests/mir-opt/const_prop/indirect.rs
+++ b/tests/mir-opt/const_prop/indirect.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff
index d03c23a3fb56..0ac7fa43d5b4 100644
--- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff
@@ -8,7 +8,7 @@
       let mut _3: u8;                      // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
       scope 1 {
       }
-      scope 2 (inlined ::add) { // at $DIR/inherit_overflow.rs:8:13: 8:47
+      scope 2 (inlined ::add) { // at $DIR/inherit_overflow.rs:9:13: 9:47
           debug self => _2;                // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           debug other => _3;               // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           let mut _4: (u8, bool);          // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
diff --git a/tests/mir-opt/const_prop/inherit_overflow.rs b/tests/mir-opt/const_prop/inherit_overflow.rs
index 541a8c5c3af2..4e905d00d4d9 100644
--- a/tests/mir-opt/const_prop/inherit_overflow.rs
+++ b/tests/mir-opt/const_prop/inherit_overflow.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Zmir-enable-passes=+Inline
 
diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
index a4f9003e1401..2652694097c4 100644
--- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
@@ -11,7 +11,7 @@
           _2 = (const (), const 0_u8, const 0_u8); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
           _1 = encode(move _2) -> bb1;     // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
                                            // mir::Constant
-                                           // + span: $DIR/issue_66971.rs:17:5: 17:11
+                                           // + span: $DIR/issue_66971.rs:18:5: 18:11
                                            // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/issue_66971.rs b/tests/mir-opt/const_prop/issue_66971.rs
index 6ca03438ef39..af95c9ca2838 100644
--- a/tests/mir-opt/const_prop/issue_66971.rs
+++ b/tests/mir-opt/const_prop/issue_66971.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Z mir-opt-level=3
 
diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
index f456a3212049..54c9200d6721 100644
--- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
@@ -16,7 +16,7 @@
           StorageDead(_3);                 // scope 0 at $DIR/issue_67019.rs:+1:18: +1:19
           _1 = test(move _2) -> bb1;       // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20
                                            // mir::Constant
-                                           // + span: $DIR/issue_67019.rs:12:5: 12:9
+                                           // + span: $DIR/issue_67019.rs:13:5: 13:9
                                            // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/issue_67019.rs b/tests/mir-opt/const_prop/issue_67019.rs
index ffc6fa1f290f..08c7d4805d61 100644
--- a/tests/mir-opt/const_prop/issue_67019.rs
+++ b/tests/mir-opt/const_prop/issue_67019.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Z mir-opt-level=3
 
diff --git a/tests/mir-opt/const_prop/large_array_index.rs b/tests/mir-opt/const_prop/large_array_index.rs
index 48d134376db6..073f98495689 100644
--- a/tests/mir-opt/const_prop/large_array_index.rs
+++ b/tests/mir-opt/const_prop/large_array_index.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 // EMIT_MIR large_array_index.main.ConstProp.diff
diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
index 149aa6290d0e..75f6ebc58c75 100644
--- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
@@ -16,7 +16,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14
           _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:29: 6:32
+                                           // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:29: 7:32
                                            // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
index cb59509ff106..70a287cf381e 100644
--- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test
 // compile-flags: -O
 
diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
index 4010dd6c6d0d..9582504b25e8 100644
--- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
@@ -26,7 +26,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10
           _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_unprop_assign.rs:6:13: 6:16
+                                           // + span: $DIR/mutable_variable_unprop_assign.rs:7:13: 7:16
                                            // + literal: Const { ty: fn() -> i32 {foo}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs
index b077cfd3e0ae..fabd04e9bd27 100644
--- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test
 // compile-flags: -O
 
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.rs b/tests/mir-opt/const_prop/optimizes_into_variable.rs
index abea07e2025b..5ffa153476d9 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.rs
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test
 // compile-flags: -C overflow-checks=on
 
diff --git a/tests/mir-opt/const_prop/repeat.rs b/tests/mir-opt/const_prop/repeat.rs
index 36d9b9fc62d5..2f3b7d2c5021 100644
--- a/tests/mir-opt/const_prop/repeat.rs
+++ b/tests/mir-opt/const_prop/repeat.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -O
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
diff --git a/tests/mir-opt/const_prop/return_place.rs b/tests/mir-opt/const_prop/return_place.rs
index 06a853696791..ae119df8518e 100644
--- a/tests/mir-opt/const_prop/return_place.rs
+++ b/tests/mir-opt/const_prop/return_place.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -C overflow-checks=on
 
 // EMIT_MIR return_place.add.ConstProp.diff
diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
index 1151caaabbc1..a091b4ace20c 100644
--- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
@@ -15,7 +15,7 @@
 -         _2 = consume(_1) -> bb1;         // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
 +         _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
                                            // mir::Constant
-                                           // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12
+                                           // + span: $DIR/scalar_literal_propagation.rs:5:5: 5:12
                                            // + literal: Const { ty: fn(u32) {consume}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.rs b/tests/mir-opt/const_prop/scalar_literal_propagation.rs
index 8724e4d57115..e13e352f8a1d 100644
--- a/tests/mir-opt/const_prop/scalar_literal_propagation.rs
+++ b/tests/mir-opt/const_prop/scalar_literal_propagation.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR scalar_literal_propagation.main.ConstProp.diff
 fn main() {
     let x = 1;
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
index b99b83b0cba8..8bd2b48d6d6a 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
@@ -20,7 +20,7 @@
           StorageLive(_4);                 // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _9 = const _;                    // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
                                            // mir::Constant
-                                           // + span: $DIR/slice_len.rs:7:6: 7:19
+                                           // + span: $DIR/slice_len.rs:8:6: 8:19
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
index b99b83b0cba8..8bd2b48d6d6a 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
@@ -20,7 +20,7 @@
           StorageLive(_4);                 // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _9 = const _;                    // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
                                            // mir::Constant
-                                           // + span: $DIR/slice_len.rs:7:6: 7:19
+                                           // + span: $DIR/slice_len.rs:8:6: 8:19
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs
index 8183def0c63d..4499c54f264b 100644
--- a/tests/mir-opt/const_prop/slice_len.rs
+++ b/tests/mir-opt/const_prop/slice_len.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Zmir-enable-passes=+InstCombine
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
diff --git a/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff b/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff
index ddc1a4493dbb..85704c48a2c3 100644
--- a/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff
@@ -15,14 +15,14 @@
       bb1: {
           _0 = foo(const -1_i32) -> bb3;   // scope 0 at $DIR/switch_int.rs:+3:14: +3:21
                                            // mir::Constant
-                                           // + span: $DIR/switch_int.rs:9:14: 9:17
+                                           // + span: $DIR/switch_int.rs:10:14: 10:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value() }
       }
   
       bb2: {
           _0 = foo(const 0_i32) -> bb3;    // scope 0 at $DIR/switch_int.rs:+2:14: +2:20
                                            // mir::Constant
-                                           // + span: $DIR/switch_int.rs:8:14: 8:17
+                                           // + span: $DIR/switch_int.rs:9:14: 9:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff b/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
index 09c47ee6e830..0864db22523f 100644
--- a/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
+++ b/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
@@ -15,14 +15,14 @@
       bb1: {
           _0 = foo(const -1_i32) -> bb3;   // scope 0 at $DIR/switch_int.rs:+3:14: +3:21
                                            // mir::Constant
-                                           // + span: $DIR/switch_int.rs:9:14: 9:17
+                                           // + span: $DIR/switch_int.rs:10:14: 10:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value() }
       }
   
       bb2: {
           _0 = foo(const 0_i32) -> bb3;    // scope 0 at $DIR/switch_int.rs:+2:14: +2:20
                                            // mir::Constant
-                                           // + span: $DIR/switch_int.rs:8:14: 8:17
+                                           // + span: $DIR/switch_int.rs:9:14: 9:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/switch_int.rs b/tests/mir-opt/const_prop/switch_int.rs
index d7319eca18e2..2a2322e43a97 100644
--- a/tests/mir-opt/const_prop/switch_int.rs
+++ b/tests/mir-opt/const_prop/switch_int.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #[inline(never)]
 fn foo(_: i32) { }
 
diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
index d370abce45a4..12313b6c58d7 100644
--- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
@@ -15,7 +15,7 @@
 +         _1 = const (1_u32, 2_u32);       // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
           _2 = consume(_1) -> bb1;         // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
                                            // mir::Constant
-                                           // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12
+                                           // + span: $DIR/tuple_literal_propagation.rs:6:5: 6:12
                                            // + literal: Const { ty: fn((u32, u32)) {consume}, val: Value() }
       }
   
diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.rs b/tests/mir-opt/const_prop/tuple_literal_propagation.rs
index e644baec4a83..edd748d00ab3 100644
--- a/tests/mir-opt/const_prop/tuple_literal_propagation.rs
+++ b/tests/mir-opt/const_prop/tuple_literal_propagation.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR tuple_literal_propagation.main.ConstProp.diff
 fn main() {
     let x = (1, 2);
diff --git a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff
index b183865a9bcf..2a0bff57db9c 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff
@@ -15,7 +15,7 @@
           _4 = &_3;                        // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = cmp_ref(_2, _4) -> bb1;     // scope 0 at $DIR/borrowed_local.rs:+8:13: +8:45
                                            // mir::Constant
-                                           // + span: $DIR/borrowed_local.rs:23:29: 23:36
+                                           // + span: $DIR/borrowed_local.rs:24:29: 24:36
                                            // + literal: Const { ty: for<'a, 'b> fn(&'a u8, &'b u8) -> bool {cmp_ref}, val: Value() }
       }
   
@@ -23,7 +23,7 @@
 -         _0 = opaque::(_3) -> bb2;    // scope 0 at $DIR/borrowed_local.rs:+12:13: +12:38
 +         _0 = opaque::(_1) -> bb2;    // scope 0 at $DIR/borrowed_local.rs:+12:13: +12:38
                                            // mir::Constant
-                                           // + span: $DIR/borrowed_local.rs:27:28: 27:34
+                                           // + span: $DIR/borrowed_local.rs:28:28: 28:34
                                            // + literal: Const { ty: fn(u8) -> bool {opaque::}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs
index c4b980e2b351..9186da5af484 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.rs
+++ b/tests/mir-opt/copy-prop/borrowed_local.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 #![feature(custom_mir, core_intrinsics)]
diff --git a/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
index 8b116532d9f5..b78c19d78d04 100644
--- a/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
@@ -18,7 +18,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/branch.rs:+1:9: +1:10
           _1 = val() -> bb1;               // scope 0 at $DIR/branch.rs:+1:13: +1:18
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:13:13: 13:16
+                                           // + span: $DIR/branch.rs:14:13: 14:16
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value() }
       }
   
@@ -27,7 +27,7 @@
           StorageLive(_3);                 // scope 1 at $DIR/branch.rs:+3:16: +3:22
           _3 = cond() -> bb2;              // scope 1 at $DIR/branch.rs:+3:16: +3:22
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:15:16: 15:20
+                                           // + span: $DIR/branch.rs:16:16: 16:20
                                            // + literal: Const { ty: fn() -> bool {cond}, val: Value() }
       }
   
@@ -44,7 +44,7 @@
           StorageLive(_4);                 // scope 1 at $DIR/branch.rs:+6:9: +6:14
           _4 = val() -> bb5;               // scope 1 at $DIR/branch.rs:+6:9: +6:14
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:18:9: 18:12
+                                           // + span: $DIR/branch.rs:19:9: 19:12
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/branch.rs b/tests/mir-opt/copy-prop/branch.rs
index 50b1e00fad4f..0a2e16946345 100644
--- a/tests/mir-opt/copy-prop/branch.rs
+++ b/tests/mir-opt/copy-prop/branch.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that we bail out when there are multiple assignments to the same local.
 // unit-test: CopyProp
 fn val() -> i32 {
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
index ac4e9a2bfa73..24bca32207fa 100644
--- a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
@@ -13,7 +13,7 @@
           _3 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12
           _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13
                                            // mir::Constant
-                                           // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10
+                                           // + span: $DIR/copy_propagation_arg.rs:17:5: 17:10
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
index 0a3e985e7c26..87708f340054 100644
--- a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
@@ -13,7 +13,7 @@
           _3 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+2:15: +2:16
           _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17
                                            // mir::Constant
-                                           // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14
+                                           // + span: $DIR/copy_propagation_arg.rs:12:9: 12:14
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.rs b/tests/mir-opt/copy-prop/copy_propagation_arg.rs
index cc98985f1fda..1b65dcb01ed3 100644
--- a/tests/mir-opt/copy-prop/copy_propagation_arg.rs
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that CopyProp does not propagate an assignment to a function argument
 // (doing so can break usages of the original argument value)
 // unit-test: CopyProp
diff --git a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff
index 6ca73ffdde28..160f47bdd8f7 100644
--- a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff
@@ -11,7 +11,7 @@
 -         _0 = opaque::(move _1) -> bb1; // scope 0 at $DIR/custom_move_arg.rs:+3:9: +3:41
 +         _0 = opaque::(_1) -> bb1; // scope 0 at $DIR/custom_move_arg.rs:+3:9: +3:41
                                            // mir::Constant
-                                           // + span: $DIR/custom_move_arg.rs:15:24: 15:30
+                                           // + span: $DIR/custom_move_arg.rs:16:24: 16:30
                                            // + literal: Const { ty: fn(NotCopy) {opaque::}, val: Value() }
       }
   
@@ -20,7 +20,7 @@
 -         _0 = opaque::(_3) -> bb2; // scope 0 at $DIR/custom_move_arg.rs:+7:9: +7:35
 +         _0 = opaque::(_1) -> bb2; // scope 0 at $DIR/custom_move_arg.rs:+7:9: +7:35
                                            // mir::Constant
-                                           // + span: $DIR/custom_move_arg.rs:19:24: 19:30
+                                           // + span: $DIR/custom_move_arg.rs:20:24: 20:30
                                            // + literal: Const { ty: fn(NotCopy) {opaque::}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs
index 4a591146e619..29c368df82d8 100644
--- a/tests/mir-opt/copy-prop/custom_move_arg.rs
+++ b/tests/mir-opt/copy-prop/custom_move_arg.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 #![feature(custom_mir, core_intrinsics)]
diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
index 3e61869e82f1..23d92ed1ac5b 100644
--- a/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
@@ -24,7 +24,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/cycle.rs:+1:9: +1:14
           _1 = val() -> bb1;               // scope 0 at $DIR/cycle.rs:+1:17: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:9:17: 9:20
+                                           // + span: $DIR/cycle.rs:10:17: 10:20
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value() }
       }
   
@@ -43,7 +43,7 @@
           _6 = _1;                         // scope 3 at $DIR/cycle.rs:+6:10: +6:11
           _5 = std::mem::drop::(move _6) -> bb2; // scope 3 at $DIR/cycle.rs:+6:5: +6:12
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:14:5: 14:9
+                                           // + span: $DIR/cycle.rs:15:5: 15:9
                                            // + literal: Const { ty: fn(i32) {std::mem::drop::}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/cycle.rs b/tests/mir-opt/copy-prop/cycle.rs
index b74c397269de..da70f6bec2eb 100644
--- a/tests/mir-opt/copy-prop/cycle.rs
+++ b/tests/mir-opt/copy-prop/cycle.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that cyclic assignments don't hang CopyProp, and result in reasonable code.
 // unit-test: CopyProp
 fn val() -> i32 {
diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
index d48b04e2de27..c56418d8893f 100644
--- a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
+++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
@@ -18,7 +18,7 @@ fn f(_1: usize) -> usize {
         _4 = _1;                         // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9
         _0 = id::(move _4) -> bb1; // scope 1 at $DIR/dead_stores_79191.rs:+4:5: +4:10
                                          // mir::Constant
-                                         // + span: $DIR/dead_stores_79191.rs:12:5: 12:7
+                                         // + span: $DIR/dead_stores_79191.rs:13:5: 13:7
                                          // + literal: Const { ty: fn(usize) -> usize {id::}, val: Value() }
     }
 
diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.rs b/tests/mir-opt/copy-prop/dead_stores_79191.rs
index e3493b8b7a18..84453c55e3ef 100644
--- a/tests/mir-opt/copy-prop/dead_stores_79191.rs
+++ b/tests/mir-opt/copy-prop/dead_stores_79191.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 fn id(x: T) -> T {
diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
index 727791f50a4e..f355421732e4 100644
--- a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
+++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
@@ -18,7 +18,7 @@ fn f(_1: usize) -> usize {
         _4 = _1;                         // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9
         _0 = id::(move _4) -> bb1; // scope 1 at $DIR/dead_stores_better.rs:+4:5: +4:10
                                          // mir::Constant
-                                         // + span: $DIR/dead_stores_better.rs:16:5: 16:7
+                                         // + span: $DIR/dead_stores_better.rs:17:5: 17:7
                                          // + literal: Const { ty: fn(usize) -> usize {id::}, val: Value() }
     }
 
diff --git a/tests/mir-opt/copy-prop/dead_stores_better.rs b/tests/mir-opt/copy-prop/dead_stores_better.rs
index 8465b3c98536..87b916fd3ff8 100644
--- a/tests/mir-opt/copy-prop/dead_stores_better.rs
+++ b/tests/mir-opt/copy-prop/dead_stores_better.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates
 // that that pass enables this one to do more optimizations.
 
diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff
index 97d0a01e00bc..e09ccb831199 100644
--- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff
@@ -51,7 +51,7 @@
           StorageDead(_7);                 // scope 2 at $DIR/issue_107511.rs:+6:17: +6:18
           _5 = core::slice::::len(move _6) -> bb1; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
                                            // mir::Constant
-                                           // + span: $DIR/issue_107511.rs:10:19: 10:22
+                                           // + span: $DIR/issue_107511.rs:11:19: 11:22
                                            // + literal: Const { ty: for<'a> fn(&'a [i32]) -> usize {core::slice::::len}, val: Value() }
       }
   
@@ -61,7 +61,7 @@
           StorageDead(_5);                 // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
           _3 =  as IntoIterator>::into_iter(move _4) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
                                            // mir::Constant
-                                           // + span: $DIR/issue_107511.rs:10:14: 10:24
+                                           // + span: $DIR/issue_107511.rs:11:14: 11:24
                                            // + literal: Const { ty: fn(std::ops::Range) ->  as IntoIterator>::IntoIter { as IntoIterator>::into_iter}, val: Value() }
       }
   
@@ -81,7 +81,7 @@
           _12 = &mut (*_13);               // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
           _11 =  as Iterator>::next(move _12) -> bb4; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
                                            // mir::Constant
-                                           // + span: $DIR/issue_107511.rs:10:14: 10:24
+                                           // + span: $DIR/issue_107511.rs:11:14: 11:24
                                            // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/issue_107511.rs b/tests/mir-opt/copy-prop/issue_107511.rs
index d593f2872ea4..2b00ff15581f 100644
--- a/tests/mir-opt/copy-prop/issue_107511.rs
+++ b/tests/mir-opt/copy-prop/issue_107511.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 // EMIT_MIR issue_107511.main.CopyProp.diff
diff --git a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
index d76bf1cfe7e0..650bd66a7d73 100644
--- a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
@@ -24,7 +24,7 @@
 -         _3 = g::(move _4, move _5) -> bb1; // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
 +         _3 = g::(_1, _1) -> bb1;      // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
                                            // mir::Constant
-                                           // + span: $DIR/move_arg.rs:7:5: 7:6
+                                           // + span: $DIR/move_arg.rs:8:5: 8:6
                                            // + literal: Const { ty: fn(T, T) {g::}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/move_arg.rs b/tests/mir-opt/copy-prop/move_arg.rs
index 40ae1d8f4661..f88d9a9e74bb 100644
--- a/tests/mir-opt/copy-prop/move_arg.rs
+++ b/tests/mir-opt/copy-prop/move_arg.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Test that we do not move multiple times from the same local.
 // unit-test: CopyProp
 
diff --git a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff
index 02308beb88af..beb85d68a660 100644
--- a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff
@@ -13,14 +13,14 @@
 +         _3 = (_1.0: u8);                 // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
 +         _0 = opaque::(_1) -> bb1;   // scope 0 at $DIR/move_projection.rs:+6:13: +6:44
                                            // mir::Constant
-                                           // + span: $DIR/move_projection.rs:19:28: 19:34
+                                           // + span: $DIR/move_projection.rs:20:28: 20:34
                                            // + literal: Const { ty: fn(Foo) -> bool {opaque::}, val: Value() }
       }
   
       bb1: {
           _0 = opaque::(move _3) -> bb2; // scope 0 at $DIR/move_projection.rs:+9:13: +9:44
                                            // mir::Constant
-                                           // + span: $DIR/move_projection.rs:22:28: 22:34
+                                           // + span: $DIR/move_projection.rs:23:28: 23:34
                                            // + literal: Const { ty: fn(u8) -> bool {opaque::}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs
index 2a1bbae99a4c..c158c69e0cf8 100644
--- a/tests/mir-opt/copy-prop/move_projection.rs
+++ b/tests/mir-opt/copy-prop/move_projection.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 #![feature(custom_mir, core_intrinsics)]
diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff
index 6c32b675a5bc..b4a248245663 100644
--- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff
@@ -39,7 +39,7 @@
 -         _6 = opaque::<*mut u8>(move _7) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14
 +         _6 = opaque::<*mut u8>(_2) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14
                                            // mir::Constant
-                                           // + span: $DIR/reborrow.rs:38:5: 38:11
+                                           // + span: $DIR/reborrow.rs:39:5: 39:11
                                            // + literal: Const { ty: fn(*mut u8) {opaque::<*mut u8>}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff
index 2f1b522c2ec7..a6a6c05b24ae 100644
--- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff
@@ -35,7 +35,7 @@
 -         _5 = opaque::<*mut u8>(move _6) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14
 +         _5 = opaque::<*mut u8>(_2) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14
                                            // mir::Constant
-                                           // + span: $DIR/reborrow.rs:30:5: 30:11
+                                           // + span: $DIR/reborrow.rs:31:5: 31:11
                                            // + literal: Const { ty: fn(*mut u8) {opaque::<*mut u8>}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff
index 9b580c1f4e15..f3d26cc6e2bf 100644
--- a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff
@@ -33,7 +33,7 @@
 -         _5 = opaque::<&mut u8>(move _6) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14
 +         _5 = opaque::<&mut u8>(move _2) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14
                                            // mir::Constant
-                                           // + span: $DIR/reborrow.rs:14:5: 14:11
+                                           // + span: $DIR/reborrow.rs:15:5: 15:11
                                            // + literal: Const { ty: fn(&mut u8) {opaque::<&mut u8>}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff
index cff4a176098b..63e42b4dc771 100644
--- a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff
@@ -33,7 +33,7 @@
 -         _5 = opaque::<&mut u8>(move _6) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14
 +         _5 = opaque::<&mut u8>(move _2) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14
                                            // mir::Constant
-                                           // + span: $DIR/reborrow.rs:22:5: 22:11
+                                           // + span: $DIR/reborrow.rs:23:5: 23:11
                                            // + literal: Const { ty: fn(&mut u8) {opaque::<&mut u8>}, val: Value() }
       }
   
diff --git a/tests/mir-opt/copy-prop/reborrow.rs b/tests/mir-opt/copy-prop/reborrow.rs
index c2926b8fa518..91b77966ba84 100644
--- a/tests/mir-opt/copy-prop/reborrow.rs
+++ b/tests/mir-opt/copy-prop/reborrow.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that CopyProp considers reborrows as not mutating the pointer.
 // unit-test: CopyProp
 
diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs
index 0738a4ee53b8..0f9f5a97faca 100644
--- a/tests/mir-opt/dataflow-const-prop/checked.rs
+++ b/tests/mir-opt/dataflow-const-prop/checked.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DataflowConstProp
 // compile-flags: -Coverflow-checks=on
 
diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
index 29781e9ce188..1edcc28e68c1 100644
--- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
@@ -8,7 +8,7 @@
       let mut _3: u8;                      // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
       scope 1 {
       }
-      scope 2 (inlined ::add) { // at $DIR/inherit_overflow.rs:8:13: 8:47
+      scope 2 (inlined ::add) { // at $DIR/inherit_overflow.rs:9:13: 9:47
           debug self => _2;                // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           debug other => _3;               // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           let mut _4: (u8, bool);          // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs
index f4aba60f0c80..90349d5270cc 100644
--- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs
+++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DataflowConstProp
 // compile-flags: -Zmir-enable-passes=+Inline
 
diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff
index 158f187f1576..70ef17afd659 100644
--- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff
@@ -26,7 +26,7 @@
           _3 = &(*_4);                     // scope 1 at $DIR/ref_without_sb.rs:+2:12: +2:14
           _2 = escape::(move _3) -> bb1; // scope 1 at $DIR/ref_without_sb.rs:+2:5: +2:15
                                            // mir::Constant
-                                           // + span: $DIR/ref_without_sb.rs:12:5: 12:11
+                                           // + span: $DIR/ref_without_sb.rs:13:5: 13:11
                                            // + literal: Const { ty: for<'a> fn(&'a i32) {escape::}, val: Value() }
       }
   
@@ -38,7 +38,7 @@
           StorageLive(_5);                 // scope 1 at $DIR/ref_without_sb.rs:+4:5: +4:20
           _5 = some_function() -> bb2;     // scope 1 at $DIR/ref_without_sb.rs:+4:5: +4:20
                                            // mir::Constant
-                                           // + span: $DIR/ref_without_sb.rs:14:5: 14:18
+                                           // + span: $DIR/ref_without_sb.rs:15:5: 15:18
                                            // + literal: Const { ty: fn() {some_function}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs
index 2fd480b0968a..f53de3cf2d4c 100644
--- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs
+++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DataflowConstProp
 
 #[inline(never)]
diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
index 004643e36f13..6ca569f3d8e5 100644
--- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
@@ -32,7 +32,7 @@
           _5 = _3;                         // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
           _4 = ptr::mut_ptr::::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
                                            // mir::Constant
-                                           // + span: $DIR/sibling_ptr.rs:15:12: 15:15
+                                           // + span: $DIR/sibling_ptr.rs:16:12: 16:15
                                            // + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::::add}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs
index 6dfb3a4ed309..81fc3c2f49c7 100644
--- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs
+++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // This attempts to modify `x.1` via a pointer derived from `addr_of_mut!(x.0)`.
 // According to Miri, that is UB. However, T-opsem has not finalized that
 // decision and as such we cannot rely on it in optimizations. Consequently,
diff --git a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff
index 8018400e798a..9854beaeb217 100644
--- a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff
@@ -25,7 +25,7 @@
 -         _2 = foo(move _3) -> bb1;        // scope 1 at $DIR/terminator.rs:+3:5: +3:15
 +         _2 = foo(const 2_i32) -> bb1;    // scope 1 at $DIR/terminator.rs:+3:5: +3:15
                                            // mir::Constant
-                                           // + span: $DIR/terminator.rs:9:5: 9:8
+                                           // + span: $DIR/terminator.rs:10:5: 10:8
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/terminator.rs b/tests/mir-opt/dataflow-const-prop/terminator.rs
index d151f666a2dc..4f001df35f14 100644
--- a/tests/mir-opt/dataflow-const-prop/terminator.rs
+++ b/tests/mir-opt/dataflow-const-prop/terminator.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DataflowConstProp
 
 fn foo(n: i32) {}
diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
index cd3b792fb751..2776ff51d85a 100644
--- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
+++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
@@ -32,7 +32,7 @@
 +         StorageLive(_4);                 // scope 0 at $DIR/cycle.rs:+3:11: +3:17
 +         _4 = cond() -> bb2;              // scope 0 at $DIR/cycle.rs:+3:11: +3:17
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:12:11: 12:15
+                                           // + span: $DIR/cycle.rs:13:11: 13:15
                                            // + literal: Const { ty: fn() -> bool {cond}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs
index b35ce0bcb5ad..570bfe84d106 100644
--- a/tests/mir-opt/dead-store-elimination/cycle.rs
+++ b/tests/mir-opt/dead-store-elimination/cycle.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DeadStoreElimination
 
 #[inline(never)]
diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
index 3b1f81175cbf..c4ebf1ca834f 100644
--- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
+++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
@@ -19,7 +19,7 @@
           _3 = &(*_1);                     // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23
           _2 = core::str::::as_bytes(move _3) -> bb1; // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23
                                            // mir::Constant
-                                           // + span: $DIR/deduplicate_blocks.rs:5:13: 5:21
+                                           // + span: $DIR/deduplicate_blocks.rs:6:13: 6:21
                                            // + literal: Const { ty: for<'a> fn(&'a str) -> &'a [u8] {core::str::::as_bytes}, val: Value() }
       }
   
diff --git a/tests/mir-opt/deduplicate_blocks.rs b/tests/mir-opt/deduplicate_blocks.rs
index 2b9eed99ecdb..46012e19aa4b 100644
--- a/tests/mir-opt/deduplicate_blocks.rs
+++ b/tests/mir-opt/deduplicate_blocks.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DeduplicateBlocks
 
 // EMIT_MIR deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
diff --git a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
index 9c729663265e..b7416d389ef7 100644
--- a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
@@ -22,7 +22,7 @@
 +         nop;                             // scope 0 at $DIR/branch.rs:+1:9: +1:10
 +         _0 = val() -> bb1;               // scope 0 at $DIR/branch.rs:+1:13: +1:18
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:13:13: 13:16
+                                           // + span: $DIR/branch.rs:14:13: 14:16
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value() }
       }
   
@@ -32,7 +32,7 @@
           StorageLive(_3);                 // scope 1 at $DIR/branch.rs:+3:16: +3:22
           _3 = cond() -> bb2;              // scope 1 at $DIR/branch.rs:+3:16: +3:22
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:15:16: 15:20
+                                           // + span: $DIR/branch.rs:16:16: 16:20
                                            // + literal: Const { ty: fn() -> bool {cond}, val: Value() }
       }
   
@@ -50,7 +50,7 @@
           StorageLive(_4);                 // scope 1 at $DIR/branch.rs:+6:9: +6:14
           _4 = val() -> bb5;               // scope 1 at $DIR/branch.rs:+6:9: +6:14
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:18:9: 18:12
+                                           // + span: $DIR/branch.rs:19:9: 19:12
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dest-prop/branch.rs b/tests/mir-opt/dest-prop/branch.rs
index 898c908b18c7..7e4276e66922 100644
--- a/tests/mir-opt/dest-prop/branch.rs
+++ b/tests/mir-opt/dest-prop/branch.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that assignment in both branches of an `if` are eliminated.
 // unit-test: DestinationPropagation
 fn val() -> i32 {
diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff
index 298991b5ad1c..a61e741f73dc 100644
--- a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff
@@ -16,7 +16,7 @@
 +         nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12
 +         _2 = dummy(move _1) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13
                                            // mir::Constant
-                                           // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10
+                                           // + span: $DIR/copy_propagation_arg.rs:17:5: 17:10
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff
index d37a9f71d3eb..c7fbecac5c47 100644
--- a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff
@@ -15,7 +15,7 @@
 -         _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17
 +         _1 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17
                                            // mir::Constant
-                                           // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14
+                                           // + span: $DIR/copy_propagation_arg.rs:12:9: 12:14
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.rs b/tests/mir-opt/dest-prop/copy_propagation_arg.rs
index 31be6c931393..57cb328c231b 100644
--- a/tests/mir-opt/dest-prop/copy_propagation_arg.rs
+++ b/tests/mir-opt/dest-prop/copy_propagation_arg.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that DestinationPropagation does not propagate an assignment to a function argument
 // (doing so can break usages of the original argument value)
 // unit-test: DestinationPropagation
diff --git a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
index cfc203c5f89a..b06f069a2e4f 100644
--- a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
@@ -28,7 +28,7 @@
 +         nop;                             // scope 0 at $DIR/cycle.rs:+1:9: +1:14
 +         _6 = val() -> bb1;               // scope 0 at $DIR/cycle.rs:+1:17: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:9:17: 9:20
+                                           // + span: $DIR/cycle.rs:10:17: 10:20
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value() }
       }
   
@@ -56,7 +56,7 @@
 +         nop;                             // scope 3 at $DIR/cycle.rs:+6:10: +6:11
           _5 = std::mem::drop::(move _6) -> bb2; // scope 3 at $DIR/cycle.rs:+6:5: +6:12
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:14:5: 14:9
+                                           // + span: $DIR/cycle.rs:15:5: 15:9
                                            // + literal: Const { ty: fn(i32) {std::mem::drop::}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dest-prop/cycle.rs b/tests/mir-opt/dest-prop/cycle.rs
index 6182878f3413..3aea19d80dc7 100644
--- a/tests/mir-opt/dest-prop/cycle.rs
+++ b/tests/mir-opt/dest-prop/cycle.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code.
 // unit-test: DestinationPropagation
 fn val() -> i32 {
diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir
index 63cac133b73b..b9d4b59d2f7a 100644
--- a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir
+++ b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir
@@ -22,7 +22,7 @@ fn f(_1: usize) -> usize {
         nop;                             // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9
         _0 = id::(move _1) -> bb1; // scope 1 at $DIR/dead_stores_79191.rs:+4:5: +4:10
                                          // mir::Constant
-                                         // + span: $DIR/dead_stores_79191.rs:12:5: 12:7
+                                         // + span: $DIR/dead_stores_79191.rs:13:5: 13:7
                                          // + literal: Const { ty: fn(usize) -> usize {id::}, val: Value() }
     }
 
diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.rs b/tests/mir-opt/dest-prop/dead_stores_79191.rs
index 43e0bf66418a..9d4814838d4e 100644
--- a/tests/mir-opt/dest-prop/dead_stores_79191.rs
+++ b/tests/mir-opt/dest-prop/dead_stores_79191.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DestinationPropagation
 
 fn id(x: T) -> T {
diff --git a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir
index 26068931aaf2..9eb0e09bf1b2 100644
--- a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir
+++ b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir
@@ -21,7 +21,7 @@ fn f(_1: usize) -> usize {
         nop;                             // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9
         _0 = id::(move _1) -> bb1; // scope 1 at $DIR/dead_stores_better.rs:+4:5: +4:10
                                          // mir::Constant
-                                         // + span: $DIR/dead_stores_better.rs:16:5: 16:7
+                                         // + span: $DIR/dead_stores_better.rs:17:5: 17:7
                                          // + literal: Const { ty: fn(usize) -> usize {id::}, val: Value() }
     }
 
diff --git a/tests/mir-opt/dest-prop/dead_stores_better.rs b/tests/mir-opt/dest-prop/dead_stores_better.rs
index 003ad57d83ea..72d406bfd40a 100644
--- a/tests/mir-opt/dest-prop/dead_stores_better.rs
+++ b/tests/mir-opt/dest-prop/dead_stores_better.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates
 // that that pass enables this one to do more optimizations.
 
diff --git a/tests/mir-opt/dest-prop/simple.rs b/tests/mir-opt/dest-prop/simple.rs
index d4c27228fe42..3a4aec34e8cc 100644
--- a/tests/mir-opt/dest-prop/simple.rs
+++ b/tests/mir-opt/dest-prop/simple.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too.
 // unit-test: DestinationPropagation
 // EMIT_MIR simple.nrvo.DestinationPropagation.diff
diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff
index fbed3178801f..457fc830874d 100644
--- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff
@@ -10,7 +10,7 @@
           debug un => _1;                  // in scope 1 at $DIR/union.rs:+5:9: +5:11
           scope 2 {
           }
-          scope 3 (inlined std::mem::drop::) { // at $DIR/union.rs:15:5: 15:27
+          scope 3 (inlined std::mem::drop::) { // at $DIR/union.rs:16:5: 16:27
               debug _x => _3;              // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
           }
       }
@@ -20,7 +20,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/union.rs:+5:23: +5:28
           _2 = val() -> bb1;               // scope 0 at $DIR/union.rs:+5:23: +5:28
                                            // mir::Constant
-                                           // + span: $DIR/union.rs:13:23: 13:26
+                                           // + span: $DIR/union.rs:14:23: 14:26
                                            // + literal: Const { ty: fn() -> u32 {val}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dest-prop/union.rs b/tests/mir-opt/dest-prop/union.rs
index eb6cb09fc455..062d02d06731 100644
--- a/tests/mir-opt/dest-prop/union.rs
+++ b/tests/mir-opt/dest-prop/union.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that we can propagate into places that are projections into unions
 // compile-flags: -Zunsound-mir-opts
 fn val() -> u32 {
diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff
index 9ea756c27129..ae63d724d0a5 100644
--- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff
@@ -36,7 +36,7 @@
 -         _6 = _2;                         // scope 1 at $DIR/unreachable.rs:+3:14: +3:15
 -         _4 = g::(move _5, move _6) -> bb2; // scope 1 at $DIR/unreachable.rs:+3:9: +3:16
 -                                          // mir::Constant
--                                          // + span: $DIR/unreachable.rs:11:9: 11:10
+-                                          // + span: $DIR/unreachable.rs:12:9: 12:10
 -                                          // + literal: Const { ty: fn(T, T) {g::}, val: Value() }
 -     }
 - 
@@ -60,7 +60,7 @@
 +         _9 = _1;                         // scope 1 at $DIR/unreachable.rs:+5:14: +5:15
 +         _7 = g::(move _1, move _9) -> bb2; // scope 1 at $DIR/unreachable.rs:+5:9: +5:16
                                            // mir::Constant
-                                           // + span: $DIR/unreachable.rs:13:9: 13:10
+                                           // + span: $DIR/unreachable.rs:14:9: 14:10
                                            // + literal: Const { ty: fn(T, T) {g::}, val: Value() }
       }
   
diff --git a/tests/mir-opt/dest-prop/unreachable.rs b/tests/mir-opt/dest-prop/unreachable.rs
index 32b5def984a8..c73d11ae3baf 100644
--- a/tests/mir-opt/dest-prop/unreachable.rs
+++ b/tests/mir-opt/dest-prop/unreachable.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that unreachable code is removed after the destination propagation.
 // Regression test for issue #105428.
 //
diff --git a/tests/mir-opt/div_overflow.rs b/tests/mir-opt/div_overflow.rs
index 10ce5bc0f4f0..fe34a865b93f 100644
--- a/tests/mir-opt/div_overflow.rs
+++ b/tests/mir-opt/div_overflow.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Copt-level=0 -Coverflow-checks=yes
 
 // Tests that division with a const does not emit a panicking branch for overflow
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
index ec063294856c..8a4a16825195 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
@@ -40,7 +40,7 @@
           _5 = &(*_1);                     // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
           _4 = Formatter::<'_>::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
                                            // mir::Constant
-                                           // + span: $DIR/funky_arms.rs:15:26: 15:35
+                                           // + span: $DIR/funky_arms.rs:16:26: 16:35
                                            // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> bool {Formatter::<'_>::sign_plus}, val: Value() }
       }
   
@@ -74,7 +74,7 @@
           _8 = &(*_1);                     // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
           _7 = Formatter::<'_>::precision(move _8) -> bb5; // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
                                            // mir::Constant
-                                           // + span: $DIR/funky_arms.rs:24:34: 24:43
+                                           // + span: $DIR/funky_arms.rs:25:34: 25:43
                                            // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> Option {Formatter::<'_>::precision}, val: Value() }
       }
   
@@ -95,7 +95,7 @@
           StorageDead(_15);                // scope 3 at $DIR/funky_arms.rs:+15:78: +15:79
           _0 = float_to_exponential_common_exact::(_1, _2, move _13, move _14, _3) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87
                                            // mir::Constant
-                                           // + span: $DIR/funky_arms.rs:26:9: 26:42
+                                           // + span: $DIR/funky_arms.rs:27:9: 27:42
                                            // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::}, val: Value() }
       }
   
@@ -110,7 +110,7 @@
           _20 = _6;                        // scope 2 at $DIR/funky_arms.rs:+17:56: +17:60
           _0 = float_to_exponential_common_shortest::(_1, _2, move _20, _3) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68
                                            // mir::Constant
-                                           // + span: $DIR/funky_arms.rs:28:9: 28:45
+                                           // + span: $DIR/funky_arms.rs:29:9: 29:45
                                            // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::}, val: Value() }
       }
   
diff --git a/tests/mir-opt/funky_arms.rs b/tests/mir-opt/funky_arms.rs
index 3e70d85e0d47..c4f75b5df6d8 100644
--- a/tests/mir-opt/funky_arms.rs
+++ b/tests/mir-opt/funky_arms.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: --crate-type lib -Cdebug-assertions=no
 
 #![feature(flt2dec)]
diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff
index 64c3e47ff46e..75d9bd54d5ba 100644
--- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff
+++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff
@@ -9,11 +9,11 @@
       let mut _4: &::C;        // in scope 0 at $DIR/dyn_trait.rs:+2:23: +2:24
       scope 1 {
           debug c => _2;                   // in scope 1 at $DIR/dyn_trait.rs:+1:9: +1:10
-+         scope 2 (inlined try_execute_query::<::C>) { // at $DIR/dyn_trait.rs:34:5: 34:25
-+             debug c => _4;               // in scope 2 at $DIR/dyn_trait.rs:26:36: 26:37
-+             let mut _5: &dyn Cache::V>; // in scope 2 at $DIR/dyn_trait.rs:27:14: 27:15
-+             scope 3 (inlined mk_cycle::<::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16
-+                 debug c => _5;           // in scope 3 at $DIR/dyn_trait.rs:20:27: 20:28
++         scope 2 (inlined try_execute_query::<::C>) { // at $DIR/dyn_trait.rs:35:5: 35:25
++             debug c => _4;               // in scope 2 at $DIR/dyn_trait.rs:27:36: 27:37
++             let mut _5: &dyn Cache::V>; // in scope 2 at $DIR/dyn_trait.rs:28:14: 28:15
++             scope 3 (inlined mk_cycle::<::V>) { // at $DIR/dyn_trait.rs:28:5: 28:16
++                 debug c => _5;           // in scope 3 at $DIR/dyn_trait.rs:21:27: 21:28
 +             }
 +         }
       }
@@ -24,7 +24,7 @@
           _3 = &(*_1);                     // scope 0 at $DIR/dyn_trait.rs:+1:22: +1:23
           _2 = ::cache::(move _3) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:13: +1:24
                                            // mir::Constant
-                                           // + span: $DIR/dyn_trait.rs:33:13: 33:21
+                                           // + span: $DIR/dyn_trait.rs:34:13: 34:21
                                            // + user_ty: UserType(0)
                                            // + literal: Const { ty: for<'a> fn(&'a T) -> &'a ::C {::cache::}, val: Value() }
       }
@@ -34,18 +34,18 @@
           StorageLive(_4);                 // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24
           _4 = &(*_2);                     // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24
 -         _0 = try_execute_query::<::C>(move _4) -> bb2; // scope 1 at $DIR/dyn_trait.rs:+2:5: +2:25
-+         StorageLive(_5);                 // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15
-+         _5 = _4 as &dyn Cache::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15
-+         _0 = ::V> as Cache>::store_nocache(_5) -> bb2; // scope 3 at $DIR/dyn_trait.rs:21:5: 21:22
++         StorageLive(_5);                 // scope 2 at $DIR/dyn_trait.rs:28:14: 28:15
++         _5 = _4 as &dyn Cache::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:28:14: 28:15
++         _0 = ::V> as Cache>::store_nocache(_5) -> bb2; // scope 3 at $DIR/dyn_trait.rs:22:5: 22:22
                                            // mir::Constant
--                                          // + span: $DIR/dyn_trait.rs:34:5: 34:22
+-                                          // + span: $DIR/dyn_trait.rs:35:5: 35:22
 -                                          // + literal: Const { ty: for<'a> fn(&'a ::C) {try_execute_query::<::C>}, val: Value() }
-+                                          // + span: $DIR/dyn_trait.rs:21:7: 21:20
++                                          // + span: $DIR/dyn_trait.rs:22:7: 22:20
 +                                          // + literal: Const { ty: for<'a> fn(&'a dyn Cache::V>) {::V> as Cache>::store_nocache}, val: Value() }
       }
   
       bb2: {
-+         StorageDead(_5);                 // scope 2 at $DIR/dyn_trait.rs:27:15: 27:16
++         StorageDead(_5);                 // scope 2 at $DIR/dyn_trait.rs:28:15: 28:16
           StorageDead(_4);                 // scope 1 at $DIR/dyn_trait.rs:+2:24: +2:25
           StorageDead(_2);                 // scope 0 at $DIR/dyn_trait.rs:+3:1: +3:2
           return;                          // scope 0 at $DIR/dyn_trait.rs:+3:2: +3:2
diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
index 7653a5ded440..925c95988b79 100644
--- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
+++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
@@ -11,7 +11,7 @@
           _2 = &(*_1);                     // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22
           _0 =  as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/dyn_trait.rs:21:7: 21:20
+                                           // + span: $DIR/dyn_trait.rs:22:7: 22:20
                                            // + literal: Const { ty: for<'a> fn(&'a dyn Cache) { as Cache>::store_nocache}, val: Value() }
       }
   
diff --git a/tests/mir-opt/inline/dyn_trait.rs b/tests/mir-opt/inline/dyn_trait.rs
index 6a46e1e07b1a..2af81f825705 100644
--- a/tests/mir-opt/inline/dyn_trait.rs
+++ b/tests/mir-opt/inline/dyn_trait.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #![crate_type = "lib"]
 
 use std::fmt::Debug;
diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
index 3fa9c3e88f63..f4e5272abfc8 100644
--- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
+++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
@@ -6,8 +6,8 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/dyn_trait.rs:+0:43: +0:43
       let mut _2: &dyn Cache::V>; // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
       let mut _3: &C;                      // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
-+     scope 1 (inlined mk_cycle::<::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16
-+         debug c => _2;                   // in scope 1 at $DIR/dyn_trait.rs:20:27: 20:28
++     scope 1 (inlined mk_cycle::<::V>) { // at $DIR/dyn_trait.rs:28:5: 28:16
++         debug c => _2;                   // in scope 1 at $DIR/dyn_trait.rs:21:27: 21:28
 +     }
   
       bb0: {
@@ -17,11 +17,11 @@
           _2 = move _3 as &dyn Cache::V> (Pointer(Unsize)); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
           StorageDead(_3);                 // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
 -         _0 = mk_cycle::<::V>(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:16
-+         _0 = ::V> as Cache>::store_nocache(_2) -> bb1; // scope 1 at $DIR/dyn_trait.rs:21:5: 21:22
++         _0 = ::V> as Cache>::store_nocache(_2) -> bb1; // scope 1 at $DIR/dyn_trait.rs:22:5: 22:22
                                            // mir::Constant
--                                          // + span: $DIR/dyn_trait.rs:27:5: 27:13
+-                                          // + span: $DIR/dyn_trait.rs:28:5: 28:13
 -                                          // + literal: Const { ty: for<'a> fn(&'a (dyn Cache::V> + 'a)) {mk_cycle::<::V>}, val: Value() }
-+                                          // + span: $DIR/dyn_trait.rs:21:7: 21:20
++                                          // + span: $DIR/dyn_trait.rs:22:7: 22:20
 +                                          // + literal: Const { ty: for<'a> fn(&'a dyn Cache::V>) {::V> as Cache>::store_nocache}, val: Value() }
       }
   
diff --git a/tests/mir-opt/inline/exponential_runtime.main.Inline.diff b/tests/mir-opt/inline/exponential_runtime.main.Inline.diff
index dd1f253cb47d..30af8661dec7 100644
--- a/tests/mir-opt/inline/exponential_runtime.main.Inline.diff
+++ b/tests/mir-opt/inline/exponential_runtime.main.Inline.diff
@@ -4,14 +4,14 @@
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/exponential_runtime.rs:+0:11: +0:11
       let _1: ();                          // in scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
-+     scope 1 (inlined <() as G>::call) {  // at $DIR/exponential_runtime.rs:86:5: 86:22
-+         let _2: ();                      // in scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         let _3: ();                      // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
-+         let _4: ();                      // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
-+         scope 2 (inlined <() as F>::call) { // at $DIR/exponential_runtime.rs:73:9: 73:25
-+             let _5: ();                  // in scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25
-+             let _6: ();                  // in scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25
-+             let _7: ();                  // in scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25
++     scope 1 (inlined <() as G>::call) {  // at $DIR/exponential_runtime.rs:87:5: 87:22
++         let _2: ();                      // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         let _3: ();                      // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++         let _4: ();                      // in scope 1 at $DIR/exponential_runtime.rs:76:9: 76:25
++         scope 2 (inlined <() as F>::call) { // at $DIR/exponential_runtime.rs:74:9: 74:25
++             let _5: ();                  // in scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25
++             let _6: ();                  // in scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25
++             let _7: ();                  // in scope 2 at $DIR/exponential_runtime.rs:64:9: 64:25
 +         }
 +     }
   
@@ -21,14 +21,14 @@
 +         StorageLive(_2);                 // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
 +         StorageLive(_3);                 // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
 +         StorageLive(_4);                 // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
-+         StorageLive(_5);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         StorageLive(_6);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         StorageLive(_7);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         _5 = <() as E>::call() -> bb4;   // scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25
++         StorageLive(_5);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         StorageLive(_6);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         StorageLive(_7);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         _5 = <() as E>::call() -> bb4;   // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25
                                            // mir::Constant
--                                          // + span: $DIR/exponential_runtime.rs:86:5: 86:20
+-                                          // + span: $DIR/exponential_runtime.rs:87:5: 87:20
 -                                          // + literal: Const { ty: fn() {<() as G>::call}, val: Value() }
-+                                          // + span: $DIR/exponential_runtime.rs:61:9: 61:23
++                                          // + span: $DIR/exponential_runtime.rs:62:9: 62:23
 +                                          // + literal: Const { ty: fn() {<() as E>::call}, val: Value() }
       }
   
@@ -42,33 +42,33 @@
 +     }
 + 
 +     bb2: {
-+         StorageDead(_7);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         StorageDead(_6);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         StorageDead(_5);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         _3 = <() as F>::call() -> bb3;   // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
-+                                          // mir::Constant
-+                                          // + span: $DIR/exponential_runtime.rs:74:9: 74:23
-+                                          // + literal: Const { ty: fn() {<() as F>::call}, val: Value() }
-+     }
-+ 
-+     bb3: {
-+         _4 = <() as F>::call() -> bb1;   // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++         StorageDead(_7);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         StorageDead(_6);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         StorageDead(_5);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         _3 = <() as F>::call() -> bb3;   // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
 +                                          // mir::Constant
 +                                          // + span: $DIR/exponential_runtime.rs:75:9: 75:23
 +                                          // + literal: Const { ty: fn() {<() as F>::call}, val: Value() }
 +     }
 + 
-+     bb4: {
-+         _6 = <() as E>::call() -> bb5;   // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25
++     bb3: {
++         _4 = <() as F>::call() -> bb1;   // scope 1 at $DIR/exponential_runtime.rs:76:9: 76:25
 +                                          // mir::Constant
-+                                          // + span: $DIR/exponential_runtime.rs:62:9: 62:23
++                                          // + span: $DIR/exponential_runtime.rs:76:9: 76:23
++                                          // + literal: Const { ty: fn() {<() as F>::call}, val: Value() }
++     }
++ 
++     bb4: {
++         _6 = <() as E>::call() -> bb5;   // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25
++                                          // mir::Constant
++                                          // + span: $DIR/exponential_runtime.rs:63:9: 63:23
 +                                          // + literal: Const { ty: fn() {<() as E>::call}, val: Value() }
 +     }
 + 
 +     bb5: {
-+         _7 = <() as E>::call() -> bb2;   // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25
++         _7 = <() as E>::call() -> bb2;   // scope 2 at $DIR/exponential_runtime.rs:64:9: 64:25
 +                                          // mir::Constant
-+                                          // + span: $DIR/exponential_runtime.rs:63:9: 63:23
++                                          // + span: $DIR/exponential_runtime.rs:64:9: 64:23
 +                                          // + literal: Const { ty: fn() {<() as E>::call}, val: Value() }
       }
   }
diff --git a/tests/mir-opt/inline/exponential_runtime.rs b/tests/mir-opt/inline/exponential_runtime.rs
index d9219d76a98b..39985528f462 100644
--- a/tests/mir-opt/inline/exponential_runtime.rs
+++ b/tests/mir-opt/inline/exponential_runtime.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Checks that code with exponential runtime does not have exponential behavior in inlining.
 
 trait A {
diff --git a/tests/mir-opt/inline/inline_cycle.one.Inline.diff b/tests/mir-opt/inline/inline_cycle.one.Inline.diff
index 5510cd7bc8ce..f6ba69a1d294 100644
--- a/tests/mir-opt/inline/inline_cycle.one.Inline.diff
+++ b/tests/mir-opt/inline/inline_cycle.one.Inline.diff
@@ -4,9 +4,9 @@
   fn one() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10
       let _1: ();                          // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
-+     scope 1 (inlined ::call) { // at $DIR/inline_cycle.rs:14:5: 14:24
-+         scope 2 (inlined  as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23
-+             scope 3 (inlined  as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31
++     scope 1 (inlined ::call) { // at $DIR/inline_cycle.rs:15:5: 15:24
++         scope 2 (inlined  as Call>::call) { // at $DIR/inline_cycle.rs:44:9: 44:23
++             scope 3 (inlined  as Call>::call) { // at $DIR/inline_cycle.rs:29:9: 29:31
 +             }
 +         }
 +     }
@@ -14,10 +14,10 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
 -         _1 = ::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
-+         _1 = ::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28
++         _1 = ::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:37:9: 37:28
                                            // mir::Constant
--                                          // + span: $DIR/inline_cycle.rs:14:5: 14:22
-+                                          // + span: $DIR/inline_cycle.rs:36:9: 36:26
+-                                          // + span: $DIR/inline_cycle.rs:15:5: 15:22
++                                          // + span: $DIR/inline_cycle.rs:37:9: 37:26
                                            // + literal: Const { ty: fn() {::call}, val: Value() }
       }
   
diff --git a/tests/mir-opt/inline/inline_cycle.rs b/tests/mir-opt/inline/inline_cycle.rs
index 63ad57de1d46..2f81696cf03e 100644
--- a/tests/mir-opt/inline/inline_cycle.rs
+++ b/tests/mir-opt/inline/inline_cycle.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that inliner handles various forms of recursion and doesn't fall into
 // an infinite inlining cycle. The particular outcome of inlining is not
 // crucial otherwise.
diff --git a/tests/mir-opt/inline/inline_cycle.two.Inline.diff b/tests/mir-opt/inline/inline_cycle.two.Inline.diff
index 0215b3d93f9e..c8f58111da7d 100644
--- a/tests/mir-opt/inline/inline_cycle.two.Inline.diff
+++ b/tests/mir-opt/inline/inline_cycle.two.Inline.diff
@@ -5,11 +5,11 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10
       let _1: ();                          // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
 +     let mut _2: fn() {f};                // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
-+     let mut _4: ();                      // in scope 0 at $DIR/inline_cycle.rs:54:5: 54:8
-+     scope 1 (inlined call::) { // at $DIR/inline_cycle.rs:49:5: 49:12
-+         debug f => _2;                   // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23
-+         let _3: ();                      // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
-+         scope 2 (inlined >::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8
++     let mut _4: ();                      // in scope 0 at $DIR/inline_cycle.rs:55:5: 55:8
++     scope 1 (inlined call::) { // at $DIR/inline_cycle.rs:50:5: 50:12
++         debug f => _2;                   // in scope 1 at $DIR/inline_cycle.rs:54:22: 54:23
++         let _3: ();                      // in scope 1 at $DIR/inline_cycle.rs:55:5: 55:8
++         scope 2 (inlined >::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:55:5: 55:8
 +         }
 +     }
   
@@ -19,19 +19,19 @@
 +         StorageLive(_2);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
 +         _2 = f;                          // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
                                            // mir::Constant
--                                          // + span: $DIR/inline_cycle.rs:49:5: 49:9
+-                                          // + span: $DIR/inline_cycle.rs:50:5: 50:9
 -                                          // + literal: Const { ty: fn(fn() {f}) {call::}, val: Value() }
 -                                          // mir::Constant
-                                           // + span: $DIR/inline_cycle.rs:49:10: 49:11
+                                           // + span: $DIR/inline_cycle.rs:50:10: 50:11
                                            // + literal: Const { ty: fn() {f}, val: Value() }
 +         StorageLive(_3);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
-+         StorageLive(_4);                 // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
-+         _4 = const ();                   // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
++         StorageLive(_4);                 // scope 1 at $DIR/inline_cycle.rs:55:5: 55:8
++         _4 = const ();                   // scope 1 at $DIR/inline_cycle.rs:55:5: 55:8
 +         _3 = move _2() -> bb1;           // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_4);                 // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
++         StorageDead(_4);                 // scope 1 at $DIR/inline_cycle.rs:55:5: 55:8
 +         StorageDead(_3);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
 +         StorageDead(_2);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
           StorageDead(_1);                 // scope 0 at $DIR/inline_cycle.rs:+1:12: +1:13
diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff
index 04de3e61e5ff..9429ca593646 100644
--- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff
@@ -4,19 +4,19 @@
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/inline_cycle_generic.rs:+0:11: +0:11
       let _1: ();                          // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
-+     scope 1 (inlined ::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24
-+         scope 2 (inlined  as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31
++     scope 1 (inlined ::call) { // at $DIR/inline_cycle_generic.rs:10:5: 10:24
++         scope 2 (inlined  as Call>::call) { // at $DIR/inline_cycle_generic.rs:39:9: 39:31
 +         }
 +     }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
 -         _1 = ::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
-+         _1 = ::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:31:9: 31:28
++         _1 = ::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:32:9: 32:28
                                            // mir::Constant
--                                          // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22
+-                                          // + span: $DIR/inline_cycle_generic.rs:10:5: 10:22
 -                                          // + literal: Const { ty: fn() {::call}, val: Value() }
-+                                          // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26
++                                          // + span: $DIR/inline_cycle_generic.rs:32:9: 32:26
 +                                          // + literal: Const { ty: fn() {::call}, val: Value() }
       }
   
diff --git a/tests/mir-opt/inline/inline_cycle_generic.rs b/tests/mir-opt/inline/inline_cycle_generic.rs
index 24b4f37939ad..84e6e4005a6e 100644
--- a/tests/mir-opt/inline/inline_cycle_generic.rs
+++ b/tests/mir-opt/inline/inline_cycle_generic.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that inliner handles various forms of recursion and doesn't fall into
 // an infinite inlining cycle. The particular outcome of inlining is not
 // crucial otherwise.
diff --git a/tests/mir-opt/inline/inline_options.main.Inline.after.mir b/tests/mir-opt/inline/inline_options.main.Inline.after.mir
index abe26bd8ce36..a2938ead0dc1 100644
--- a/tests/mir-opt/inline/inline_options.main.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_options.main.Inline.after.mir
@@ -4,17 +4,17 @@ fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/inline_options.rs:+0:11: +0:11
     let _1: ();                          // in scope 0 at $DIR/inline_options.rs:+1:5: +1:18
     let _2: ();                          // in scope 0 at $DIR/inline_options.rs:+2:5: +2:21
-    scope 1 (inlined inlined::) {   // at $DIR/inline_options.rs:10:5: 10:21
-        let _3: ();                      // in scope 1 at $DIR/inline_options.rs:16:23: 16:26
-        let _4: ();                      // in scope 1 at $DIR/inline_options.rs:16:28: 16:31
-        let _5: ();                      // in scope 1 at $DIR/inline_options.rs:16:33: 16:36
+    scope 1 (inlined inlined::) {   // at $DIR/inline_options.rs:11:5: 11:21
+        let _3: ();                      // in scope 1 at $DIR/inline_options.rs:17:23: 17:26
+        let _4: ();                      // in scope 1 at $DIR/inline_options.rs:17:28: 17:31
+        let _5: ();                      // in scope 1 at $DIR/inline_options.rs:17:33: 17:36
     }
 
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/inline_options.rs:+1:5: +1:18
         _1 = not_inlined() -> bb1;       // scope 0 at $DIR/inline_options.rs:+1:5: +1:18
                                          // mir::Constant
-                                         // + span: $DIR/inline_options.rs:9:5: 9:16
+                                         // + span: $DIR/inline_options.rs:10:5: 10:16
                                          // + literal: Const { ty: fn() {not_inlined}, val: Value() }
     }
 
@@ -24,9 +24,9 @@ fn main() -> () {
         StorageLive(_3);                 // scope 0 at $DIR/inline_options.rs:+2:5: +2:21
         StorageLive(_4);                 // scope 0 at $DIR/inline_options.rs:+2:5: +2:21
         StorageLive(_5);                 // scope 0 at $DIR/inline_options.rs:+2:5: +2:21
-        _3 = g() -> bb3;                 // scope 1 at $DIR/inline_options.rs:16:23: 16:26
+        _3 = g() -> bb3;                 // scope 1 at $DIR/inline_options.rs:17:23: 17:26
                                          // mir::Constant
-                                         // + span: $DIR/inline_options.rs:16:23: 16:24
+                                         // + span: $DIR/inline_options.rs:17:23: 17:24
                                          // + literal: Const { ty: fn() {g}, val: Value() }
     }
 
@@ -40,16 +40,16 @@ fn main() -> () {
     }
 
     bb3: {
-        _4 = g() -> bb4;                 // scope 1 at $DIR/inline_options.rs:16:28: 16:31
+        _4 = g() -> bb4;                 // scope 1 at $DIR/inline_options.rs:17:28: 17:31
                                          // mir::Constant
-                                         // + span: $DIR/inline_options.rs:16:28: 16:29
+                                         // + span: $DIR/inline_options.rs:17:28: 17:29
                                          // + literal: Const { ty: fn() {g}, val: Value() }
     }
 
     bb4: {
-        _5 = g() -> bb2;                 // scope 1 at $DIR/inline_options.rs:16:33: 16:36
+        _5 = g() -> bb2;                 // scope 1 at $DIR/inline_options.rs:17:33: 17:36
                                          // mir::Constant
-                                         // + span: $DIR/inline_options.rs:16:33: 16:34
+                                         // + span: $DIR/inline_options.rs:17:33: 17:34
                                          // + literal: Const { ty: fn() {g}, val: Value() }
     }
 }
diff --git a/tests/mir-opt/inline/inline_options.rs b/tests/mir-opt/inline/inline_options.rs
index 477f050b69e4..f0a898832392 100644
--- a/tests/mir-opt/inline/inline_options.rs
+++ b/tests/mir-opt/inline/inline_options.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Checks that inlining threshold can be controlled with
 // inline-mir-threshold and inline-hint-threshold options.
 //
diff --git a/tests/mir-opt/inline/inline_specialization.main.Inline.diff b/tests/mir-opt/inline/inline_specialization.main.Inline.diff
index af08296edea5..9dde9994d1d1 100644
--- a/tests/mir-opt/inline/inline_specialization.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_specialization.main.Inline.diff
@@ -7,19 +7,19 @@
       scope 1 {
           debug x => _1;                   // in scope 1 at $DIR/inline_specialization.rs:+1:9: +1:10
       }
-+     scope 2 (inlined  as Foo>::bar) { // at $DIR/inline_specialization.rs:5:13: 5:38
++     scope 2 (inlined  as Foo>::bar) { // at $DIR/inline_specialization.rs:6:13: 6:38
 +     }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_specialization.rs:+1:9: +1:10
 -         _1 =  as Foo>::bar() -> bb1; // scope 0 at $DIR/inline_specialization.rs:+1:13: +1:38
 -                                          // mir::Constant
--                                          // + span: $DIR/inline_specialization.rs:5:13: 5:36
+-                                          // + span: $DIR/inline_specialization.rs:6:13: 6:36
 -                                          // + literal: Const { ty: fn() -> u32 { as Foo>::bar}, val: Value() }
 -     }
 - 
 -     bb1: {
-+         _1 = const 123_u32;              // scope 2 at $DIR/inline_specialization.rs:14:31: 14:34
++         _1 = const 123_u32;              // scope 2 at $DIR/inline_specialization.rs:15:31: 15:34
           _0 = const ();                   // scope 0 at $DIR/inline_specialization.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/inline_specialization.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/inline_specialization.rs:+2:2: +2:2
diff --git a/tests/mir-opt/inline/inline_specialization.rs b/tests/mir-opt/inline/inline_specialization.rs
index 87275b4e5146..c24795e05c6d 100644
--- a/tests/mir-opt/inline/inline_specialization.rs
+++ b/tests/mir-opt/inline/inline_specialization.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #![feature(specialization)]
 
 // EMIT_MIR inline_specialization.main.Inline.diff
diff --git a/tests/mir-opt/inline/inline_trait_method.rs b/tests/mir-opt/inline/inline_trait_method.rs
index 74be53f55129..6aa957eb5349 100644
--- a/tests/mir-opt/inline/inline_trait_method.rs
+++ b/tests/mir-opt/inline/inline_trait_method.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Z span_free_formats
 
 fn main() {
diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir
index 637bf282a65b..a9020a5bbb7c 100644
--- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir
@@ -10,7 +10,7 @@ fn test(_1: &dyn X) -> u32 {
         _2 = &(*_1);                     // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10
         _0 = ::y(move _2) -> bb1; // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10
                                          // mir::Constant
-                                         // + span: $DIR/inline_trait_method.rs:9:7: 9:8
+                                         // + span: $DIR/inline_trait_method.rs:10:7: 10:8
                                          // + literal: Const { ty: for<'a> fn(&'a dyn X) -> u32 {::y}, val: Value() }
     }
 
diff --git a/tests/mir-opt/inline/inline_trait_method_2.rs b/tests/mir-opt/inline/inline_trait_method_2.rs
index 378e71a25673..07a601908018 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.rs
+++ b/tests/mir-opt/inline/inline_trait_method_2.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Z span_free_formats -Z mir-opt-level=4
 
 // EMIT_MIR inline_trait_method_2.test2.Inline.after.mir
diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
index b7c5bbecb688..a4bbecf3b876 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
@@ -5,8 +5,8 @@ fn test2(_1: &dyn X) -> bool {
     let mut _0: bool;                    // return place in scope 0 at $DIR/inline_trait_method_2.rs:+0:24: +0:28
     let mut _2: &dyn X;                  // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
     let mut _3: &dyn X;                  // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
-    scope 1 (inlined test) {             // at $DIR/inline_trait_method_2.rs:5:5: 5:12
-        debug x => _2;                   // in scope 1 at $DIR/inline_trait_method_2.rs:9:9: 9:10
+    scope 1 (inlined test) {             // at $DIR/inline_trait_method_2.rs:6:5: 6:12
+        debug x => _2;                   // in scope 1 at $DIR/inline_trait_method_2.rs:10:9: 10:10
     }
 
     bb0: {
@@ -15,9 +15,9 @@ fn test2(_1: &dyn X) -> bool {
         _3 = &(*_1);                     // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
         _2 = move _3 as &dyn X (Pointer(Unsize)); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
         StorageDead(_3);                 // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
-        _0 = ::y(_2) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10
+        _0 = ::y(_2) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:11:5: 11:10
                                          // mir::Constant
-                                         // + span: $DIR/inline_trait_method_2.rs:10:7: 10:8
+                                         // + span: $DIR/inline_trait_method_2.rs:11:7: 11:8
                                          // + literal: Const { ty: for<'a> fn(&'a dyn X) -> bool {::y}, val: Value() }
     }
 
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.diff
index 97361fa5f4c3..18df6f9af5fa 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.diff
@@ -3,14 +3,14 @@
   
   fn outer() -> usize {
       let mut _0: usize;                   // return place in scope 0 at $DIR/issue_106141.rs:+0:19: +0:24
-+     scope 1 (inlined inner) {            // at $DIR/issue_106141.rs:2:5: 2:12
-+         let mut _1: bool;                // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21
-+         let mut _2: bool;                // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21
-+         let mut _3: &[bool; 1];          // in scope 1 at $DIR/issue_106141.rs:11:18: 11:25
++     scope 1 (inlined inner) {            // at $DIR/issue_106141.rs:3:5: 3:12
++         let mut _1: bool;                // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21
++         let mut _2: bool;                // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21
++         let mut _3: &[bool; 1];          // in scope 1 at $DIR/issue_106141.rs:12:18: 12:25
 +         scope 2 {
-+             debug buffer => _3;          // in scope 2 at $DIR/issue_106141.rs:11:9: 11:15
++             debug buffer => _3;          // in scope 2 at $DIR/issue_106141.rs:12:9: 12:15
 +             scope 3 {
-+                 debug index => _0;       // in scope 3 at $DIR/issue_106141.rs:12:9: 12:14
++                 debug index => _0;       // in scope 3 at $DIR/issue_106141.rs:13:9: 13:14
 +             }
 +         }
 +     }
@@ -18,36 +18,36 @@
       bb0: {
 -         _0 = inner() -> bb1;             // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
 +         StorageLive(_3);                 // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
-+         _3 = const _;                    // scope 1 at $DIR/issue_106141.rs:11:18: 11:25
++         _3 = const _;                    // scope 1 at $DIR/issue_106141.rs:12:18: 12:25
                                            // mir::Constant
--                                          // + span: $DIR/issue_106141.rs:2:5: 2:10
+-                                          // + span: $DIR/issue_106141.rs:3:5: 3:10
 -                                          // + literal: Const { ty: fn() -> usize {inner}, val: Value() }
-+                                          // + span: $DIR/issue_106141.rs:11:18: 11:25
++                                          // + span: $DIR/issue_106141.rs:12:18: 12:25
 +                                          // + literal: Const { ty: &[bool; 1], val: Unevaluated(inner, [], Some(promoted[0])) }
-+         _0 = index() -> bb1;             // scope 2 at $DIR/issue_106141.rs:12:17: 12:24
++         _0 = index() -> bb1;             // scope 2 at $DIR/issue_106141.rs:13:17: 13:24
 +                                          // mir::Constant
-+                                          // + span: $DIR/issue_106141.rs:12:17: 12:22
++                                          // + span: $DIR/issue_106141.rs:13:17: 13:22
 +                                          // + literal: Const { ty: fn() -> usize {index}, val: Value() }
       }
   
       bb1: {
-+         StorageLive(_1);                 // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
-+         _2 = Lt(_0, const 1_usize);      // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
-+         assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
++         StorageLive(_1);                 // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
++         _2 = Lt(_0, const 1_usize);      // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
++         assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
 +     }
 + 
 +     bb2: {
-+         _1 = (*_3)[_0];                  // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
-+         switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
++         _1 = (*_3)[_0];                  // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
++         switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
 +     }
 + 
 +     bb3: {
-+         _0 = const 0_usize;              // scope 3 at $DIR/issue_106141.rs:16:9: 16:10
-+         goto -> bb4;                     // scope 3 at $DIR/issue_106141.rs:13:5: 17:6
++         _0 = const 0_usize;              // scope 3 at $DIR/issue_106141.rs:17:9: 17:10
++         goto -> bb4;                     // scope 3 at $DIR/issue_106141.rs:14:5: 18:6
 +     }
 + 
 +     bb4: {
-+         StorageDead(_1);                 // scope 3 at $DIR/issue_106141.rs:17:5: 17:6
++         StorageDead(_1);                 // scope 3 at $DIR/issue_106141.rs:18:5: 18:6
 +         StorageDead(_3);                 // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
           return;                          // scope 0 at $DIR/issue_106141.rs:+2:2: +2:2
       }
diff --git a/tests/mir-opt/inline/issue_106141.rs b/tests/mir-opt/inline/issue_106141.rs
index c8288b7f3419..b6bd806e6fce 100644
--- a/tests/mir-opt/inline/issue_106141.rs
+++ b/tests/mir-opt/inline/issue_106141.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 pub fn outer() -> usize {
     inner()
 }
diff --git a/tests/mir-opt/inline/unchecked_shifts.rs b/tests/mir-opt/inline/unchecked_shifts.rs
index e55fa745abce..17724530d657 100644
--- a/tests/mir-opt/inline/unchecked_shifts.rs
+++ b/tests/mir-opt/inline/unchecked_shifts.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #![crate_type = "lib"]
 #![feature(unchecked_math)]
 
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
index 537be1c2ae47..bf05ed417181 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
@@ -7,7 +7,7 @@
       let mut _0: u16;                     // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:65: +0:68
       let mut _3: u16;                     // in scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:6
       let mut _4: u32;                     // in scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
-+     scope 1 (inlined core::num::::unchecked_shl) { // at $DIR/unchecked_shifts.rs:10:7: 10:23
++     scope 1 (inlined core::num::::unchecked_shl) { // at $DIR/unchecked_shifts.rs:11:7: 11:23
 +         debug self => _3;                // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         let mut _5: u16;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
@@ -60,7 +60,7 @@
 +         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         _7 = >::try_into(_4) -> bb1; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                            // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:10:7: 10:20
+-                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
 -                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::::unchecked_shl}, val: Value() }
 +                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +                                          // + literal: Const { ty: fn(u32) -> Result>::Error> {>::try_into}, val: Value() }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
index 517440af9f2e..7f6e974f66b1 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
@@ -4,7 +4,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
     debug a => _1;                       // in scope 0 at $DIR/unchecked_shifts.rs:+0:46: +0:47
     debug b => _2;                       // in scope 0 at $DIR/unchecked_shifts.rs:+0:54: +0:55
     let mut _0: u16;                     // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:65: +0:68
-    scope 1 (inlined core::num::::unchecked_shl) { // at $DIR/unchecked_shifts.rs:10:7: 10:23
+    scope 1 (inlined core::num::::unchecked_shl) { // at $DIR/unchecked_shifts.rs:11:7: 11:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         let mut _3: u16;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
index 021ff67f5219..5c4fb5ba8ba2 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
@@ -7,7 +7,7 @@
       let mut _0: i16;                     // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:63: +0:66
       let mut _3: i16;                     // in scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:6
       let mut _4: u32;                     // in scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
-+     scope 1 (inlined core::num::::unchecked_shr) { // at $DIR/unchecked_shifts.rs:16:7: 16:23
++     scope 1 (inlined core::num::::unchecked_shr) { // at $DIR/unchecked_shifts.rs:17:7: 17:23
 +         debug self => _3;                // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         let mut _5: i16;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
@@ -60,7 +60,7 @@
 +         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         _7 = >::try_into(_4) -> bb1; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                            // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:16:7: 16:20
+-                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
 -                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::::unchecked_shr}, val: Value() }
 +                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +                                          // + literal: Const { ty: fn(u32) -> Result>::Error> {>::try_into}, val: Value() }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
index 0d56e9a68eb4..698a3c656550 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
@@ -4,7 +4,7 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
     debug a => _1;                       // in scope 0 at $DIR/unchecked_shifts.rs:+0:44: +0:45
     debug b => _2;                       // in scope 0 at $DIR/unchecked_shifts.rs:+0:52: +0:53
     let mut _0: i16;                     // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:63: +0:66
-    scope 1 (inlined core::num::::unchecked_shr) { // at $DIR/unchecked_shifts.rs:16:7: 16:23
+    scope 1 (inlined core::num::::unchecked_shr) { // at $DIR/unchecked_shifts.rs:17:7: 17:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         let mut _3: i16;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff
index b96c80b42161..d048b9e65130 100644
--- a/tests/mir-opt/issue_101973.inner.ConstProp.diff
+++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff
@@ -16,15 +16,15 @@
       let mut _11: bool;                   // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
       let mut _12: u32;                    // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
       let mut _13: bool;                   // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
-      scope 1 (inlined imm8) {             // at $DIR/issue_101973.rs:14:5: 14:17
-          debug x => _1;                   // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14
-          let mut _14: u32;                // in scope 1 at $DIR/issue_101973.rs:7:12: 7:27
-          let mut _15: u32;                // in scope 1 at $DIR/issue_101973.rs:7:12: 7:20
+      scope 1 (inlined imm8) {             // at $DIR/issue_101973.rs:15:5: 15:17
+          debug x => _1;                   // in scope 1 at $DIR/issue_101973.rs:6:13: 6:14
+          let mut _14: u32;                // in scope 1 at $DIR/issue_101973.rs:8:12: 8:27
+          let mut _15: u32;                // in scope 1 at $DIR/issue_101973.rs:8:12: 8:20
           scope 2 {
-              debug out => _4;             // in scope 2 at $DIR/issue_101973.rs:6:9: 6:16
+              debug out => _4;             // in scope 2 at $DIR/issue_101973.rs:7:9: 7:16
           }
       }
-      scope 3 (inlined core::num::::rotate_right) { // at $DIR/issue_101973.rs:14:18: 14:58
+      scope 3 (inlined core::num::::rotate_right) { // at $DIR/issue_101973.rs:15:18: 15:58
           debug self => _4;                // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
           debug n => _6;                   // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
       }
@@ -33,13 +33,13 @@
           StorageLive(_2);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65
           StorageLive(_3);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:58
           StorageLive(_4);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17
-          StorageLive(_14);                // scope 2 at $DIR/issue_101973.rs:7:12: 7:27
-          StorageLive(_15);                // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
-          _15 = Shr(_1, const 0_i32);      // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
-          _14 = BitAnd(move _15, const 255_u32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27
-          StorageDead(_15);                // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
-          _4 = BitOr(const 0_u32, move _14); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27
-          StorageDead(_14);                // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
+          StorageLive(_14);                // scope 2 at $DIR/issue_101973.rs:8:12: 8:27
+          StorageLive(_15);                // scope 2 at $DIR/issue_101973.rs:8:12: 8:20
+          _15 = Shr(_1, const 0_i32);      // scope 2 at $DIR/issue_101973.rs:8:12: 8:20
+          _14 = BitAnd(move _15, const 255_u32); // scope 2 at $DIR/issue_101973.rs:8:12: 8:27
+          StorageDead(_15);                // scope 2 at $DIR/issue_101973.rs:8:26: 8:27
+          _4 = BitOr(const 0_u32, move _14); // scope 2 at $DIR/issue_101973.rs:8:5: 8:27
+          StorageDead(_14);                // scope 2 at $DIR/issue_101973.rs:8:26: 8:27
           StorageLive(_6);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
           StorageLive(_7);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
           StorageLive(_8);                 // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
diff --git a/tests/mir-opt/issue_101973.rs b/tests/mir-opt/issue_101973.rs
index 216659a235ef..da388f14918f 100644
--- a/tests/mir-opt/issue_101973.rs
+++ b/tests/mir-opt/issue_101973.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -O -C debug-assertions=on
 // This needs inlining followed by ConstProp to reproduce, so we cannot use "unit-test".
 
diff --git a/tests/mir-opt/issue_76432.rs b/tests/mir-opt/issue_76432.rs
index fbbfd4ceb112..76bb11aae3d7 100644
--- a/tests/mir-opt/issue_76432.rs
+++ b/tests/mir-opt/issue_76432.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Zmir-enable-passes=-NormalizeArrayLen
 // Check that we do not insert StorageDead at each target if StorageDead was never seen
 
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
index 6e28fb61b6bd..42b605326908 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
@@ -5,7 +5,7 @@ fn num_to_digit(_1: char) -> u32 {
     let mut _0: u32;                     // return place in scope 0 at $DIR/issue_59352.rs:+0:35: +0:38
     let mut _2: std::option::Option; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
     let mut _3: u32;                     // in scope 0 at $DIR/issue_59352.rs:+2:12: +2:23
-    scope 1 (inlined char::methods::::is_digit) { // at $DIR/issue_59352.rs:14:12: 14:23
+    scope 1 (inlined char::methods::::is_digit) { // at $DIR/issue_59352.rs:15:12: 15:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         debug radix => _3;               // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         let mut _4: &std::option::Option; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
@@ -15,7 +15,7 @@ fn num_to_digit(_1: char) -> u32 {
             let mut _6: isize;           // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
         }
     }
-    scope 3 (inlined #[track_caller] Option::::unwrap) { // at $DIR/issue_59352.rs:14:42: 14:50
+    scope 3 (inlined #[track_caller] Option::::unwrap) { // at $DIR/issue_59352.rs:15:42: 15:50
         debug self => _2;                // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _7: isize;               // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _8: !;                   // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
@@ -38,7 +38,7 @@ fn num_to_digit(_1: char) -> u32 {
         StorageLive(_2);                 // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
         _2 = char::methods::::to_digit(_1, const 8_u32) -> bb2; // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
                                          // mir::Constant
-                                         // + span: $DIR/issue_59352.rs:14:30: 14:38
+                                         // + span: $DIR/issue_59352.rs:15:30: 15:38
                                          // + literal: Const { ty: fn(char, u32) -> Option {char::methods::::to_digit}, val: Value() }
     }
 
diff --git a/tests/mir-opt/issues/issue_59352.rs b/tests/mir-opt/issues/issue_59352.rs
index 1e0045555ab8..92011bd65887 100644
--- a/tests/mir-opt/issues/issue_59352.rs
+++ b/tests/mir-opt/issues/issue_59352.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // This test is a mirror of codegen/issue-59352.rs.
 // The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case
 // as effectively `if x.is_some() { x.unwrap() } else { 0 }`.
diff --git a/tests/mir-opt/lower_array_len.rs b/tests/mir-opt/lower_array_len.rs
index 972d46cb8e2b..e1bb51f2d1d9 100644
--- a/tests/mir-opt/lower_array_len.rs
+++ b/tests/mir-opt/lower_array_len.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: NormalizeArrayLen
 // compile-flags: -Zmir-enable-passes=+LowerSliceLenCalls
 
diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
index 2b0370cf3580..67918e62b9c2 100644
--- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
+++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
@@ -22,7 +22,7 @@
           _6 = &(*_2);                     // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
 -         _5 = core::slice::::len(move _6) -> bb1; // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_slice_len.rs:5:22: 5:25
+-                                          // + span: $DIR/lower_slice_len.rs:6:22: 6:25
 -                                          // + literal: Const { ty: for<'a> fn(&'a [u8]) -> usize {core::slice::::len}, val: Value() }
 +         _5 = Len((*_6));                 // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
 +         goto -> bb1;                     // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
diff --git a/tests/mir-opt/lower_slice_len.rs b/tests/mir-opt/lower_slice_len.rs
index 12955aed1fbb..9c39c29fc4e4 100644
--- a/tests/mir-opt/lower_slice_len.rs
+++ b/tests/mir-opt/lower_slice_len.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: LowerSliceLenCalls
 
 // EMIT_MIR lower_slice_len.bound.LowerSliceLenCalls.diff
diff --git a/tests/mir-opt/nrvo_simple.rs b/tests/mir-opt/nrvo_simple.rs
index 5786ae621270..525dfe4262a4 100644
--- a/tests/mir-opt/nrvo_simple.rs
+++ b/tests/mir-opt/nrvo_simple.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: RenameReturnPlace
 
 // EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff
diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
index a8dd91efc379..0e8309532c2f 100644
--- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
+++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
@@ -34,7 +34,7 @@
           _3 = std::ops::Range:: { start: const 0_i32, end: const 10_i32 }; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
           _2 =  as IntoIterator>::into_iter(move _3) -> bb1; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
                                            // mir::Constant
-                                           // + span: $DIR/remove_storage_markers.rs:10:14: 10:19
+                                           // + span: $DIR/remove_storage_markers.rs:11:14: 11:19
                                            // + literal: Const { ty: fn(std::ops::Range) ->  as IntoIterator>::IntoIter { as IntoIterator>::into_iter}, val: Value() }
       }
   
@@ -54,7 +54,7 @@
           _8 = &mut (*_9);                 // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
           _7 =  as Iterator>::next(move _8) -> bb3; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
                                            // mir::Constant
-                                           // + span: $DIR/remove_storage_markers.rs:10:14: 10:19
+                                           // + span: $DIR/remove_storage_markers.rs:11:14: 11:19
                                            // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() }
       }
   
diff --git a/tests/mir-opt/remove_storage_markers.rs b/tests/mir-opt/remove_storage_markers.rs
index f00b826911c6..480db8ac155b 100644
--- a/tests/mir-opt/remove_storage_markers.rs
+++ b/tests/mir-opt/remove_storage_markers.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: RemoveStorageMarkers
 
 // Checks that storage markers are removed at opt-level=0.
diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
index ac79e7270134..b473d0fdecd0 100644
--- a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
+++ b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
@@ -16,7 +16,7 @@
       bb1: {
           _2 = noop() -> bb2;              // scope 0 at $DIR/simplify_if.rs:+2:9: +2:15
                                            // mir::Constant
-                                           // + span: $DIR/simplify_if.rs:7:9: 7:13
+                                           // + span: $DIR/simplify_if.rs:8:9: 8:13
                                            // + literal: Const { ty: fn() {noop}, val: Value() }
       }
   
diff --git a/tests/mir-opt/simplify_if.rs b/tests/mir-opt/simplify_if.rs
index 2d093d9266bb..b86f80a8038b 100644
--- a/tests/mir-opt/simplify_if.rs
+++ b/tests/mir-opt/simplify_if.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #[inline(never)]
 fn noop() {}
 
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.rs b/tests/mir-opt/simplify_locals_fixedpoint.rs
index 1fdba6e99e3e..7c41e8b7c20e 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.rs
+++ b/tests/mir-opt/simplify_locals_fixedpoint.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Zmir-opt-level=1
 
 fn foo() {
diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
index 0f8866f9c2f4..ae2c774f29dc 100644
--- a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
+++ b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
@@ -56,7 +56,7 @@
 +         StorageDead(_3);                 // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
 +         _1 = use_zst(move _2) -> bb1;    // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
                                            // mir::Constant
-                                           // + span: $DIR/simplify_locals_removes_unused_consts.rs:15:5: 15:12
+                                           // + span: $DIR/simplify_locals_removes_unused_consts.rs:16:5: 16:12
                                            // + literal: Const { ty: fn(((), ())) {use_zst}, val: Value() }
       }
   
@@ -84,7 +84,7 @@
 +         StorageDead(_7);                 // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34
 +         _5 = use_u8(move _6) -> bb2;     // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:5: +4:35
                                            // mir::Constant
-                                           // + span: $DIR/simplify_locals_removes_unused_consts.rs:17:5: 17:11
+                                           // + span: $DIR/simplify_locals_removes_unused_consts.rs:18:5: 18:11
                                            // + literal: Const { ty: fn(u8) {use_u8}, val: Value() }
       }
   
diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.rs b/tests/mir-opt/simplify_locals_removes_unused_consts.rs
index 7a03a2837ae7..983d8004e2ed 100644
--- a/tests/mir-opt/simplify_locals_removes_unused_consts.rs
+++ b/tests/mir-opt/simplify_locals_removes_unused_consts.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: SimplifyLocals-before-const-prop
 // compile-flags: -C overflow-checks=no
 
diff --git a/tests/mir-opt/simplify_match.main.ConstProp.diff b/tests/mir-opt/simplify_match.main.ConstProp.diff
index b700adfb105b..d2b9ac3cc0b9 100644
--- a/tests/mir-opt/simplify_match.main.ConstProp.diff
+++ b/tests/mir-opt/simplify_match.main.ConstProp.diff
@@ -22,7 +22,7 @@
       bb2: {
           _0 = noop() -> bb3;              // scope 0 at $DIR/simplify_match.rs:+2:17: +2:23
                                            // mir::Constant
-                                           // + span: $DIR/simplify_match.rs:7:17: 7:21
+                                           // + span: $DIR/simplify_match.rs:8:17: 8:21
                                            // + literal: Const { ty: fn() {noop}, val: Value() }
       }
   
diff --git a/tests/mir-opt/simplify_match.rs b/tests/mir-opt/simplify_match.rs
index 216203f9ff08..6a2a6f217196 100644
--- a/tests/mir-opt/simplify_match.rs
+++ b/tests/mir-opt/simplify_match.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #[inline(never)]
 fn noop() {}
 
diff --git a/tests/mir-opt/unreachable.main.UnreachablePropagation.diff b/tests/mir-opt/unreachable.main.UnreachablePropagation.diff
index 848bff1d4920..323b61346c00 100644
--- a/tests/mir-opt/unreachable.main.UnreachablePropagation.diff
+++ b/tests/mir-opt/unreachable.main.UnreachablePropagation.diff
@@ -21,7 +21,7 @@
           StorageLive(_1);                 // scope 1 at $DIR/unreachable.rs:+1:23: +1:30
           _1 = empty() -> bb1;             // scope 1 at $DIR/unreachable.rs:+1:23: +1:30
                                            // mir::Constant
-                                           // + span: $DIR/unreachable.rs:9:23: 9:28
+                                           // + span: $DIR/unreachable.rs:10:23: 10:28
                                            // + literal: Const { ty: fn() -> Option {empty}, val: Value() }
       }
   
diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs
index 6098b525b559..97093729dd13 100644
--- a/tests/mir-opt/unreachable.rs
+++ b/tests/mir-opt/unreachable.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 enum Empty {}
 
 fn empty() -> Option {
diff --git a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
index fb778470e532..94bc633613b7 100644
--- a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
+++ b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
@@ -23,7 +23,7 @@
           StorageLive(_2);                 // scope 2 at $DIR/unreachable_diverging.rs:+2:25: +2:32
           _2 = empty() -> bb1;             // scope 2 at $DIR/unreachable_diverging.rs:+2:25: +2:32
                                            // mir::Constant
-                                           // + span: $DIR/unreachable_diverging.rs:14:25: 14:30
+                                           // + span: $DIR/unreachable_diverging.rs:15:25: 15:30
                                            // + literal: Const { ty: fn() -> Option {empty}, val: Value() }
       }
   
@@ -44,7 +44,7 @@
       bb3: {
           _5 = loop_forever() -> bb5;      // scope 2 at $DIR/unreachable_diverging.rs:+4:13: +4:27
                                            // mir::Constant
-                                           // + span: $DIR/unreachable_diverging.rs:16:13: 16:25
+                                           // + span: $DIR/unreachable_diverging.rs:17:13: 17:25
                                            // + literal: Const { ty: fn() {loop_forever}, val: Value() }
       }
   
diff --git a/tests/mir-opt/unreachable_diverging.rs b/tests/mir-opt/unreachable_diverging.rs
index bbf28efc7ddd..24e776148c12 100644
--- a/tests/mir-opt/unreachable_diverging.rs
+++ b/tests/mir-opt/unreachable_diverging.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 pub enum Empty {}
 
 fn empty() -> Option {
diff --git a/tests/mir-opt/while_storage.rs b/tests/mir-opt/while_storage.rs
index afd083acb340..d10048dd908a 100644
--- a/tests/mir-opt/while_storage.rs
+++ b/tests/mir-opt/while_storage.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Test that we correctly generate StorageDead statements for while loop
 // conditions on all branches
 
diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
index 318119bd477c..811789a60c3e 100644
--- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
@@ -14,7 +14,7 @@ fn while_loop(_1: bool) -> () {
         StorageLive(_2);                 // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
         _2 = get_bool(_1) -> bb2;        // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
                                          // mir::Constant
-                                         // + span: $DIR/while_storage.rs:10:11: 10:19
+                                         // + span: $DIR/while_storage.rs:11:11: 11:19
                                          // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value() }
     }
 
@@ -26,7 +26,7 @@ fn while_loop(_1: bool) -> () {
         StorageLive(_3);                 // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
         _3 = get_bool(_1) -> bb4;        // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
                                          // mir::Constant
-                                         // + span: $DIR/while_storage.rs:11:12: 11:20
+                                         // + span: $DIR/while_storage.rs:12:12: 12:20
                                          // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value() }
     }
 

From ded048398f36c6bc15c71b1be270cc91c418935e Mon Sep 17 00:00:00 2001
From: SparrowLii 
Date: Thu, 6 Apr 2023 19:36:21 +0800
Subject: [PATCH 178/267] add `dont_check_failure_status` option in the
 compiler test

---
 src/tools/compiletest/src/header.rs  | 10 ++++++++++
 src/tools/compiletest/src/runtest.rs |  4 +++-
 tests/ui/recursion/issue-95134.rs    |  2 +-
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 5bc9d9afcb9d..43151f053080 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -150,6 +150,8 @@ pub struct TestProps {
     pub normalize_stdout: Vec<(String, String)>,
     pub normalize_stderr: Vec<(String, String)>,
     pub failure_status: i32,
+    // For UI tests, allows compiler to exit with arbitrary failure status
+    pub dont_check_failure_status: bool,
     // Whether or not `rustfix` should apply the `CodeSuggestion`s of this test and compile the
     // resulting Rust code.
     pub run_rustfix: bool,
@@ -192,6 +194,7 @@ mod directives {
     pub const CHECK_TEST_LINE_NUMBERS_MATCH: &'static str = "check-test-line-numbers-match";
     pub const IGNORE_PASS: &'static str = "ignore-pass";
     pub const FAILURE_STATUS: &'static str = "failure-status";
+    pub const DONT_CHECK_FAILURE_STATUS: &'static str = "dont-check-failure-status";
     pub const RUN_RUSTFIX: &'static str = "run-rustfix";
     pub const RUSTFIX_ONLY_MACHINE_APPLICABLE: &'static str = "rustfix-only-machine-applicable";
     pub const ASSEMBLY_OUTPUT: &'static str = "assembly-output";
@@ -239,6 +242,7 @@ impl TestProps {
             normalize_stdout: vec![],
             normalize_stderr: vec![],
             failure_status: -1,
+            dont_check_failure_status: false,
             run_rustfix: false,
             rustfix_only_machine_applicable: false,
             assembly_output: None,
@@ -401,6 +405,12 @@ impl TestProps {
                     self.failure_status = code;
                 }
 
+                config.set_name_directive(
+                    ln,
+                    DONT_CHECK_FAILURE_STATUS,
+                    &mut self.dont_check_failure_status,
+                );
+
                 config.set_name_directive(ln, RUN_RUSTFIX, &mut self.run_rustfix);
                 config.set_name_directive(
                     ln,
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index a40030723105..b71ae03eb554 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -309,7 +309,9 @@ impl<'test> TestCx<'test> {
                 );
             }
 
-            self.check_correct_failure_status(proc_res);
+            if !self.props.dont_check_failure_status {
+                self.check_correct_failure_status(proc_res);
+            }
         }
     }
 
diff --git a/tests/ui/recursion/issue-95134.rs b/tests/ui/recursion/issue-95134.rs
index fdc4d5369814..2f1cffa2fa90 100644
--- a/tests/ui/recursion/issue-95134.rs
+++ b/tests/ui/recursion/issue-95134.rs
@@ -1,7 +1,7 @@
 // build-fail
 // known-bug: #95134
 // compile-flags: -Copt-level=0
-// failure-status: 101
+// dont-check-failure-status
 // dont-check-compiler-stderr
 
 pub fn encode_num(n: u32, mut writer: Writer) -> Result<(), Writer::Error> {

From 40b6095e88926801e002221d09e53f97cfb732f3 Mon Sep 17 00:00:00 2001
From: klensy 
Date: Thu, 6 Apr 2023 18:21:37 +0300
Subject: [PATCH 179/267] bump few deps

---
 Cargo.lock                    | 40 +++++++++++++++++++----------------
 src/tools/rustbook/Cargo.toml |  2 +-
 src/tools/tidy/Cargo.toml     |  2 +-
 3 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 07dcca0fd47b..b0028530af55 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1673,12 +1673,6 @@ version = "2.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "64db3e262960f0662f43a6366788d5f10f7f244b8f7d7d987f560baf5ded5c50"
 
-[[package]]
-name = "fs_extra"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
-
 [[package]]
 name = "futf"
 version = "0.1.5"
@@ -2861,12 +2855,11 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "jemalloc-sys"
-version = "0.5.0+5.3.0"
+version = "0.5.3+5.3.0-patched"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f655c3ecfa6b0d03634595b4b54551d4bd5ac208b9e0124873949a7ab168f70b"
+checksum = "f9bd5d616ea7ed58b571b2e209a65759664d7fb021a0819d7a790afc67e47ca1"
 dependencies = [
  "cc",
- "fs_extra",
  "libc",
 ]
 
@@ -3475,18 +3468,30 @@ dependencies = [
 
 [[package]]
 name = "openssl"
-version = "0.10.38"
+version = "0.10.49"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
+checksum = "4d2f106ab837a24e03672c59b1239669a0596406ff657c3c0835b6b7f0f35a33"
 dependencies = [
  "bitflags",
  "cfg-if",
  "foreign-types",
  "libc",
  "once_cell",
+ "openssl-macros",
  "openssl-sys",
 ]
 
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.8",
+]
+
 [[package]]
 name = "openssl-probe"
 version = "0.1.5"
@@ -3495,20 +3500,19 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
 
 [[package]]
 name = "openssl-src"
-version = "111.22.0+1.1.1q"
+version = "111.25.0+1.1.1t"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f31f0d509d1c1ae9cada2f9539ff8f37933831fd5098879e482aa687d659853"
+checksum = "3173cd3626c43e3854b1b727422a276e568d9ec5fe8cec197822cf52cfb743d6"
 dependencies = [
  "cc",
 ]
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.72"
+version = "0.9.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
+checksum = "3a20eace9dc2d82904039cb76dcf50fb1a0bba071cfd1629720b5d6f1ddba0fa"
 dependencies = [
- "autocfg",
  "cc",
  "libc",
  "openssl-src",
@@ -4178,7 +4182,7 @@ name = "rustbook"
 version = "0.1.0"
 dependencies = [
  "clap 4.2.1",
- "env_logger 0.7.1",
+ "env_logger 0.10.0",
  "mdbook",
 ]
 
@@ -6299,7 +6303,7 @@ name = "tidy"
 version = "0.1.0"
 dependencies = [
  "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "cargo_metadata 0.14.0",
+ "cargo_metadata 0.15.3",
  "ignore",
  "lazy_static",
  "miropt-test-tools",
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 8286bd506bca..b9cf2617ba9e 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 
 [dependencies]
 clap = "4.0.32"
-env_logger = "0.7.1"
+env_logger = "0.10"
 
 [dependencies.mdbook]
 version = "0.4.28"
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index cdf1dd366046..8c6b1eb22ecb 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 autobins = false
 
 [dependencies]
-cargo_metadata = "0.14"
+cargo_metadata = "0.15"
 cargo-platform = "0.1.2"
 regex = "1"
 miropt-test-tools = { path = "../miropt-test-tools" }

From 00d54c879bfb6adb5b7a611af6bd522499d07a1d Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Thu, 6 Apr 2023 16:49:43 +0000
Subject: [PATCH 180/267] Label non_exhaustive on privacy errors

---
 compiler/rustc_resolve/src/diagnostics.rs     |  8 +++++-
 .../ui/rfc-2008-non-exhaustive/struct.stderr  | 11 +++++---
 .../ui/rfc-2008-non-exhaustive/variant.stderr | 25 +++++++++++++++++++
 3 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index e69a9d0aecaf..bb473d62a7bb 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1607,7 +1607,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut err =
             struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
         err.span_label(ident.span, &format!("private {}", descr));
-        if let Some(span) = ctor_fields_span {
+
+        if let Some(def_id) = res.opt_def_id()
+            && !def_id.is_local()
+            && let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
+        {
+            err.span_label(attr.span, format!("the {nonimport_descr} is `#[non_exhaustive]`"));
+        } else if let Some(span) = ctor_fields_span {
             err.span_label(span, "a constructor is private if any of the fields is private");
             if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
                 err.multipart_suggestion_verbose(
diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.stderr b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
index 2cb9ba0d1d14..36154fe51a4e 100644
--- a/tests/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -10,10 +10,10 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
    |                                ^^^^^^^^^^^ private tuple struct constructor
    |
-  ::: $DIR/auxiliary/structs.rs:12:24
+  ::: $DIR/auxiliary/structs.rs:11:1
    |
-LL | pub struct TupleStruct(pub u16, pub u16);
-   |                        ---------------- a constructor is private if any of the fields is private
+LL | #[non_exhaustive]
+   | ----------------- the tuple struct constructor is `#[non_exhaustive]`
    |
 note: the tuple struct constructor `TupleStruct` is defined here
   --> $DIR/auxiliary/structs.rs:12:1
@@ -27,6 +27,11 @@ error[E0603]: unit struct `UnitStruct` is private
 LL |     let us_explicit = structs::UnitStruct;
    |                                ^^^^^^^^^^ private unit struct
    |
+  ::: $DIR/auxiliary/structs.rs:8:1
+   |
+LL | #[non_exhaustive]
+   | ----------------- the unit struct is `#[non_exhaustive]`
+   |
 note: the unit struct `UnitStruct` is defined here
   --> $DIR/auxiliary/structs.rs:9:1
    |
diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.stderr b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
index 720b7b119cec..551ecb5acf27 100644
--- a/tests/ui/rfc-2008-non-exhaustive/variant.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -4,6 +4,11 @@ error[E0603]: tuple variant `Tuple` is private
 LL |     let variant_tuple = NonExhaustiveVariants::Tuple(640);
    |                                                ^^^^^ private tuple variant
    |
+  ::: $DIR/auxiliary/variants.rs:5:5
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |     ----------------- the tuple variant is `#[non_exhaustive]`
+   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
@@ -16,6 +21,11 @@ error[E0603]: unit variant `Unit` is private
 LL |     let variant_unit = NonExhaustiveVariants::Unit;
    |                                               ^^^^ private unit variant
    |
+  ::: $DIR/auxiliary/variants.rs:4:5
+   |
+LL |     #[non_exhaustive] Unit,
+   |     ----------------- the unit variant is `#[non_exhaustive]`
+   |
 note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
@@ -28,6 +38,11 @@ error[E0603]: unit variant `Unit` is private
 LL |         NonExhaustiveVariants::Unit => "",
    |                                ^^^^ private unit variant
    |
+  ::: $DIR/auxiliary/variants.rs:4:5
+   |
+LL |     #[non_exhaustive] Unit,
+   |     ----------------- the unit variant is `#[non_exhaustive]`
+   |
 note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
@@ -40,6 +55,11 @@ error[E0603]: tuple variant `Tuple` is private
 LL |         NonExhaustiveVariants::Tuple(fe_tpl) => "",
    |                                ^^^^^ private tuple variant
    |
+  ::: $DIR/auxiliary/variants.rs:5:5
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |     ----------------- the tuple variant is `#[non_exhaustive]`
+   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
@@ -52,6 +72,11 @@ error[E0603]: tuple variant `Tuple` is private
 LL |     if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
    |                                   ^^^^^ private tuple variant
    |
+  ::: $DIR/auxiliary/variants.rs:5:5
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |     ----------------- the tuple variant is `#[non_exhaustive]`
+   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |

From 8ed2dc0bcee8c7ca43d2b6a66c9743cacf8dcddf Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Thu, 6 Apr 2023 16:52:17 +0000
Subject: [PATCH 181/267] Make span a bit better

---
 compiler/rustc_resolve/src/diagnostics.rs     | 14 +++++-
 .../ui/rfc-2008-non-exhaustive/struct.stderr  | 14 ++----
 .../ui/rfc-2008-non-exhaustive/variant.stderr | 45 +++++++------------
 3 files changed, 32 insertions(+), 41 deletions(-)

diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index bb473d62a7bb..0c9d306081eb 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1608,11 +1608,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
         err.span_label(ident.span, &format!("private {}", descr));
 
+        let mut non_exhaustive = None;
+        // If an ADT is foreign and marked as `non_exhaustive`, then that's
+        // probably why we have the privacy error.
+        // Otherwise, point out if the struct has any private fields.
         if let Some(def_id) = res.opt_def_id()
             && !def_id.is_local()
             && let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
         {
-            err.span_label(attr.span, format!("the {nonimport_descr} is `#[non_exhaustive]`"));
+            non_exhaustive = Some(attr.span);
         } else if let Some(span) = ctor_fields_span {
             err.span_label(span, "a constructor is private if any of the fields is private");
             if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
@@ -1662,6 +1666,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             if !first && binding.vis.is_public() {
                 note_span.push_span_label(def_span, "consider importing it directly");
             }
+            // Final step in the import chain, point out if the ADT is `non_exhaustive`
+            // which is probably why this privacy violation occurred.
+            if next_binding.is_none() && let Some(span) = non_exhaustive {
+                note_span.push_span_label(
+                    span,
+                    format!("cannot be constructed because it is `#[non_exhaustive]`"),
+                );
+            }
             err.span_note(note_span, &msg);
         }
 
diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.stderr b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
index 36154fe51a4e..39b1ef1e078c 100644
--- a/tests/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -10,14 +10,11 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
    |                                ^^^^^^^^^^^ private tuple struct constructor
    |
-  ::: $DIR/auxiliary/structs.rs:11:1
-   |
-LL | #[non_exhaustive]
-   | ----------------- the tuple struct constructor is `#[non_exhaustive]`
-   |
 note: the tuple struct constructor `TupleStruct` is defined here
   --> $DIR/auxiliary/structs.rs:12:1
    |
+LL | #[non_exhaustive]
+   | ----------------- cannot be constructed because it is `#[non_exhaustive]`
 LL | pub struct TupleStruct(pub u16, pub u16);
    | ^^^^^^^^^^^^^^^^^^^^^^
 
@@ -27,14 +24,11 @@ error[E0603]: unit struct `UnitStruct` is private
 LL |     let us_explicit = structs::UnitStruct;
    |                                ^^^^^^^^^^ private unit struct
    |
-  ::: $DIR/auxiliary/structs.rs:8:1
-   |
-LL | #[non_exhaustive]
-   | ----------------- the unit struct is `#[non_exhaustive]`
-   |
 note: the unit struct `UnitStruct` is defined here
   --> $DIR/auxiliary/structs.rs:9:1
    |
+LL | #[non_exhaustive]
+   | ----------------- cannot be constructed because it is `#[non_exhaustive]`
 LL | pub struct UnitStruct;
    | ^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.stderr b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
index 551ecb5acf27..4083f57a9cdf 100644
--- a/tests/ui/rfc-2008-non-exhaustive/variant.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -4,16 +4,13 @@ error[E0603]: tuple variant `Tuple` is private
 LL |     let variant_tuple = NonExhaustiveVariants::Tuple(640);
    |                                                ^^^^^ private tuple variant
    |
-  ::: $DIR/auxiliary/variants.rs:5:5
-   |
-LL |     #[non_exhaustive] Tuple(u32),
-   |     ----------------- the tuple variant is `#[non_exhaustive]`
-   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
 LL |     #[non_exhaustive] Tuple(u32),
-   |                       ^^^^^
+   |     ----------------- ^^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:14:47
@@ -21,16 +18,13 @@ error[E0603]: unit variant `Unit` is private
 LL |     let variant_unit = NonExhaustiveVariants::Unit;
    |                                               ^^^^ private unit variant
    |
-  ::: $DIR/auxiliary/variants.rs:4:5
-   |
-LL |     #[non_exhaustive] Unit,
-   |     ----------------- the unit variant is `#[non_exhaustive]`
-   |
 note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
 LL |     #[non_exhaustive] Unit,
-   |                       ^^^^
+   |     ----------------- ^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:18:32
@@ -38,16 +32,13 @@ error[E0603]: unit variant `Unit` is private
 LL |         NonExhaustiveVariants::Unit => "",
    |                                ^^^^ private unit variant
    |
-  ::: $DIR/auxiliary/variants.rs:4:5
-   |
-LL |     #[non_exhaustive] Unit,
-   |     ----------------- the unit variant is `#[non_exhaustive]`
-   |
 note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
 LL |     #[non_exhaustive] Unit,
-   |                       ^^^^
+   |     ----------------- ^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:20:32
@@ -55,16 +46,13 @@ error[E0603]: tuple variant `Tuple` is private
 LL |         NonExhaustiveVariants::Tuple(fe_tpl) => "",
    |                                ^^^^^ private tuple variant
    |
-  ::: $DIR/auxiliary/variants.rs:5:5
-   |
-LL |     #[non_exhaustive] Tuple(u32),
-   |     ----------------- the tuple variant is `#[non_exhaustive]`
-   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
 LL |     #[non_exhaustive] Tuple(u32),
-   |                       ^^^^^
+   |     ----------------- ^^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:26:35
@@ -72,16 +60,13 @@ error[E0603]: tuple variant `Tuple` is private
 LL |     if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
    |                                   ^^^^^ private tuple variant
    |
-  ::: $DIR/auxiliary/variants.rs:5:5
-   |
-LL |     #[non_exhaustive] Tuple(u32),
-   |     ----------------- the tuple variant is `#[non_exhaustive]`
-   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
 LL |     #[non_exhaustive] Tuple(u32),
-   |                       ^^^^^
+   |     ----------------- ^^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0639]: cannot create non-exhaustive variant using struct expression
   --> $DIR/variant.rs:8:26

From b6970d0e260aa33bb1e22ae7df739470ecad19e0 Mon Sep 17 00:00:00 2001
From: Maybe Waffle 
Date: Thu, 6 Apr 2023 17:03:42 +0000
Subject: [PATCH 182/267] Use `FnOnce` for `slice_owned` instead of `Fn`

---
 compiler/rustc_codegen_ssa/src/back/metadata.rs   | 2 +-
 compiler/rustc_data_structures/src/owned_slice.rs | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index c0f263d14781..3e3fcc08bd64 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -37,7 +37,7 @@ pub struct DefaultMetadataLoader;
 
 fn load_metadata_with(
     path: &Path,
-    f: impl for<'a> Fn(&'a [u8]) -> Result<&'a [u8], String>,
+    f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>,
 ) -> Result {
     let file =
         File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?;
diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs
index 146f06a1c69e..e35a93f2a1dc 100644
--- a/compiler/rustc_data_structures/src/owned_slice.rs
+++ b/compiler/rustc_data_structures/src/owned_slice.rs
@@ -59,7 +59,7 @@ pub struct OwnedSlice {
 pub fn slice_owned(owner: O, slicer: F) -> OwnedSlice
 where
     O: Send + Sync + 'static,
-    F: Fn(&O) -> &[u8],
+    F: FnOnce(&O) -> &[u8],
 {
     try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok()
 }
@@ -70,7 +70,7 @@ where
 pub fn try_slice_owned(owner: O, slicer: F) -> Result
 where
     O: Send + Sync + 'static,
-    F: Fn(&O) -> Result<&[u8], E>,
+    F: FnOnce(&O) -> Result<&[u8], E>,
 {
     // We box the owner of the bytes, so it doesn't move.
     //

From 925a3040c7f0a84885a91ba8919d1f6d7516302a Mon Sep 17 00:00:00 2001
From: ozkanonur 
Date: Thu, 6 Apr 2023 20:16:51 +0300
Subject: [PATCH 183/267] improve/extend `detect_src_and_out` test

Signed-off-by: ozkanonur 
---
 src/bootstrap/config/tests.rs | 65 ++++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 21 deletions(-)

diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index 16dc8c63abc9..4a9ab158e6ca 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -33,35 +33,58 @@ fn download_ci_llvm() {
     ));
 }
 
+// FIXME(ozkanonur): extend scope of the test
+// refs:
+//   - https://github.com/rust-lang/rust/issues/109120
+//   - https://github.com/rust-lang/rust/pull/109162#issuecomment-1496782487
 #[test]
 fn detect_src_and_out() {
-    let cfg = parse("");
+    fn test(cfg: Config, build_dir: Option<&str>) {
+        // This will bring absolute form of `src/bootstrap` path
+        let current_dir = std::env::current_dir().unwrap();
 
-    // This will bring absolute form of `src/bootstrap` path
-    let current_dir = std::env::current_dir().unwrap();
+        // get `src` by moving into project root path
+        let expected_src = current_dir.ancestors().nth(2).unwrap();
+        assert_eq!(&cfg.src, expected_src);
 
-    // get `src` by moving into project root path
-    let expected_src = current_dir.ancestors().nth(2).unwrap();
+        // Sanity check for `src`
+        let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
+        let expected_src = manifest_dir.ancestors().nth(2).unwrap();
+        assert_eq!(&cfg.src, expected_src);
 
-    assert_eq!(&cfg.src, expected_src);
+        // test if build-dir was manually given in config.toml
+        if let Some(custom_build_dir) = build_dir {
+            assert_eq!(&cfg.out, Path::new(custom_build_dir));
+        }
+        // test the native bootstrap way
+        else {
+            // This should bring output path of bootstrap in absolute form
+            let cargo_target_dir = env::var_os("CARGO_TARGET_DIR").expect(
+                "CARGO_TARGET_DIR must been provided for the test environment from bootstrap",
+            );
 
-    // This should bring output path of bootstrap in absolute form
-    let cargo_target_dir = env::var_os("CARGO_TARGET_DIR")
-        .expect("CARGO_TARGET_DIR must been provided for the test environment from bootstrap");
+            // Move to `build` from `build/bootstrap`
+            let expected_out = Path::new(&cargo_target_dir).parent().unwrap();
+            assert_eq!(&cfg.out, expected_out);
 
-    // Move to `build` from `build/bootstrap`
-    let expected_out = Path::new(&cargo_target_dir).parent().unwrap();
-    assert_eq!(&cfg.out, expected_out);
+            let args: Vec = env::args().collect();
 
-    let args: Vec = env::args().collect();
+            // Another test for `out` as a sanity check
+            //
+            // This will bring something similar to:
+            //     `{build-dir}/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804`
+            // `{build-dir}` can be anywhere, not just in the rust project directory.
+            let dep = Path::new(args.first().unwrap());
+            let expected_out = dep.ancestors().nth(4).unwrap();
 
-    // Another test for `out` as a sanity check
-    //
-    // This will bring something similar to:
-    //     `{config_toml_place}/build/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804`
-    // `{config_toml_place}` can be anywhere, not just in the rust project directory.
-    let dep = Path::new(args.first().unwrap());
-    let expected_out = dep.ancestors().nth(4).unwrap();
+            assert_eq!(&cfg.out, expected_out);
+        }
+    }
 
-    assert_eq!(&cfg.out, expected_out);
+    test(parse(""), None);
+
+    {
+        let build_dir = if cfg!(windows) { Some("C:\\tmp") } else { Some("/tmp") };
+        test(parse("build.build-dir = \"/tmp\""), build_dir);
+    }
 }

From e0e39caf842579230bc73d2d32c1e293ca55efcb Mon Sep 17 00:00:00 2001
From: Maybe Waffle 
Date: Thu, 6 Apr 2023 17:33:55 +0000
Subject: [PATCH 184/267] Add basic tests for `OwnedSlice`

---
 .../rustc_data_structures/src/owned_slice.rs  |  3 +
 .../src/owned_slice/tests.rs                  | 68 +++++++++++++++++++
 2 files changed, 71 insertions(+)
 create mode 100644 compiler/rustc_data_structures/src/owned_slice/tests.rs

diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs
index e35a93f2a1dc..c0a3cb071943 100644
--- a/compiler/rustc_data_structures/src/owned_slice.rs
+++ b/compiler/rustc_data_structures/src/owned_slice.rs
@@ -111,3 +111,6 @@ unsafe impl Send for OwnedSlice {}
 
 // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box)`, which is `Sync`
 unsafe impl Sync for OwnedSlice {}
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/owned_slice/tests.rs b/compiler/rustc_data_structures/src/owned_slice/tests.rs
new file mode 100644
index 000000000000..fe4173f422ad
--- /dev/null
+++ b/compiler/rustc_data_structures/src/owned_slice/tests.rs
@@ -0,0 +1,68 @@
+use std::{cell::Cell, ops::Deref, rc::Rc};
+
+use crate::{
+    owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
+    OnDrop,
+};
+
+#[test]
+fn smoke() {
+    let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
+
+    assert_eq!(&*slice, [1, 2, 3, 4, 5, 6]);
+}
+
+#[test]
+fn static_storage() {
+    let slice = slice_owned(Box::new(String::from("what")), |_| b"bytes boo");
+
+    assert_eq!(&*slice, b"bytes boo");
+}
+
+#[test]
+fn slice_the_slice() {
+    let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
+    let slice = slice_owned(slice, |s| &s[1..][..4]);
+    let slice = slice_owned(slice, |s| s);
+    let slice = slice_owned(slice, |s| &s[1..]);
+
+    assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
+}
+
+#[test]
+fn try_and_fail() {
+    let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(()));
+
+    assert!(res.is_err());
+}
+
+#[test]
+fn boxed() {
+    // It's important that we don't cause UB because of `Box`'es uniqueness
+
+    let boxed: Box<[u8]> = vec![1, 1, 2, 3, 5, 8, 13, 21].into_boxed_slice();
+    let slice = slice_owned(boxed, Deref::deref);
+
+    assert_eq!(&*slice, [1, 1, 2, 3, 5, 8, 13, 21]);
+}
+
+#[test]
+fn drop() {
+    let flag = Rc::new(Cell::new(false));
+    let flag_prime = Rc::clone(&flag);
+    let d = OnDrop(move || flag_prime.set(true));
+
+    let slice = slice_owned(d, |_| &[]);
+
+    assert_eq!(flag.get(), false);
+
+    std::mem::drop(slice);
+
+    assert_eq!(flag.get(), true);
+}
+
+#[test]
+fn send_sync() {
+    crate::sync::assert_send::();
+    crate::sync::assert_sync::();
+}

From 2733c29bb1a385779c1d74dbce96180799e15e56 Mon Sep 17 00:00:00 2001
From: Maybe Waffle 
Date: Thu, 6 Apr 2023 18:05:59 +0000
Subject: [PATCH 185/267] Support multithreaded mode in `OwnedSlice` tests

---
 .../src/owned_slice/tests.rs                  | 22 ++++++++++++-------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_data_structures/src/owned_slice/tests.rs b/compiler/rustc_data_structures/src/owned_slice/tests.rs
index fe4173f422ad..e715fb55362d 100644
--- a/compiler/rustc_data_structures/src/owned_slice/tests.rs
+++ b/compiler/rustc_data_structures/src/owned_slice/tests.rs
@@ -1,4 +1,10 @@
-use std::{cell::Cell, ops::Deref, rc::Rc};
+use std::{
+    ops::Deref,
+    sync::{
+        atomic::{self, AtomicBool},
+        Arc,
+    },
+};
 
 use crate::{
     owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
@@ -47,18 +53,18 @@ fn boxed() {
 }
 
 #[test]
-fn drop() {
-    let flag = Rc::new(Cell::new(false));
-    let flag_prime = Rc::clone(&flag);
-    let d = OnDrop(move || flag_prime.set(true));
+fn drop_drops() {
+    let flag = Arc::new(AtomicBool::new(false));
+    let flag_prime = Arc::clone(&flag);
+    let d = OnDrop(move || flag_prime.store(true, atomic::Ordering::Relaxed));
 
     let slice = slice_owned(d, |_| &[]);
 
-    assert_eq!(flag.get(), false);
+    assert_eq!(flag.load(atomic::Ordering::Relaxed), false);
 
-    std::mem::drop(slice);
+    drop(slice);
 
-    assert_eq!(flag.get(), true);
+    assert_eq!(flag.load(atomic::Ordering::Relaxed), true);
 }
 
 #[test]

From 529ceeeefc7b5f77834f707362044fd48b6247fd Mon Sep 17 00:00:00 2001
From: Guillaume Gomez 
Date: Thu, 6 Apr 2023 20:26:27 +0200
Subject: [PATCH 186/267] Run collapsed GUI test in mobile mode as well

---
 tests/rustdoc-gui/go-to-collapsed-elem.goml | 35 ++++++++++++++++-----
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/tests/rustdoc-gui/go-to-collapsed-elem.goml b/tests/rustdoc-gui/go-to-collapsed-elem.goml
index 279048e37c1f..ec4231252364 100644
--- a/tests/rustdoc-gui/go-to-collapsed-elem.goml
+++ b/tests/rustdoc-gui/go-to-collapsed-elem.goml
@@ -9,13 +9,32 @@ property: ("#implementations-list .implementors-toggle", {"open": "false"})
 click: "//*[@class='sidebar']//a[@href='#method.must_use']"
 assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
 
-// Now we do the same through search result.
-// First we reload the page without the anchor in the URL.
+define-function: ("collapsed-from-search", (), block {
+    // Now we do the same through search result.
+    // First we reload the page without the anchor in the URL.
+    goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+    // Then we collapse the section again...
+    property: ("#implementations-list .implementors-toggle", {"open": "false"})
+    // Then we run the search.
+    write: (".search-input", "foo::must_use")
+    wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+    click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+    assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+})
+
+call-function: ("collapsed-from-search", {})
+
+// Now running the same check but with mobile.
+size: (600, 600)
 goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-// Then we collapse the section again...
-property: ("#implementations-list .implementors-toggle", {"open": "false"})
-// Then we run the search.
-write: (".search-input", "foo::must_use")
-wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
-click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+// We check that the implementors block is expanded.
 assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+// We now collapse the implementors block.
+property: ("#implementations-list .implementors-toggle", {"open": "false"})
+// First we expand the mobile menu.
+click: ".sidebar-menu-toggle"
+// Then we click on the link to the method to ensure it'll expand the implementors block.
+click: "//*[@class='sidebar shown']//a[@href='#method.must_use']"
+assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+
+call-function: ("collapsed-from-search", {})

From 454bca514aab74a8c3c746908cac2d9c61300941 Mon Sep 17 00:00:00 2001
From: Scott McMurray 
Date: Thu, 6 Apr 2023 13:53:10 -0700
Subject: [PATCH 187/267] Check `CastKind::Transmute` sizes in a better way

Fixes #110005
---
 compiler/rustc_codegen_ssa/src/mir/operand.rs | 25 +++++++
 compiler/rustc_codegen_ssa/src/mir/rvalue.rs  | 67 +++++++++--------
 tests/codegen/intrinsics/transmute.rs         | 74 ++++++++++++++++++-
 3 files changed, 134 insertions(+), 32 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index ddef4aaee3ba..b37797fef4ce 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -259,6 +259,31 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
 }
 
 impl<'a, 'tcx, V: CodegenObject> OperandValue {
+    /// Returns an `OperandValue` that's generally UB to use in any way.
+    ///
+    /// Depending on the `layout`, returns an `Immediate` or `Pair` containing
+    /// poison value(s), or a `Ref` containing a poison pointer.
+    ///
+    /// Supports sized types only.
+    pub fn poison>(
+        bx: &mut Bx,
+        layout: TyAndLayout<'tcx>,
+    ) -> OperandValue {
+        assert!(layout.is_sized());
+        if bx.cx().is_backend_immediate(layout) {
+            let ibty = bx.cx().immediate_backend_type(layout);
+            OperandValue::Immediate(bx.const_poison(ibty))
+        } else if bx.cx().is_backend_scalar_pair(layout) {
+            let ibty0 = bx.cx().scalar_pair_element_backend_type(layout, 0, true);
+            let ibty1 = bx.cx().scalar_pair_element_backend_type(layout, 1, true);
+            OperandValue::Pair(bx.const_poison(ibty0), bx.const_poison(ibty1))
+        } else {
+            let bty = bx.cx().backend_type(layout);
+            let ptr_bty = bx.cx().type_ptr_to(bty);
+            OperandValue::Ref(bx.const_poison(ptr_bty), None, layout.align.abi)
+        }
+    }
+
     pub fn store>(
         self,
         bx: &mut Bx,
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 400512fe4e9a..6e4c0be12f08 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -158,17 +158,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         debug_assert!(src.layout.is_sized());
         debug_assert!(dst.layout.is_sized());
 
-        if src.layout.size != dst.layout.size
-            || src.layout.abi.is_uninhabited()
-            || dst.layout.abi.is_uninhabited()
-        {
-            // In all of these cases it's UB to run this transmute, but that's
-            // known statically so might as well trap for it, rather than just
-            // making it unreachable.
-            bx.abort();
-            return;
-        }
-
         if let Some(val) = self.codegen_transmute_operand(bx, src, dst.layout) {
             val.store(bx, dst);
             return;
@@ -202,8 +191,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         operand: OperandRef<'tcx, Bx::Value>,
         cast: TyAndLayout<'tcx>,
     ) -> Option> {
-        // Callers already checked that the layout sizes match
-        debug_assert_eq!(operand.layout.size, cast.size);
+        // Check for transmutes that are always UB.
+        if operand.layout.size != cast.size
+            || operand.layout.abi.is_uninhabited()
+            || cast.abi.is_uninhabited()
+        {
+            if !operand.layout.abi.is_uninhabited() {
+                // Since this is known statically and the input could have existed
+                // without already having hit UB, might as well trap for it.
+                bx.abort();
+            }
+
+            // Because this transmute is UB, return something easy to generate,
+            // since it's fine that later uses of the value are probably UB.
+            return Some(OperandValue::poison(bx, cast));
+        }
 
         let operand_kind = self.value_kind(operand.layout);
         let cast_kind = self.value_kind(cast);
@@ -221,11 +223,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let OperandValueKind::Immediate(in_scalar) = operand_kind else {
                     bug!("Found {operand_kind:?} for operand {operand:?}");
                 };
-                if let OperandValueKind::Immediate(out_scalar) = cast_kind {
+                if let OperandValueKind::Immediate(out_scalar) = cast_kind
+                    && in_scalar.size(self.cx) == out_scalar.size(self.cx)
+                {
                     let cast_bty = bx.backend_type(cast);
-                    Some(OperandValue::Immediate(Self::transmute_immediate(
-                        bx, imm, in_scalar, out_scalar, cast_bty,
-                    )))
+                    Some(OperandValue::Immediate(
+                        self.transmute_immediate(bx, imm, in_scalar, out_scalar, cast_bty),
+                    ))
                 } else {
                     None
                 }
@@ -234,12 +238,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let OperandValueKind::Pair(in_a, in_b) = operand_kind else {
                     bug!("Found {operand_kind:?} for operand {operand:?}");
                 };
-                if let OperandValueKind::Pair(out_a, out_b) = cast_kind {
+                if let OperandValueKind::Pair(out_a, out_b) = cast_kind
+                    && in_a.size(self.cx) == out_a.size(self.cx)
+                    && in_b.size(self.cx) == out_b.size(self.cx)
+                {
                     let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false);
                     let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false);
                     Some(OperandValue::Pair(
-                        Self::transmute_immediate(bx, imm_a, in_a, out_a, out_a_ibty),
-                        Self::transmute_immediate(bx, imm_b, in_b, out_b, out_b_ibty),
+                        self.transmute_immediate(bx, imm_a, in_a, out_a, out_a_ibty),
+                        self.transmute_immediate(bx, imm_b, in_b, out_b, out_b_ibty),
                     ))
                 } else {
                     None
@@ -254,12 +261,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     /// `to_backend_ty` must be the *non*-immediate backend type (so it will be
     /// `i8`, not `i1`, for `bool`-like types.)
     fn transmute_immediate(
+        &self,
         bx: &mut Bx,
         mut imm: Bx::Value,
         from_scalar: abi::Scalar,
         to_scalar: abi::Scalar,
         to_backend_ty: Bx::Type,
     ) -> Bx::Value {
+        debug_assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));
+
         use abi::Primitive::*;
         imm = bx.from_immediate(imm);
         imm = match (from_scalar.primitive(), to_scalar.primitive()) {
@@ -831,14 +841,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let operand_ty = operand.ty(self.mir, self.cx.tcx());
                 let cast_layout = self.cx.layout_of(self.monomorphize(cast_ty));
                 let operand_layout = self.cx.layout_of(self.monomorphize(operand_ty));
-                if operand_layout.size != cast_layout.size
-                    || operand_layout.abi.is_uninhabited()
-                    || cast_layout.abi.is_uninhabited()
-                {
-                    // Send UB cases to the full form so the operand version can
-                    // `bitcast` without worrying about malformed IR.
-                    return false;
-                }
 
                 match (self.value_kind(operand_layout), self.value_kind(cast_layout)) {
                     // Can always load from a pointer as needed
@@ -847,9 +849,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     // Need to generate an `alloc` to get a pointer from an immediate
                     (OperandValueKind::Immediate(..) | OperandValueKind::Pair(..), OperandValueKind::Ref) => false,
 
-                    // When we have scalar immediates, we can convert them as needed
-                    (OperandValueKind::Immediate(..), OperandValueKind::Immediate(..)) |
-                    (OperandValueKind::Pair(..), OperandValueKind::Pair(..)) => true,
+                    // When we have scalar immediates, we can only convert things
+                    // where the sizes match, to avoid endianness questions.
+                    (OperandValueKind::Immediate(a), OperandValueKind::Immediate(b)) =>
+                        a.size(self.cx) == b.size(self.cx),
+                    (OperandValueKind::Pair(a0, a1), OperandValueKind::Pair(b0, b1)) =>
+                        a0.size(self.cx) == b0.size(self.cx) && a1.size(self.cx) == b1.size(self.cx),
 
                     // Send mixings between scalars and pairs through the memory route
                     // FIXME: Maybe this could use insertvalue/extractvalue instead?
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
index 7ad0e62213cb..c2295ca9a0c3 100644
--- a/tests/codegen/intrinsics/transmute.rs
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -54,6 +54,32 @@ pub unsafe fn check_smaller_size(x: u32) -> u16 {
     }
 }
 
+// CHECK-LABEL: @check_smaller_array(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
+    // CHECK: call void @llvm.trap
+    mir!{
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_bigger_array(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
+    // CHECK: call void @llvm.trap
+    mir!{
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
 // CHECK-LABEL: @check_to_uninhabited(
 #[no_mangle]
 #[custom_mir(dialect = "runtime", phase = "initial")]
@@ -71,7 +97,7 @@ pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
 #[no_mangle]
 #[custom_mir(dialect = "runtime", phase = "initial")]
 pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
-    // CHECK: call void @llvm.trap
+    // CHECK: ret i16 poison
     mir!{
         {
             RET = CastTransmute(x);
@@ -301,3 +327,49 @@ pub unsafe fn check_pair_to_array(x: (i64, u64)) -> [u8; 16] {
     // CHECK: store i64 %x.1, ptr %{{.+}}, align 1
     transmute(x)
 }
+
+// CHECK-LABEL: @check_heterogeneous_integer_pair(
+#[no_mangle]
+pub unsafe fn check_heterogeneous_integer_pair(x: (i32, bool)) -> (bool, u32) {
+    // CHECK: store i32 %x.0
+    // CHECK: %[[WIDER:.+]] = zext i1 %x.1 to i8
+    // CHECK: store i8 %[[WIDER]]
+
+    // CHECK: %[[BYTE:.+]] = load i8
+    // CHECK: trunc i8 %[[BYTE:.+]] to i1
+    // CHECK: load i32
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_heterogeneous_float_pair(
+#[no_mangle]
+pub unsafe fn check_heterogeneous_float_pair(x: (f64, f32)) -> (f32, f64) {
+    // CHECK: store double %x.0
+    // CHECK: store float %x.1
+    // CHECK: %[[A:.+]] = load float
+    // CHECK: %[[B:.+]] = load double
+    // CHECK: %[[P:.+]] = insertvalue { float, double } poison, float %[[A]], 0
+    // CHECK: insertvalue { float, double } %[[P]], double %[[B]], 1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_issue_110005(
+#[no_mangle]
+pub unsafe fn check_issue_110005(x: (usize, bool)) -> Option> {
+    // CHECK: store i64 %x.0
+    // CHECK: %[[WIDER:.+]] = zext i1 %x.1 to i8
+    // CHECK: store i8 %[[WIDER]]
+    // CHECK: load ptr
+    // CHECK: load i64
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_pair_to_dst_ref(
+#[no_mangle]
+pub unsafe fn check_pair_to_dst_ref<'a>(x: (usize, usize)) -> &'a [u8] {
+    // CHECK: %0 = inttoptr i64 %x.0 to ptr
+    // CHECK: %1 = insertvalue { ptr, i64 } poison, ptr %0, 0
+    // CHECK: %2 = insertvalue { ptr, i64 } %1, i64 %x.1, 1
+    // CHECK: ret { ptr, i64 } %2
+    transmute(x)
+}

From 9dbf20ef27b56c0bff35366689861ebbe5dfb7e5 Mon Sep 17 00:00:00 2001
From: Ezra Shaw 
Date: Fri, 7 Apr 2023 08:54:13 +1200
Subject: [PATCH 188/267] fix: fix regression in #109203

---
 .../rustc_parse/src/parser/diagnostics.rs     |  4 ++--
 tests/ui/parser/issues/issue-110014.rs        |  3 +++
 tests/ui/parser/issues/issue-110014.stderr    | 19 +++++++++++++++++++
 3 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 tests/ui/parser/issues/issue-110014.rs
 create mode 100644 tests/ui/parser/issues/issue-110014.stderr

diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 5210b8fe69d6..e03ce5d71205 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -423,11 +423,11 @@ impl<'a> Parser<'a> {
         if let token::Literal(Lit {
             kind: token::LitKind::Integer | token::LitKind::Float,
             symbol,
-            suffix,
+            suffix: Some(suffix), // no suffix makes it a valid literal
         }) = self.token.kind
             && rustc_ast::MetaItemLit::from_token(&self.token).is_none()
         {
-            Some((symbol.as_str().len(), suffix.unwrap()))
+            Some((symbol.as_str().len(), suffix))
         } else {
             None
         }
diff --git a/tests/ui/parser/issues/issue-110014.rs b/tests/ui/parser/issues/issue-110014.rs
new file mode 100644
index 000000000000..69d8f402bb62
--- /dev/null
+++ b/tests/ui/parser/issues/issue-110014.rs
@@ -0,0 +1,3 @@
+fn`2222222222222222222222222222222222222222() {}
+//~^ ERROR unknown start of token: `
+//~^^ ERROR expected identifier, found `2222222222222222222222222222222222222222`
diff --git a/tests/ui/parser/issues/issue-110014.stderr b/tests/ui/parser/issues/issue-110014.stderr
new file mode 100644
index 000000000000..7f1dd592e123
--- /dev/null
+++ b/tests/ui/parser/issues/issue-110014.stderr
@@ -0,0 +1,19 @@
+error: unknown start of token: `
+  --> $DIR/issue-110014.rs:1:3
+   |
+LL | fn`2222222222222222222222222222222222222222() {}
+   |   ^
+   |
+help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not
+   |
+LL | fn'2222222222222222222222222222222222222222() {}
+   |   ~
+
+error: expected identifier, found `2222222222222222222222222222222222222222`
+  --> $DIR/issue-110014.rs:1:4
+   |
+LL | fn`2222222222222222222222222222222222222222() {}
+   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier
+
+error: aborting due to 2 previous errors
+

From 443928f7e33666f83711c768ef2968090c85bc7f Mon Sep 17 00:00:00 2001
From: Jonas Platte 
Date: Thu, 6 Apr 2023 21:54:05 +0200
Subject: [PATCH 189/267] Stabilize is_some_and

---
 compiler/rustc_builtin_macros/src/lib.rs | 1 -
 compiler/rustc_const_eval/src/lib.rs     | 1 -
 compiler/rustc_hir_analysis/src/lib.rs   | 1 -
 library/core/src/option.rs               | 4 +---
 library/core/src/result.rs               | 7 ++-----
 library/std/src/lib.rs                   | 1 -
 src/tools/miri/src/lib.rs                | 1 -
 7 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 71177b8789ba..7697b592e33a 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -7,7 +7,6 @@
 #![feature(box_patterns)]
 #![feature(decl_macro)]
 #![feature(if_let_guard)]
-#![feature(is_some_and)]
 #![feature(is_sorted)]
 #![feature(let_chains)]
 #![feature(proc_macro_internals)]
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 16b83af91ac9..5ab389d04c7e 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -20,7 +20,6 @@ Rust MIR: a lowered representation of Rust.
 #![feature(try_blocks)]
 #![feature(yeet_expr)]
 #![feature(if_let_guard)]
-#![feature(is_some_and)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 2a9025d60aba..27e56180349e 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -70,7 +70,6 @@ This API is completely unstable and subject to change.
 #![feature(lazy_cell)]
 #![feature(slice_partition_dedup)]
 #![feature(try_blocks)]
-#![feature(is_some_and)]
 #![feature(type_alias_impl_trait)]
 #![recursion_limit = "256"]
 
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index fcf9707b74d4..057053297cd2 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -605,8 +605,6 @@ impl Option {
     /// # Examples
     ///
     /// ```
-    /// #![feature(is_some_and)]
-    ///
     /// let x: Option = Some(2);
     /// assert_eq!(x.is_some_and(|x| x > 1), true);
     ///
@@ -618,7 +616,7 @@ impl Option {
     /// ```
     #[must_use]
     #[inline]
-    #[unstable(feature = "is_some_and", issue = "93050")]
+    #[stable(feature = "is_some_and", since = "CURRENT_RUSTC_VERSION")]
     pub fn is_some_and(self, f: impl FnOnce(T) -> bool) -> bool {
         match self {
             None => false,
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 76d9b0385d0f..241602c0e18f 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -545,8 +545,6 @@ impl Result {
     /// # Examples
     ///
     /// ```
-    /// #![feature(is_some_and)]
-    ///
     /// let x: Result = Ok(2);
     /// assert_eq!(x.is_ok_and(|x| x > 1), true);
     ///
@@ -558,7 +556,7 @@ impl Result {
     /// ```
     #[must_use]
     #[inline]
-    #[unstable(feature = "is_some_and", issue = "93050")]
+    #[stable(feature = "is_some_and", since = "CURRENT_RUSTC_VERSION")]
     pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool {
         match self {
             Err(_) => false,
@@ -590,7 +588,6 @@ impl Result {
     /// # Examples
     ///
     /// ```
-    /// #![feature(is_some_and)]
     /// use std::io::{Error, ErrorKind};
     ///
     /// let x: Result = Err(Error::new(ErrorKind::NotFound, "!"));
@@ -604,7 +601,7 @@ impl Result {
     /// ```
     #[must_use]
     #[inline]
-    #[unstable(feature = "is_some_and", issue = "93050")]
+    #[stable(feature = "is_some_and", since = "CURRENT_RUSTC_VERSION")]
     pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool {
         match self {
             Ok(_) => false,
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 8c118b95b0a7..736b3c0497c4 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -289,7 +289,6 @@
 #![feature(hashmap_internals)]
 #![feature(ip)]
 #![feature(ip_in_core)]
-#![feature(is_some_and)]
 #![feature(maybe_uninit_slice)]
 #![feature(maybe_uninit_write_slice)]
 #![feature(panic_can_unwind)]
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 01d0f01d319d..fb4e59acd001 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -5,7 +5,6 @@
 #![feature(io_error_more)]
 #![feature(variant_count)]
 #![feature(yeet_expr)]
-#![feature(is_some_and)]
 #![feature(nonzero_ops)]
 #![feature(local_key_cell_methods)]
 #![feature(is_terminal)]

From 1499a6faad8a64c87e4837572cbcea959ec5c006 Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Thu, 6 Apr 2023 22:19:22 +0100
Subject: [PATCH 190/267] UnwindAction::Terminate edge is also critical edge

---
 compiler/rustc_mir_transform/src/add_call_guards.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index ea7ccb512e09..e1e354efa1c4 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -53,7 +53,8 @@ impl AddCallGuards {
                     kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. },
                     source_info,
                 }) if pred_count[*destination] > 1
-                    && (matches!(unwind, UnwindAction::Cleanup(_)) || self == &AllCallEdges) =>
+                    && (matches!(unwind, UnwindAction::Cleanup(_) | UnwindAction::Terminate)
+                        || self == &AllCallEdges) =>
                 {
                     // It's a critical edge, break it
                     let call_guard = BasicBlockData {

From 815f5bbcc53dbb40c11127f26080e0ad9b7dc935 Mon Sep 17 00:00:00 2001
From: Michael Howell 
Date: Thu, 6 Apr 2023 14:53:29 -0700
Subject: [PATCH 191/267] rustdoc: clean up JS

* Stop checking `func` in `onEach`. It's always hard-coded right
  at the call site, so there's no point.
* Use the ternary operator in a few spots where it makes sense.
* No point in making `onEach` store `arr.length` in a variable if
  it's only used once anyway.
---
 src/librustdoc/html/static/js/main.js     | 10 ++--------
 src/librustdoc/html/static/js/settings.js |  8 ++------
 src/librustdoc/html/static/js/storage.js  | 19 +++++--------------
 3 files changed, 9 insertions(+), 28 deletions(-)

diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 45c0360a49ea..56ee4c1510e8 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -332,13 +332,7 @@ function preLoadCss(cssUrl) {
     };
 
     function getPageId() {
-        if (window.location.hash) {
-            const tmp = window.location.hash.replace(/^#/, "");
-            if (tmp.length > 0) {
-                return tmp;
-            }
-        }
-        return null;
+        return window.location.hash.replace(/^#/, "");
     }
 
     const toggleAllDocsId = "toggle-all-docs";
@@ -707,7 +701,7 @@ function preLoadCss(cssUrl) {
         });
 
         const pageId = getPageId();
-        if (pageId !== null) {
+        if (pageId !== "") {
             expandSection(pageId);
         }
     }());
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 1cd552e7f25b..ebbe6c1ca9a2 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -86,12 +86,8 @@
             if (settingId === "theme") {
                 const useSystem = getSettingValue("use-system-theme");
                 if (useSystem === "true" || settingValue === null) {
-                    if (useSystem !== "false") {
-                        settingValue = "system preference";
-                    } else {
-                        // This is the default theme.
-                        settingValue = "light";
-                    }
+                    // "light" is the default theme
+                    settingValue = useSystem === "false" ? "light" : "system preference";
                 }
             }
             if (settingValue !== null && settingValue !== "null") {
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 8d82b5b78edb..9ce09cd502e6 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -53,10 +53,9 @@ function removeClass(elem, className) {
  * @param {boolean}     [reversed] - Whether to iterate in reverse
  */
 function onEach(arr, func, reversed) {
-    if (arr && arr.length > 0 && func) {
+    if (arr && arr.length > 0) {
         if (reversed) {
-            const length = arr.length;
-            for (let i = length - 1; i >= 0; --i) {
+            for (let i = arr.length - 1; i >= 0; --i) {
                 if (func(arr[i])) {
                     return true;
                 }
@@ -150,26 +149,18 @@ const updateTheme = (function() {
      * … dictates that it should be.
      */
     function updateTheme() {
-        const use = (theme, saveTheme) => {
-            switchTheme(theme, saveTheme);
-        };
-
         // maybe the user has disabled the setting in the meantime!
         if (getSettingValue("use-system-theme") !== "false") {
             const lightTheme = getSettingValue("preferred-light-theme") || "light";
             const darkTheme = getSettingValue("preferred-dark-theme") || "dark";
 
-            if (mql.matches) {
-                use(darkTheme, true);
-            } else {
-                // prefers a light theme, or has no preference
-                use(lightTheme, true);
-            }
+            // use light theme if user prefers it, or has no preference
+            switchTheme(mql.matches ? darkTheme : lightTheme, true);
             // note: we save the theme so that it doesn't suddenly change when
             // the user disables "use-system-theme" and reloads the page or
             // navigates to another page
         } else {
-            use(getSettingValue("theme"), false);
+            switchTheme(getSettingValue("theme"), false);
         }
     }
 

From 758bedc10454b1d101613f4b363fe54c7a405b00 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Thu, 6 Apr 2023 23:11:19 +0000
Subject: [PATCH 192/267] Make elaborator generic

---
 .../src/check/compare_impl_item.rs            |   4 +-
 .../rustc_hir_analysis/src/check/wfcheck.rs   |   2 +-
 .../src/collect/item_bounds.rs                |   2 +-
 .../src/impl_wf_check/min_specialization.rs   |  12 +-
 compiler/rustc_hir_typeck/src/closure.rs      |   2 +-
 .../rustc_hir_typeck/src/method/confirm.rs    |   2 +-
 compiler/rustc_hir_typeck/src/method/probe.rs |   3 +-
 compiler/rustc_infer/src/traits/util.rs       | 209 ++++++++++--------
 compiler/rustc_lint/src/unused.rs             |  33 ++-
 .../rustc_mir_transform/src/const_prop.rs     |   5 +-
 .../src/const_prop_lint.rs                    |   5 +-
 .../src/solve/assembly.rs                     |   4 +-
 .../src/traits/auto_trait.rs                  |   8 +-
 .../src/traits/coherence.rs                   |   2 +-
 .../src/traits/error_reporting/ambiguity.rs   |   4 +-
 .../src/traits/error_reporting/mod.rs         |   2 +-
 .../rustc_trait_selection/src/traits/mod.rs   |   7 +-
 .../src/traits/object_safety.rs               |   4 +-
 .../rustc_trait_selection/src/traits/wf.rs    |   4 +-
 .../src/needless_pass_by_value.rs             |   2 +-
 src/tools/clippy/clippy_utils/src/lib.rs      |   2 +-
 21 files changed, 163 insertions(+), 155 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 2d509a114ad2..f6c2004c4a67 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -2034,7 +2034,7 @@ pub(super) fn check_type_bounds<'tcx>(
         ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
     };
 
-    let obligations = tcx
+    let obligations: Vec<_> = tcx
         .bound_explicit_item_bounds(trait_ty.def_id)
         .subst_iter_copied(tcx, rebased_substs)
         .map(|(concrete_ty_bound, span)| {
@@ -2044,7 +2044,7 @@ pub(super) fn check_type_bounds<'tcx>(
         .collect();
     debug!("check_type_bounds: item_bounds={:?}", obligations);
 
-    for mut obligation in util::elaborate_obligations(tcx, obligations) {
+    for mut obligation in util::elaborate(tcx, obligations) {
         let normalized_predicate =
             ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
         debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 24cc58ee3449..c03621fcfb22 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1908,7 +1908,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
 
         let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied();
         // Check elaborated bounds.
-        let implied_obligations = traits::elaborate_predicates_with_span(tcx, predicates_with_span);
+        let implied_obligations = traits::elaborate(tcx, predicates_with_span);
 
         for (pred, obligation_span) in implied_obligations {
             // We lower empty bounds like `Vec:` as
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index d2e45c28658b..2e56d24638cd 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -130,7 +130,7 @@ pub(super) fn item_bounds(
     tcx: TyCtxt<'_>,
     def_id: DefId,
 ) -> ty::EarlyBinder<&'_ ty::List>> {
-    let bounds = tcx.mk_predicates_from_iter(util::elaborate_predicates(
+    let bounds = tcx.mk_predicates_from_iter(util::elaborate(
         tcx,
         tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
     ));
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index b5bae5788f6b..35785e81ff49 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -318,15 +318,14 @@ fn check_predicates<'tcx>(
     span: Span,
 ) {
     let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
-    let impl1_predicates: Vec<_> =
-        traits::elaborate_predicates_with_span(tcx, instantiated.into_iter()).collect();
+    let impl1_predicates: Vec<_> = traits::elaborate(tcx, instantiated.into_iter()).collect();
 
     let mut impl2_predicates = if impl2_node.is_from_trait() {
         // Always applicable traits have to be always applicable without any
         // assumptions.
         Vec::new()
     } else {
-        traits::elaborate_predicates(
+        traits::elaborate(
             tcx,
             tcx.predicates_of(impl2_node.def_id())
                 .instantiate(tcx, impl2_substs)
@@ -371,11 +370,10 @@ fn check_predicates<'tcx>(
                 .unwrap();
 
         assert!(!obligations.needs_infer());
-        impl2_predicates.extend(
-            traits::elaborate_obligations(tcx, obligations).map(|obligation| obligation.predicate),
-        )
+        impl2_predicates
+            .extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate))
     }
-    impl2_predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits));
+    impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits));
 
     for (predicate, span) in impl1_predicates {
         if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) {
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 47a8b0801664..15eec42d7864 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -204,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut expected_sig = None;
         let mut expected_kind = None;
 
-        for (pred, span) in traits::elaborate_predicates_with_span(
+        for (pred, span) in traits::elaborate(
             self.tcx,
             // Reverse the obligations here, since `elaborate_*` uses a stack,
             // and we want to keep inference generally in the same order of
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 2762e778591e..9155a3d8daa1 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -574,7 +574,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     ) -> Option {
         let sized_def_id = self.tcx.lang_items().sized_trait()?;
 
-        traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
+        traits::elaborate(self.tcx, predicates.predicates.iter().copied())
             // We don't care about regions here.
             .filter_map(|pred| match pred.kind().skip_binder() {
                 ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index dab709e17f05..0092bd2c6e64 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1555,8 +1555,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         if !self.predicate_may_hold(&o) {
                             result = ProbeResult::NoMatch;
                             let parent_o = o.clone();
-                            let implied_obligations =
-                                traits::elaborate_obligations(self.tcx, vec![o]);
+                            let implied_obligations = traits::elaborate(self.tcx, vec![o]);
                             for o in implied_obligations {
                                 let parent = if o == parent_o {
                                     None
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index f3797499866a..c5095a76f42c 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -1,7 +1,7 @@
 use smallvec::smallvec;
 
 use crate::infer::outlives::components::{push_outlives_components, Component};
-use crate::traits::{self, Obligation, ObligationCause, PredicateObligation};
+use crate::traits::{self, Obligation, PredicateObligation};
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_middle::ty::{self, ToPredicate, TyCtxt};
 use rustc_span::symbol::Ident;
@@ -66,99 +66,143 @@ impl<'tcx> Extend> for PredicateSet<'tcx> {
 /// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
 /// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
 /// `T: Foo`, then we know that `T: 'static`.
-pub struct Elaborator<'tcx> {
-    stack: Vec>,
+pub struct Elaborator<'tcx, O> {
+    stack: Vec,
     visited: PredicateSet<'tcx>,
 }
 
+/// Describes how to elaborate an obligation into a sub-obligation.
+///
+/// For [`Obligation`], a sub-obligation is combined with the current obligation's
+/// param-env and cause code. For [`ty::Predicate`], none of this is needed, since
+/// there is no param-env or cause code to copy over.
+pub trait Elaboratable<'tcx> {
+    fn predicate(&self) -> ty::Predicate<'tcx>;
+
+    // Makes a new `Self` but with a different predicate.
+    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self;
+
+    // Makes a new `Self` but with a different predicate and a different cause
+    // code (if `Self` has one).
+    fn child_with_derived_cause(
+        &self,
+        predicate: ty::Predicate<'tcx>,
+        span: Span,
+        parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
+        index: usize,
+    ) -> Self;
+}
+
+impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> {
+    fn predicate(&self) -> ty::Predicate<'tcx> {
+        self.predicate
+    }
+
+    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
+        Obligation {
+            cause: self.cause.clone(),
+            param_env: self.param_env,
+            recursion_depth: 0,
+            predicate,
+        }
+    }
+
+    fn child_with_derived_cause(
+        &self,
+        predicate: ty::Predicate<'tcx>,
+        span: Span,
+        parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
+        index: usize,
+    ) -> Self {
+        let cause = self.cause.clone().derived_cause(parent_trait_pred, |derived| {
+            traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause {
+                derived,
+                impl_or_alias_def_id: parent_trait_pred.def_id(),
+                impl_def_predicate_index: Some(index),
+                span,
+            }))
+        });
+        Obligation { cause, param_env: self.param_env, recursion_depth: 0, predicate }
+    }
+}
+
+impl<'tcx> Elaboratable<'tcx> for ty::Predicate<'tcx> {
+    fn predicate(&self) -> ty::Predicate<'tcx> {
+        *self
+    }
+
+    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
+        predicate
+    }
+
+    fn child_with_derived_cause(
+        &self,
+        predicate: ty::Predicate<'tcx>,
+        _span: Span,
+        _parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
+        _index: usize,
+    ) -> Self {
+        predicate
+    }
+}
+
+impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) {
+    fn predicate(&self) -> ty::Predicate<'tcx> {
+        self.0
+    }
+
+    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
+        (predicate, self.1)
+    }
+
+    fn child_with_derived_cause(
+        &self,
+        predicate: ty::Predicate<'tcx>,
+        _span: Span,
+        _parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
+        _index: usize,
+    ) -> Self {
+        (predicate, self.1)
+    }
+}
+
 pub fn elaborate_trait_ref<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>,
-) -> impl Iterator> {
-    elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
+) -> Elaborator<'tcx, ty::Predicate<'tcx>> {
+    elaborate(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
 }
 
 pub fn elaborate_trait_refs<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_refs: impl Iterator>,
-) -> impl Iterator> {
-    let predicates = trait_refs.map(move |trait_ref| trait_ref.without_const().to_predicate(tcx));
-    elaborate_predicates(tcx, predicates)
+) -> Elaborator<'tcx, ty::Predicate<'tcx>> {
+    elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx)))
 }
 
-pub fn elaborate_predicates<'tcx>(
+pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
     tcx: TyCtxt<'tcx>,
-    predicates: impl Iterator>,
-) -> impl Iterator> {
-    elaborate_obligations(
-        tcx,
-        predicates
-            .map(|predicate| {
-                Obligation::new(
-                    tcx,
-                    // We'll dump the cause/param-env later
-                    ObligationCause::dummy(),
-                    ty::ParamEnv::empty(),
-                    predicate,
-                )
-            })
-            .collect(),
-    )
-    .map(|obl| obl.predicate)
-}
-
-pub fn elaborate_predicates_with_span<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    predicates: impl Iterator, Span)>,
-) -> impl Iterator, Span)> {
-    elaborate_obligations(
-        tcx,
-        predicates
-            .map(|(predicate, span)| {
-                Obligation::new(
-                    tcx,
-                    // We'll dump the cause/param-env later
-                    ObligationCause::dummy_with_span(span),
-                    ty::ParamEnv::empty(),
-                    predicate,
-                )
-            })
-            .collect(),
-    )
-    .map(|obl| (obl.predicate, obl.cause.span))
-}
-
-pub fn elaborate_obligations<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    obligations: Vec>,
-) -> Elaborator<'tcx> {
+    obligations: impl IntoIterator,
+) -> Elaborator<'tcx, O> {
     let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) };
     elaborator.extend_deduped(obligations);
     elaborator
 }
 
-fn predicate_obligation<'tcx>(
-    predicate: ty::Predicate<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-) -> PredicateObligation<'tcx> {
-    Obligation { cause, param_env, recursion_depth: 0, predicate }
-}
-
-impl<'tcx> Elaborator<'tcx> {
-    fn extend_deduped(&mut self, obligations: impl IntoIterator>) {
+impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
+    fn extend_deduped(&mut self, obligations: impl IntoIterator) {
         // Only keep those bounds that we haven't already seen.
         // This is necessary to prevent infinite recursion in some
         // cases. One common case is when people define
         // `trait Sized: Sized { }` rather than `trait Sized { }`.
         // let visited = &mut self.visited;
-        self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate)));
+        self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate())));
     }
 
-    fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
+    fn elaborate(&mut self, elaboratable: &O) {
         let tcx = self.visited.tcx;
 
-        let bound_predicate = obligation.predicate.kind();
+        let bound_predicate = elaboratable.predicate().kind();
         match bound_predicate.skip_binder() {
             ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
                 // Get predicates declared on the trait.
@@ -170,24 +214,11 @@ impl<'tcx> Elaborator<'tcx> {
                         if data.constness == ty::BoundConstness::NotConst {
                             pred = pred.without_const(tcx);
                         }
-
-                        let cause = obligation.cause.clone().derived_cause(
-                            bound_predicate.rebind(data),
-                            |derived| {
-                                traits::ImplDerivedObligation(Box::new(
-                                    traits::ImplDerivedObligationCause {
-                                        derived,
-                                        impl_or_alias_def_id: data.def_id(),
-                                        impl_def_predicate_index: Some(index),
-                                        span,
-                                    },
-                                ))
-                            },
-                        );
-                        predicate_obligation(
+                        elaboratable.child_with_derived_cause(
                             pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
-                            obligation.param_env,
-                            cause,
+                            span,
+                            bound_predicate.rebind(data),
+                            index,
                         )
                     });
                 debug!(?data, ?obligations, "super_predicates");
@@ -290,13 +321,7 @@ impl<'tcx> Elaborator<'tcx> {
                         .map(|predicate_kind| {
                             bound_predicate.rebind(predicate_kind).to_predicate(tcx)
                         })
-                        .map(|predicate| {
-                            predicate_obligation(
-                                predicate,
-                                obligation.param_env,
-                                obligation.cause.clone(),
-                            )
-                        }),
+                        .map(|predicate| elaboratable.child(predicate)),
                 );
             }
             ty::PredicateKind::TypeWellFormedFromEnv(..) => {
@@ -313,8 +338,8 @@ impl<'tcx> Elaborator<'tcx> {
     }
 }
 
-impl<'tcx> Iterator for Elaborator<'tcx> {
-    type Item = PredicateObligation<'tcx>;
+impl<'tcx, O: Elaboratable<'tcx>> Iterator for Elaborator<'tcx, O> {
+    type Item = O;
 
     fn size_hint(&self) -> (usize, Option) {
         (self.stack.len(), None)
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index ad328006051f..35c461f5acee 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -12,7 +12,7 @@ use rustc_errors::{pluralize, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_infer::traits::util::elaborate_predicates_with_span;
+use rustc_infer::traits::util::elaborate;
 use rustc_middle::ty::adjustment;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::Symbol;
@@ -254,24 +254,21 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 }
                 ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
                 ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
-                    elaborate_predicates_with_span(
-                        cx.tcx,
-                        cx.tcx.explicit_item_bounds(def).iter().cloned(),
-                    )
-                    .find_map(|(pred, _span)| {
-                        // We only look at the `DefId`, so it is safe to skip the binder here.
-                        if let ty::PredicateKind::Clause(ty::Clause::Trait(
-                            ref poly_trait_predicate,
-                        )) = pred.kind().skip_binder()
-                        {
-                            let def_id = poly_trait_predicate.trait_ref.def_id;
+                    elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned())
+                        .find_map(|(pred, _span)| {
+                            // We only look at the `DefId`, so it is safe to skip the binder here.
+                            if let ty::PredicateKind::Clause(ty::Clause::Trait(
+                                ref poly_trait_predicate,
+                            )) = pred.kind().skip_binder()
+                            {
+                                let def_id = poly_trait_predicate.trait_ref.def_id;
 
-                            is_def_must_use(cx, def_id, span)
-                        } else {
-                            None
-                        }
-                    })
-                    .map(|inner| MustUsePath::Opaque(Box::new(inner)))
+                                is_def_must_use(cx, def_id, span)
+                            } else {
+                                None
+                            }
+                        })
+                        .map(|inner| MustUsePath::Opaque(Box::new(inner)))
                 }
                 ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| {
                     if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index ac55948e61b5..839d5422ad1d 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -115,10 +115,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
             .predicates
             .iter()
             .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
-        if traits::impossible_predicates(
-            tcx,
-            traits::elaborate_predicates(tcx, predicates).collect(),
-        ) {
+        if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) {
             trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id);
             return;
         }
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 942ccd5a9d19..85e229b694ce 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -91,10 +91,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
             .predicates
             .iter()
             .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
-        if traits::impossible_predicates(
-            tcx,
-            traits::elaborate_predicates(tcx, predicates).collect(),
-        ) {
+        if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) {
             trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id);
             return;
         }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs
index f8a54f73a33e..6476da7ba489 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly.rs
@@ -9,7 +9,7 @@ use itertools::Itertools;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def_id::DefId;
 use rustc_infer::traits::query::NoSolution;
-use rustc_infer::traits::util::elaborate_predicates;
+use rustc_infer::traits::util::elaborate;
 use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult};
 use rustc_middle::ty::fast_reject::TreatProjections;
 use rustc_middle::ty::TypeFoldable;
@@ -498,7 +498,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         let tcx = self.tcx();
         let own_bounds: FxIndexSet<_> =
             bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect();
-        for assumption in elaborate_predicates(tcx, own_bounds.iter().copied()) {
+        for assumption in elaborate(tcx, own_bounds.iter().copied()) {
             // FIXME: Predicates are fully elaborated in the object type's existential bounds
             // list. We want to only consider these pre-elaborated projections, and not other
             // projection predicates that we reach by elaborating the principal trait ref,
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 878c502655cf..a53d414be9e7 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -234,7 +234,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
     /// constructed once for a given type. As part of the construction process, the `ParamEnv` will
     /// have any supertrait bounds normalized -- e.g., if we have a type `struct Foo`, the
     /// `ParamEnv` will contain `T: Copy` and `T: Clone`, since `Copy: Clone`. When we construct our
-    /// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate_predicates`, or
+    /// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate`, or
     /// else `SelectionContext` will choke on the missing predicates. However, this should never
     /// show up in the final synthesized generics: we don't want our generated docs page to contain
     /// something like `T: Copy + Clone`, as that's redundant. Therefore, we keep track of a
@@ -346,10 +346,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 _ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
             };
 
-            let normalized_preds = elaborate_predicates(
-                tcx,
-                computed_preds.clone().chain(user_computed_preds.iter().cloned()),
-            );
+            let normalized_preds =
+                elaborate(tcx, computed_preds.clone().chain(user_computed_preds.iter().cloned()));
             new_env = ty::ParamEnv::new(
                 tcx.mk_predicates_from_iter(normalized_preds),
                 param_env.reveal(),
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index d360158fdf81..53d4f95e9e30 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -368,7 +368,7 @@ fn negative_impl_exists<'tcx>(
     }
 
     // Try to prove a negative obligation exists for super predicates
-    for pred in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) {
+    for pred in util::elaborate(infcx.tcx, iter::once(o.predicate)) {
         if resolve_negative_obligation(infcx.fork(), &o.with(infcx.tcx, pred), body_def_id) {
             return true;
         }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
index 672b3365ff4a..0475f24d87c7 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -1,6 +1,6 @@
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
-use rustc_infer::traits::util::elaborate_predicates_with_span;
+use rustc_infer::traits::util::elaborate;
 use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
 use rustc_middle::ty;
 use rustc_span::{Span, DUMMY_SP};
@@ -82,7 +82,7 @@ pub fn recompute_applicable_impls<'tcx>(
 
     let predicates =
         tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
-    for (pred, span) in elaborate_predicates_with_span(tcx, predicates.into_iter()) {
+    for (pred, span) in elaborate(tcx, predicates.into_iter()) {
         let kind = pred.kind();
         if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
             && param_env_candidate_may_apply(kind.rebind(trait_pred))
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index c19798213b70..6ebf056f0e83 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1624,7 +1624,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
         };
 
-        for pred in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
+        for pred in super::elaborate(self.tcx, std::iter::once(cond)) {
             let bound_predicate = pred.kind();
             if let ty::PredicateKind::Clause(ty::Clause::Trait(implication)) =
                 bound_predicate.skip_binder()
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 8d831dca6e30..1094a77fe147 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -58,10 +58,7 @@ pub use self::specialize::{specialization_graph, translate_substs, OverlapError}
 pub use self::structural_match::{
     search_for_adt_const_param_violation, search_for_structural_match_violation,
 };
-pub use self::util::{
-    elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span,
-    elaborate_trait_ref, elaborate_trait_refs,
-};
+pub use self::util::{elaborate, elaborate_trait_ref, elaborate_trait_refs};
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
 pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
 pub use self::util::{
@@ -267,7 +264,7 @@ pub fn normalize_param_env_or_error<'tcx>(
     // and errors will get reported then; so outside of type inference we
     // can be sure that no errors should occur.
     let mut predicates: Vec<_> =
-        util::elaborate_predicates(tcx, unnormalized_env.caller_bounds().into_iter()).collect();
+        util::elaborate(tcx, unnormalized_env.caller_bounds().into_iter()).collect();
 
     debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
 
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index dbf6b78572a1..9953d048f755 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -8,7 +8,7 @@
 //!   - not reference the erased type `Self` except for in this receiver;
 //!   - not have generic type parameters.
 
-use super::{elaborate_predicates, elaborate_trait_ref};
+use super::{elaborate, elaborate_trait_ref};
 
 use crate::infer::TyCtxtInferExt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
@@ -379,7 +379,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     // Search for a predicate like `Self : Sized` amongst the trait bounds.
     let predicates = tcx.predicates_of(def_id);
     let predicates = predicates.instantiate_identity(tcx).predicates;
-    elaborate_predicates(tcx, predicates.into_iter()).any(|pred| match pred.kind().skip_binder() {
+    elaborate(tcx, predicates.into_iter()).any(|pred| match pred.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::Clause::Trait(ref trait_pred)) => {
             trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
         }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 156674e33c33..3d026506a5a8 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -364,7 +364,7 @@ impl<'tcx> WfPredicates<'tcx> {
         };
 
         if let Elaborate::All = elaborate {
-            let implied_obligations = traits::util::elaborate_obligations(tcx, obligations);
+            let implied_obligations = traits::util::elaborate(tcx, obligations);
             let implied_obligations = implied_obligations.map(extend);
             self.out.extend(implied_obligations);
         } else {
@@ -920,7 +920,7 @@ pub(crate) fn required_region_bounds<'tcx>(
 ) -> Vec> {
     assert!(!erased_self_ty.has_escaping_bound_vars());
 
-    traits::elaborate_predicates(tcx, predicates)
+    traits::elaborate(tcx, predicates)
         .filter_map(|pred| {
             debug!(?pred);
             match pred.kind().skip_binder() {
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 327e090d38be..0bb1775aae9c 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -122,7 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
 
         let sized_trait = need!(cx.tcx.lang_items().sized_trait());
 
-        let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter())
+        let preds = traits::elaborate(cx.tcx, cx.param_env.caller_bounds().iter())
             .filter(|p| !p.is_global())
             .filter_map(|pred| {
                 // Note that we do not want to deal with qualified predicates here.
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 619aa9f4bf6f..9051cf51658d 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2104,7 +2104,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
         .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
     traits::impossible_predicates(
         cx.tcx,
-        traits::elaborate_predicates(cx.tcx, predicates)
+        traits::elaborate(cx.tcx, predicates)
             .collect::>(),
     )
 }

From 2cd0729d635a47bc585c683b36cd72cf884eb258 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Thu, 6 Apr 2023 23:24:03 +0000
Subject: [PATCH 193/267] Get rid of elaborate_trait_ref{s} too

---
 .../rustc_hir_analysis/src/astconv/mod.rs     |  6 ++---
 compiler/rustc_infer/src/traits/util.rs       | 24 ++++++-------------
 .../rustc_trait_selection/src/traits/mod.rs   |  2 +-
 .../src/traits/object_safety.rs               |  5 ++--
 4 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index e25b07d93922..6727173cd886 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -33,9 +33,9 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
 use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::ty::fold::FnMutDelegate;
 use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
-use rustc_middle::ty::DynKind;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{DynKind, ToPredicate};
 use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
@@ -1526,8 +1526,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         for (base_trait_ref, span, constness) in regular_traits_refs_spans {
             assert_eq!(constness, ty::BoundConstness::NotConst);
-
-            for pred in traits::elaborate_trait_ref(tcx, base_trait_ref) {
+            let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
+            for pred in traits::elaborate(tcx, [base_pred]) {
                 debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
 
                 let bound_predicate = pred.kind();
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index c5095a76f42c..c7f7ed149407 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -166,20 +166,6 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) {
     }
 }
 
-pub fn elaborate_trait_ref<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> Elaborator<'tcx, ty::Predicate<'tcx>> {
-    elaborate(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
-}
-
-pub fn elaborate_trait_refs<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_refs: impl Iterator>,
-) -> Elaborator<'tcx, ty::Predicate<'tcx>> {
-    elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx)))
-}
-
 pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
     tcx: TyCtxt<'tcx>,
     obligations: impl IntoIterator,
@@ -364,17 +350,21 @@ pub fn supertraits<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>,
 ) -> impl Iterator> {
-    FilterToTraits::new(elaborate_trait_ref(tcx, trait_ref))
+    let pred: ty::Predicate<'tcx> = trait_ref.to_predicate(tcx);
+    FilterToTraits::new(elaborate(tcx, [pred]))
 }
 
 pub fn transitive_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_refs: impl Iterator>,
 ) -> impl Iterator> {
-    FilterToTraits::new(elaborate_trait_refs(tcx, trait_refs))
+    FilterToTraits::new(elaborate(
+        tcx,
+        trait_refs.map(|trait_ref| -> ty::Predicate<'tcx> { trait_ref.to_predicate(tcx) }),
+    ))
 }
 
-/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
+/// A specialized variant of `elaborate` that only elaborates trait references that may
 /// define the given associated type `assoc_name`. It uses the
 /// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that
 /// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 1094a77fe147..8a203dec86ba 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -58,7 +58,7 @@ pub use self::specialize::{specialization_graph, translate_substs, OverlapError}
 pub use self::structural_match::{
     search_for_adt_const_param_violation, search_for_structural_match_violation,
 };
-pub use self::util::{elaborate, elaborate_trait_ref, elaborate_trait_refs};
+pub use self::util::elaborate;
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
 pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
 pub use self::util::{
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 9953d048f755..b8ad1925e4ea 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -8,7 +8,7 @@
 //!   - not reference the erased type `Self` except for in this receiver;
 //!   - not have generic type parameters.
 
-use super::{elaborate, elaborate_trait_ref};
+use super::elaborate;
 
 use crate::infer::TyCtxtInferExt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
@@ -666,7 +666,8 @@ fn object_ty_for_trait<'tcx>(
     });
     debug!(?trait_predicate);
 
-    let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref)
+    let pred: ty::Predicate<'tcx> = trait_ref.to_predicate(tcx);
+    let mut elaborated_predicates: Vec<_> = elaborate(tcx, [pred])
         .filter_map(|pred| {
             debug!(?pred);
             let pred = pred.to_opt_poly_projection_pred()?;

From 67b46141804132919a7976b3484cbcf6055e431e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= 
Date: Wed, 5 Apr 2023 00:00:00 +0000
Subject: [PATCH 194/267] Inline try_from and try_into

To avoid link time dependency between core and compiler-builtins, when
using opt-level that implicitly enables -Zshare-generics.

While compiler-builtins should be compiled with -Zshare-generics
disabled, the -Zbuild-std does not ensure this at the moment.
---
 library/core/src/convert/mod.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 8a8d4caf96f3..5888e2960bb7 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -764,6 +764,7 @@ where
 {
     type Error = U::Error;
 
+    #[inline]
     fn try_into(self) -> Result {
         U::try_from(self)
     }
@@ -779,6 +780,7 @@ where
 {
     type Error = Infallible;
 
+    #[inline]
     fn try_from(value: U) -> Result {
         Ok(U::into(value))
     }

From 7ddc245b145bf8b1a1d6472ff7b43a2acd8f2ed7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= 
Date: Fri, 7 Apr 2023 00:00:00 +0000
Subject: [PATCH 195/267] ./x.py test --bless

---
 ...unchecked_shl_unsigned_smaller.Inline.diff | 123 +++++++++++-------
 ..._shl_unsigned_smaller.PreCodegen.after.mir | 118 ++++++++++-------
 ...s.unchecked_shr_signed_smaller.Inline.diff | 123 +++++++++++-------
 ...ed_shr_signed_smaller.PreCodegen.after.mir | 118 ++++++++++-------
 4 files changed, 298 insertions(+), 184 deletions(-)

diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
index bf05ed417181..6184a0acd187 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
@@ -14,36 +14,45 @@
 +         let mut _6: std::option::Option; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         let mut _7: std::result::Result; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         scope 2 {
-+             scope 3 (inlined Result::::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                 debug self => _7;        // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 let mut _8: isize;       // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 let _9: u16;             // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 scope 4 {
-+                     debug x => _9;       // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
++             scope 3 (inlined >::try_into) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                 debug self => _4;        // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                 scope 4 (inlined convert::num:: for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                     debug u => _4;       // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _8: bool;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _9: u32;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _10: u16;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +                 }
-+                 scope 5 {
-+                     scope 6 {
-+                         debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++             }
++             scope 5 (inlined Result::::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                 debug self => _7;        // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 let mut _11: isize;      // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 let _12: u16;            // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 scope 6 {
++                     debug x => _12;      // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++                 }
++                 scope 7 {
++                     scope 8 {
++                         debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                     }
 +                 }
 +             }
-+             scope 7 (inlined #[track_caller] Option::::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                 debug self => _6;        // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 let mut _10: &std::option::Option; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 let mut _11: isize;      // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 scope 8 {
-+                     debug val => _5;     // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL
++             scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                 debug self => _6;        // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                 let mut _13: &std::option::Option; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                 let mut _14: isize;      // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                 scope 10 {
++                     debug val => _5;     // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
 +                 }
-+                 scope 9 {
-+                     scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                         scope 12 {
-+                             scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                 scope 11 {
++                     scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 14 {
++                             scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
 +                             }
 +                         }
 +                     }
 +                 }
-+                 scope 10 (inlined Option::::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                     debug self => _10;   // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                 scope 12 (inlined Option::::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                     debug self => _13;   // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
 +                 }
 +             }
 +         }
@@ -55,58 +64,78 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
+-                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::::unchecked_shl}, val: Value() }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         _7 = >::try_into(_4) -> bb1; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
--                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::::unchecked_shl}, val: Value() }
-+                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> Result>::Error> {>::try_into}, val: Value() }
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = const 65535_u32;            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _8 = Gt(_4, move _9);            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _8) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageLive(_9);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         _8 = discriminant(_7);           // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+         switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageDead(_12);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _14) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
 +     }
 + 
 +     bb2: {
-+         StorageDead(_9);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         StorageLive(_10);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         _11 = discriminant(_6);          // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+         switchInt(move _11) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+     }
-+ 
-+     bb3: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
 +     }
 + 
++     bb3: {
++         _7 = Result::::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value() }
++         goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
 +     bb4: {
-+         _6 = Option::::None;        // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-+         goto -> bb2;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = _4 as u16 (IntToInt);      // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _7 = Result::::Ok(move _10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +     }
 + 
 +     bb5: {
-+         unreachable;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_12);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         _11 = discriminant(_7);          // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _11) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb6: {
-+         _9 = move ((_7 as Ok).0: u16);   // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+         _6 = Option::::Some(move _9); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
-+         goto -> bb2;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::::None;        // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb1;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb7: {
-+         _5 = move ((_6 as Some).0: u16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+         StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         _12 = move ((_7 as Ok).0: u16);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::::Some(move _12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_6 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         _0 = unchecked_shl::(_3, move _5) -> [return: bb3, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         _0 = unchecked_shl::(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +                                          // mir::Constant
 +                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::}, val: Value() }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
index 7f6e974f66b1..726b6bbf93b5 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
@@ -11,36 +11,45 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
         let mut _4: std::option::Option; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         let mut _5: std::result::Result; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         scope 2 {
-            scope 3 (inlined Result::::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                debug self => _5;        // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                let mut _6: isize;       // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                let _7: u16;             // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                scope 4 {
-                    debug x => _7;       // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
+            scope 3 (inlined >::try_into) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                debug self => _2;        // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                scope 4 (inlined convert::num:: for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                    debug u => _2;       // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _6: bool;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _7: u32;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _8: u16;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                 }
-                scope 5 {
-                    scope 6 {
-                        debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+            }
+            scope 5 (inlined Result::::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                debug self => _5;        // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+                let mut _9: isize;       // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+                let _10: u16;            // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+                scope 6 {
+                    debug x => _10;      // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+                }
+                scope 7 {
+                    scope 8 {
+                        debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                     }
                 }
             }
-            scope 7 (inlined #[track_caller] Option::::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                debug self => _4;        // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                let mut _8: &std::option::Option; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                let mut _9: isize;       // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                scope 8 {
-                    debug val => _3;     // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL
+            scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                debug self => _4;        // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                let mut _11: &std::option::Option; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                let mut _12: isize;      // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                scope 10 {
+                    debug val => _3;     // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
                 }
-                scope 9 {
-                    scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                        scope 12 {
-                            scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                scope 11 {
+                    scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 14 {
+                            scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             }
                         }
                     }
                 }
-                scope 10 (inlined Option::::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                    debug self => _8;    // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                scope 12 (inlined Option::::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                    debug self => _11;   // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
                 }
             }
         }
@@ -50,51 +59,70 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        _5 = >::try_into(_2) -> bb1; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                                         // + literal: Const { ty: fn(u32) -> Result>::Error> {>::try_into}, val: Value() }
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = const 65535_u32;            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Gt(_2, move _7);            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        _6 = discriminant(_5);           // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-        switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageLive(_11);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _12 = discriminant(_4);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _12) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb2: {
-        StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        StorageLive(_8);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        _9 = discriminant(_4);           // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _9) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-    }
-
-    bb3: {
         StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
     }
 
+    bb3: {
+        _5 = Result::::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value() }
+        goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
     bb4: {
-        _4 = Option::::None;        // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb2;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = _2 as u16 (IntToInt);       // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _5 = Result::::Ok(move _8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb5: {
-        unreachable;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_10);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _9 = discriminant(_5);           // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _9) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb6: {
-        _7 = move ((_5 as Ok).0: u16);   // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-        _4 = Option::::Some(move _7); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb2;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        _4 = Option::::None;        // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb1;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb7: {
-        _3 = move ((_4 as Some).0: u16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_8);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        _10 = move ((_5 as Ok).0: u16);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        _4 = Option::::Some(move _10); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb9: {
+        _3 = move ((_4 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_11);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        _0 = unchecked_shl::(_1, move _3) -> [return: bb3, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _0 = unchecked_shl::(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::}, val: Value() }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
index 5c4fb5ba8ba2..35d5b6e72f28 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
@@ -14,36 +14,45 @@
 +         let mut _6: std::option::Option; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         let mut _7: std::result::Result; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         scope 2 {
-+             scope 3 (inlined Result::::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                 debug self => _7;        // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 let mut _8: isize;       // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 let _9: i16;             // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 scope 4 {
-+                     debug x => _9;       // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
++             scope 3 (inlined >::try_into) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                 debug self => _4;        // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                 scope 4 (inlined convert::num:: for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                     debug u => _4;       // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _8: bool;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _9: u32;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _10: i16;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +                 }
-+                 scope 5 {
-+                     scope 6 {
-+                         debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++             }
++             scope 5 (inlined Result::::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                 debug self => _7;        // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 let mut _11: isize;      // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 let _12: i16;            // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 scope 6 {
++                     debug x => _12;      // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++                 }
++                 scope 7 {
++                     scope 8 {
++                         debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                     }
 +                 }
 +             }
-+             scope 7 (inlined #[track_caller] Option::::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                 debug self => _6;        // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 let mut _10: &std::option::Option; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 let mut _11: isize;      // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 scope 8 {
-+                     debug val => _5;     // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL
++             scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                 debug self => _6;        // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                 let mut _13: &std::option::Option; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                 let mut _14: isize;      // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                 scope 10 {
++                     debug val => _5;     // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
 +                 }
-+                 scope 9 {
-+                     scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                         scope 12 {
-+                             scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                 scope 11 {
++                     scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 14 {
++                             scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
 +                             }
 +                         }
 +                     }
 +                 }
-+                 scope 10 (inlined Option::::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                     debug self => _10;   // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                 scope 12 (inlined Option::::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                     debug self => _13;   // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
 +                 }
 +             }
 +         }
@@ -55,58 +64,78 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
+-                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::::unchecked_shr}, val: Value() }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         _7 = >::try_into(_4) -> bb1; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
--                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::::unchecked_shr}, val: Value() }
-+                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> Result>::Error> {>::try_into}, val: Value() }
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = const 32767_u32;            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _8 = Gt(_4, move _9);            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _8) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageLive(_9);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         _8 = discriminant(_7);           // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+         switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageDead(_12);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _14) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
 +     }
 + 
 +     bb2: {
-+         StorageDead(_9);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         StorageLive(_10);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         _11 = discriminant(_6);          // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+         switchInt(move _11) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+     }
-+ 
-+     bb3: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
 +     }
 + 
++     bb3: {
++         _7 = Result::::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value() }
++         goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
 +     bb4: {
-+         _6 = Option::::None;        // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-+         goto -> bb2;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = _4 as i16 (IntToInt);      // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _7 = Result::::Ok(move _10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +     }
 + 
 +     bb5: {
-+         unreachable;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_12);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         _11 = discriminant(_7);          // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _11) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb6: {
-+         _9 = move ((_7 as Ok).0: i16);   // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+         _6 = Option::::Some(move _9); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
-+         goto -> bb2;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::::None;        // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb1;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb7: {
-+         _5 = move ((_6 as Some).0: i16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+         StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         _12 = move ((_7 as Ok).0: i16);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::::Some(move _12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_6 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         _0 = unchecked_shr::(_3, move _5) -> [return: bb3, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         _0 = unchecked_shr::(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +                                          // mir::Constant
 +                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::}, val: Value() }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
index 698a3c656550..b006085b54c5 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
@@ -11,36 +11,45 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
         let mut _4: std::option::Option; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         let mut _5: std::result::Result; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         scope 2 {
-            scope 3 (inlined Result::::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                debug self => _5;        // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                let mut _6: isize;       // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                let _7: i16;             // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                scope 4 {
-                    debug x => _7;       // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
+            scope 3 (inlined >::try_into) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                debug self => _2;        // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                scope 4 (inlined convert::num:: for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                    debug u => _2;       // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _6: bool;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _7: u32;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _8: i16;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                 }
-                scope 5 {
-                    scope 6 {
-                        debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+            }
+            scope 5 (inlined Result::::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                debug self => _5;        // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+                let mut _9: isize;       // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+                let _10: i16;            // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+                scope 6 {
+                    debug x => _10;      // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+                }
+                scope 7 {
+                    scope 8 {
+                        debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                     }
                 }
             }
-            scope 7 (inlined #[track_caller] Option::::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                debug self => _4;        // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                let mut _8: &std::option::Option; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                let mut _9: isize;       // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                scope 8 {
-                    debug val => _3;     // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL
+            scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                debug self => _4;        // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                let mut _11: &std::option::Option; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                let mut _12: isize;      // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                scope 10 {
+                    debug val => _3;     // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
                 }
-                scope 9 {
-                    scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                        scope 12 {
-                            scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                scope 11 {
+                    scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 14 {
+                            scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             }
                         }
                     }
                 }
-                scope 10 (inlined Option::::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                    debug self => _8;    // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                scope 12 (inlined Option::::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                    debug self => _11;   // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
                 }
             }
         }
@@ -50,51 +59,70 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        _5 = >::try_into(_2) -> bb1; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                                         // + literal: Const { ty: fn(u32) -> Result>::Error> {>::try_into}, val: Value() }
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = const 32767_u32;            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Gt(_2, move _7);            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        _6 = discriminant(_5);           // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-        switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        StorageLive(_11);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _12 = discriminant(_4);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _12) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb2: {
-        StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        StorageLive(_8);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        _9 = discriminant(_4);           // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _9) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-    }
-
-    bb3: {
         StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
     }
 
+    bb3: {
+        _5 = Result::::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value() }
+        goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
     bb4: {
-        _4 = Option::::None;        // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb2;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = _2 as i16 (IntToInt);       // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _5 = Result::::Ok(move _8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb5: {
-        unreachable;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_10);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _9 = discriminant(_5);           // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _9) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb6: {
-        _7 = move ((_5 as Ok).0: i16);   // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-        _4 = Option::::Some(move _7); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb2;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        _4 = Option::::None;        // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb1;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb7: {
-        _3 = move ((_4 as Some).0: i16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_8);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        _10 = move ((_5 as Ok).0: i16);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        _4 = Option::::Some(move _10); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb9: {
+        _3 = move ((_4 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_11);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        _0 = unchecked_shr::(_1, move _3) -> [return: bb3, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _0 = unchecked_shr::(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::}, val: Value() }

From 4646b3df6ad09f5cda12742ee98309b659006039 Mon Sep 17 00:00:00 2001
From: Jack Huey <31162821+jackh726@users.noreply.github.com>
Date: Thu, 6 Apr 2023 21:12:17 -0400
Subject: [PATCH 196/267] Use BoundTy and BoundRegion instead of kind of
 PlaceholderTy and PlaceholderRegion

---
 .../src/diagnostics/bound_region_errors.rs    |  4 +-
 .../rustc_borrowck/src/diagnostics/mod.rs     | 14 ++++---
 .../src/diagnostics/region_errors.rs          |  2 +-
 .../src/type_check/relate_tys.rs              |  2 +-
 .../rustc_hir_analysis/src/astconv/mod.rs     |  8 ++--
 .../rustc_infer/src/infer/canonical/mod.rs    | 12 +++---
 .../src/infer/error_reporting/mod.rs          |  6 +--
 .../nice_region_error/placeholder_relation.rs | 16 +++++++-
 .../src/infer/higher_ranked/mod.rs            | 14 +++----
 compiler/rustc_infer/src/infer/mod.rs         | 16 +++++---
 .../rustc_infer/src/infer/nll_relate/mod.rs   |  2 +-
 .../infer/region_constraints/leak_check.rs    |  4 +-
 compiler/rustc_middle/src/infer/canonical.rs  |  8 ++--
 compiler/rustc_middle/src/ty/mod.rs           |  6 +--
 compiler/rustc_middle/src/ty/print/pretty.rs  | 15 +++++--
 .../rustc_middle/src/ty/structural_impls.rs   |  4 +-
 compiler/rustc_middle/src/ty/sty.rs           |  4 +-
 .../src/solve/canonicalize.rs                 | 14 +++++--
 .../src/traits/project.rs                     |  6 +--
 compiler/rustc_traits/src/chalk/lowering.rs   | 39 ++++++++++++-------
 20 files changed, 121 insertions(+), 75 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 68205fa45587..84f75caa6928 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -181,8 +181,8 @@ trait TypeOpInfo<'tcx> {
         };
 
         let placeholder_region = tcx.mk_re_placeholder(ty::Placeholder {
-            name: placeholder.name,
             universe: adjusted_universe.into(),
+            bound: placeholder.bound,
         });
 
         let error_region =
@@ -191,8 +191,8 @@ trait TypeOpInfo<'tcx> {
                     error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
                 adjusted_universe.map(|adjusted| {
                     tcx.mk_re_placeholder(ty::Placeholder {
-                        name: error_placeholder.name,
                         universe: adjusted.into(),
+                        bound: error_placeholder.bound,
                     })
                 })
             } else {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 7bd4331c5ed9..110354a20d83 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -467,9 +467,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let ty::Ref(region, ..) = ty.kind() {
             match **region {
                 ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
-                | ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
-                    printer.region_highlight_mode.highlighting_bound_region(br, counter)
-                }
+                | ty::RePlaceholder(ty::PlaceholderRegion {
+                    bound: ty::BoundRegion { kind: br, .. },
+                    ..
+                }) => printer.region_highlight_mode.highlighting_bound_region(br, counter),
                 _ => {}
             }
         }
@@ -485,9 +486,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let region = if let ty::Ref(region, ..) = ty.kind() {
             match **region {
                 ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
-                | ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
-                    printer.region_highlight_mode.highlighting_bound_region(br, counter)
-                }
+                | ty::RePlaceholder(ty::PlaceholderRegion {
+                    bound: ty::BoundRegion { kind: br, .. },
+                    ..
+                }) => printer.region_highlight_mode.highlighting_bound_region(br, counter),
                 _ => {}
             }
             region
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index ffe82b46cfd6..9fcebeb0acdc 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -207,7 +207,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             .regioncx
             .placeholders_contained_in(lower_bound)
             .map(|placeholder| {
-                if let Some(id) = placeholder.name.get_id()
+                if let Some(id) = placeholder.bound.kind.get_id()
                     && let Some(placeholder_id) = id.as_local()
                     && let gat_hir_id = hir.local_def_id_to_hir_id(placeholder_id)
                     && let Some(generics_impl) = hir.get_parent(gat_hir_id).generics()
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 305e2c8fe8eb..cdc916457ca6 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -123,7 +123,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
             .constraints
             .placeholder_region(self.type_checker.infcx, placeholder);
 
-        let reg_info = match placeholder.name {
+        let reg_info = match placeholder.bound.kind {
             ty::BoundRegionKind::BrAnon(_, Some(span)) => BoundRegionInfo::Span(span),
             ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(Symbol::intern("anon")),
             ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index e25b07d93922..e0408b36af9e 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2336,10 +2336,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 FnMutDelegate {
                     regions: &mut |_| tcx.lifetimes.re_erased,
                     types: &mut |bv| {
-                        tcx.mk_placeholder(ty::PlaceholderType { universe, name: bv.kind })
+                        tcx.mk_placeholder(ty::PlaceholderType { universe, bound: bv })
                     },
                     consts: &mut |bv, ty| {
-                        tcx.mk_const(ty::PlaceholderConst { universe, name: bv }, ty)
+                        tcx.mk_const(ty::PlaceholderConst { universe, bound: bv }, ty)
                     },
                 },
             );
@@ -2525,11 +2525,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                             regions: &mut |_| tcx.lifetimes.re_erased,
                                             types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType {
                                                 universe,
-                                                name: bv.kind,
+                                                bound: bv,
                                             }),
                                             consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst {
                                                 universe,
-                                                name: bv
+                                                bound: bv,
                                             }, ty),
                                         })
                                     )
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index ce230afdab3c..fbb2257bf67c 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -125,9 +125,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 ty.into()
             }
 
-            CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => {
+            CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => {
                 let universe_mapped = universe_map(universe);
-                let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, name };
+                let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, bound };
                 self.tcx.mk_placeholder(placeholder_mapped).into()
             }
 
@@ -138,9 +138,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 )
                 .into(),
 
-            CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => {
+            CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, bound }) => {
                 let universe_mapped = universe_map(universe);
-                let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, name };
+                let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, bound };
                 self.tcx.mk_re_placeholder(placeholder_mapped).into()
             }
 
@@ -152,9 +152,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 )
                 .into(),
 
-            CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, name }, ty) => {
+            CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => {
                 let universe_mapped = universe_map(universe);
-                let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, name };
+                let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound };
                 self.tcx.mk_const(placeholder_mapped, ty).into()
             }
         }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index c9956b60a56d..40d576068171 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -170,15 +170,15 @@ fn msg_span_from_named_region<'tcx>(
         }
         ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            name: ty::BoundRegionKind::BrNamed(def_id, name),
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, name), .. },
             ..
         }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            name: ty::BoundRegionKind::BrAnon(_, Some(span)),
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(_, Some(span)), .. },
             ..
         }) => (format!("the anonymous lifetime defined here"), Some(span)),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            name: ty::BoundRegionKind::BrAnon(_, None),
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(_, None), .. },
             ..
         }) => (format!("an anonymous lifetime"), None),
         _ => bug!("{:?}", region),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
index e8d94f0c04ea..06aff52681fd 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
@@ -16,8 +16,20 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         match &self.error {
             Some(RegionResolutionError::ConcreteFailure(
                 SubregionOrigin::RelateRegionParamBound(span),
-                Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)),
-                Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)),
+                Region(Interned(
+                    RePlaceholder(ty::Placeholder {
+                        bound: ty::BoundRegion { kind: sub_name, .. },
+                        ..
+                    }),
+                    _,
+                )),
+                Region(Interned(
+                    RePlaceholder(ty::Placeholder {
+                        bound: ty::BoundRegion { kind: sup_name, .. },
+                        ..
+                    }),
+                    _,
+                )),
             )) => {
                 let span = *span;
                 let (sub_span, sub_symbol) = match sub_name {
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index d1897cf24b4a..a63cfbc919c6 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -82,20 +82,20 @@ impl<'tcx> InferCtxt<'tcx> {
 
         let delegate = FnMutDelegate {
             regions: &mut |br: ty::BoundRegion| {
-                self.tcx.mk_re_placeholder(ty::PlaceholderRegion {
-                    universe: next_universe,
-                    name: br.kind,
-                })
+                self.tcx
+                    .mk_re_placeholder(ty::PlaceholderRegion { universe: next_universe, bound: br })
             },
             types: &mut |bound_ty: ty::BoundTy| {
                 self.tcx.mk_placeholder(ty::PlaceholderType {
                     universe: next_universe,
-                    name: bound_ty.kind,
+                    bound: bound_ty,
                 })
             },
             consts: &mut |bound_var: ty::BoundVar, ty| {
-                self.tcx
-                    .mk_const(ty::PlaceholderConst { universe: next_universe, name: bound_var }, ty)
+                self.tcx.mk_const(
+                    ty::PlaceholderConst { universe: next_universe, bound: bound_var },
+                    ty,
+                )
             },
         };
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 9903ffa90bae..ac8349e4c3ab 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -2130,13 +2130,17 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
 
         fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             if let ty::Infer(_) = t.kind() {
+                let idx = {
+                    let idx = self.idx;
+                    self.idx += 1;
+                    idx
+                };
                 self.tcx.mk_placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::ROOT,
-                    name: ty::BoundTyKind::Anon({
-                        let idx = self.idx;
-                        self.idx += 1;
-                        idx
-                    }),
+                    bound: ty::BoundTy {
+                        var: ty::BoundVar::from_u32(idx),
+                        kind: ty::BoundTyKind::Anon(idx),
+                    },
                 })
             } else {
                 t.super_fold_with(self)
@@ -2153,7 +2157,7 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
                 self.tcx.mk_const(
                     ty::PlaceholderConst {
                         universe: ty::UniverseIndex::ROOT,
-                        name: ty::BoundVar::from_u32({
+                        bound: ty::BoundVar::from_u32({
                             let idx = self.idx;
                             self.idx += 1;
                             idx
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 7616a996da10..9f7b26b87f45 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -296,7 +296,7 @@ where
                     universe
                 });
 
-                let placeholder = ty::PlaceholderRegion { universe, name: br.kind };
+                let placeholder = ty::PlaceholderRegion { universe, bound: br };
                 debug!(?placeholder);
                 let placeholder_reg = nll_delegate.next_placeholder_region(placeholder);
                 debug!(?placeholder_reg);
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index 89ada23c6673..b8ba98fc0a9f 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -290,9 +290,9 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
     ) -> TypeError<'tcx> {
         debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region);
         if self.overly_polymorphic {
-            TypeError::RegionsOverlyPolymorphic(placeholder.name, other_region)
+            TypeError::RegionsOverlyPolymorphic(placeholder.bound.kind, other_region)
         } else {
-            TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, other_region)
+            TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region)
         }
     }
 }
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 2f42849f390b..d3f71e75d991 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -155,9 +155,11 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
             | CanonicalVarKind::Region(_)
             | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
 
-            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(),
-            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(),
-            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(),
+            CanonicalVarKind::PlaceholderRegion(placeholder) => {
+                placeholder.bound.kind.expect_anon()
+            }
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.kind.expect_anon(),
+            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_u32(),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 800a230b6544..c856bb25e147 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1454,12 +1454,12 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
 #[derive(HashStable, TyEncodable, TyDecodable)]
 pub struct Placeholder {
     pub universe: UniverseIndex,
-    pub name: T,
+    pub bound: T,
 }
 
-pub type PlaceholderRegion = Placeholder;
+pub type PlaceholderRegion = Placeholder;
 
-pub type PlaceholderType = Placeholder;
+pub type PlaceholderType = Placeholder;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
 #[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index de4c703107e1..fb681f1114d6 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -739,7 +739,7 @@ pub trait PrettyPrinter<'tcx>:
                     p!(print(data))
                 }
             }
-            ty::Placeholder(placeholder) => match placeholder.name {
+            ty::Placeholder(placeholder) => match placeholder.bound.kind {
                 ty::BoundTyKind::Anon(_) => p!(write("Placeholder({:?})", placeholder)),
                 ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
             },
@@ -2104,7 +2104,9 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
 
             ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
-            | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+            | ty::RePlaceholder(ty::Placeholder {
+                bound: ty::BoundRegion { kind: br, .. }, ..
+            }) => {
                 if br.is_named() {
                     return true;
                 }
@@ -2181,7 +2183,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
             }
             ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
-            | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+            | ty::RePlaceholder(ty::Placeholder {
+                bound: ty::BoundRegion { kind: br, .. }, ..
+            }) => {
                 if let ty::BrNamed(_, name) = br && br.is_named() {
                     p!(write("{}", name));
                     return Ok(self);
@@ -2259,7 +2263,10 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> {
             ty::ReLateBound(db, br) if db >= self.current_index => {
                 *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br))
             }
-            ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => {
+            ty::RePlaceholder(ty::PlaceholderRegion {
+                bound: ty::BoundRegion { kind, .. },
+                ..
+            }) => {
                 // If this is an anonymous placeholder, don't rename. Otherwise, in some
                 // async fns, we get a `for<'r> Send` bound
                 match kind {
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index d4f058440b95..3eda2b2d9843 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -254,8 +254,8 @@ TrivialTypeTraversalAndLiftImpls! {
     crate::ty::AssocKind,
     crate::ty::AliasKind,
     crate::ty::AliasRelationDirection,
-    crate::ty::Placeholder,
-    crate::ty::Placeholder,
+    crate::ty::Placeholder,
+    crate::ty::Placeholder,
     crate::ty::ClosureKind,
     crate::ty::FreeRegion,
     crate::ty::InferTy,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 5ea77833af25..f6d79e94a511 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1632,7 +1632,7 @@ impl<'tcx> Region<'tcx> {
                 ty::ReLateBound(_, br) => br.kind.get_name(),
                 ty::ReFree(fr) => fr.bound_region.get_name(),
                 ty::ReStatic => Some(kw::StaticLifetime),
-                ty::RePlaceholder(placeholder) => placeholder.name.get_name(),
+                ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(),
                 _ => None,
             };
 
@@ -1650,7 +1650,7 @@ impl<'tcx> Region<'tcx> {
             ty::ReFree(fr) => fr.bound_region.is_named(),
             ty::ReStatic => true,
             ty::ReVar(..) => false,
-            ty::RePlaceholder(placeholder) => placeholder.name.is_named(),
+            ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(),
             ty::ReErased => false,
             ty::ReError(_) => false,
         }
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index 2e5a8b7debc5..848554e89efc 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -300,14 +300,20 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> {
             ty::Placeholder(placeholder) => match self.canonicalize_mode {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
                     universe: placeholder.universe,
-                    name: BoundTyKind::Anon(self.variables.len() as u32),
+                    bound: ty::BoundTy {
+                        var: ty::BoundVar::from_usize(self.variables.len()),
+                        kind: ty::BoundTyKind::Anon(self.variables.len() as u32),
+                    },
                 }),
                 CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
             },
             ty::Param(_) => match self.canonicalize_mode {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
                     universe: ty::UniverseIndex::ROOT,
-                    name: ty::BoundTyKind::Anon(self.variables.len() as u32),
+                    bound: ty::BoundTy {
+                        var: ty::BoundVar::from_usize(self.variables.len()),
+                        kind: ty::BoundTyKind::Anon(self.variables.len() as u32),
+                    },
                 }),
                 CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"),
             },
@@ -373,7 +379,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
                     ty::Placeholder {
                         universe: placeholder.universe,
-                        name: ty::BoundVar::from(self.variables.len()),
+                        bound: ty::BoundVar::from(self.variables.len()),
                     },
                     c.ty(),
                 ),
@@ -385,7 +391,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
                     ty::Placeholder {
                         universe: ty::UniverseIndex::ROOT,
-                        name: ty::BoundVar::from(self.variables.len()),
+                        bound: ty::BoundVar::from(self.variables.len()),
                     },
                     c.ty(),
                 ),
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index b8d9cff9c489..826fc63ca065 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -772,7 +772,7 @@ impl<'tcx> TypeFolder> for BoundVarReplacer<'_, 'tcx> {
             }
             ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
-                let p = ty::PlaceholderRegion { universe, name: br.kind };
+                let p = ty::PlaceholderRegion { universe, bound: br };
                 self.mapped_regions.insert(p, br);
                 self.infcx.tcx.mk_re_placeholder(p)
             }
@@ -790,7 +790,7 @@ impl<'tcx> TypeFolder> for BoundVarReplacer<'_, 'tcx> {
             }
             ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
-                let p = ty::PlaceholderType { universe, name: bound_ty.kind };
+                let p = ty::PlaceholderType { universe, bound: bound_ty };
                 self.mapped_types.insert(p, bound_ty);
                 self.infcx.tcx.mk_placeholder(p)
             }
@@ -809,7 +809,7 @@ impl<'tcx> TypeFolder> for BoundVarReplacer<'_, 'tcx> {
             }
             ty::ConstKind::Bound(debruijn, bound_const) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
-                let p = ty::PlaceholderConst { universe, name: bound_const };
+                let p = ty::PlaceholderConst { universe, bound: bound_const };
                 self.mapped_consts.insert(p, bound_const);
                 self.infcx.tcx.mk_const(p, ct.ty())
             }
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 527f6013a151..f7caf50c56ac 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -376,7 +376,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> {
             ty::Placeholder(_placeholder) => {
                 chalk_ir::TyKind::Placeholder(chalk_ir::PlaceholderIndex {
                     ui: chalk_ir::UniverseIndex { counter: _placeholder.universe.as_usize() },
-                    idx: _placeholder.name.expect_anon() as usize,
+                    idx: _placeholder.bound.var.as_usize(),
                 })
             }
             ty::Infer(_infer) => unimplemented!(),
@@ -484,7 +484,10 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty> {
             ),
             TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
                 universe: ty::UniverseIndex::from_usize(placeholder.ui.counter),
-                name: ty::BoundTyKind::Anon(placeholder.idx as u32),
+                bound: ty::BoundTy {
+                    var: ty::BoundVar::from_usize(placeholder.idx),
+                    kind: ty::BoundTyKind::Anon(placeholder.idx as u32),
+                },
             }),
             TyKind::InferenceVar(_, _) => unimplemented!(),
             TyKind::Dyn(_) => unimplemented!(),
@@ -536,7 +539,10 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime unimplemented!(),
             chalk_ir::LifetimeData::Placeholder(p) => tcx.mk_re_placeholder(ty::Placeholder {
                 universe: ty::UniverseIndex::from_usize(p.ui.counter),
-                name: ty::BoundRegionKind::BrAnon(p.idx as u32, None),
+                bound: ty::BoundRegion {
+                    var: ty::BoundVar::from_usize(p.idx),
+                    kind: ty::BoundRegionKind::BrAnon(p.idx as u32, None),
+                },
             }),
             chalk_ir::LifetimeData::Static => tcx.lifetimes.re_static,
             chalk_ir::LifetimeData::Erased => tcx.lifetimes.re_erased,
@@ -1090,7 +1096,10 @@ impl<'tcx> TypeFolder> for ParamsSubstitutor<'tcx> {
             ty::Param(param) => match self.list.iter().position(|r| r == ¶m) {
                 Some(idx) => self.tcx.mk_placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::from_usize(0),
-                    name: ty::BoundTyKind::Anon(idx as u32),
+                    bound: ty::BoundTy {
+                        var: ty::BoundVar::from_usize(idx),
+                        kind: ty::BoundTyKind::Anon(idx as u32),
+                    },
                 }),
                 None => {
                     self.list.push(param);
@@ -1098,7 +1107,10 @@ impl<'tcx> TypeFolder> for ParamsSubstitutor<'tcx> {
                     self.params.insert(idx as u32, param);
                     self.tcx.mk_placeholder(ty::PlaceholderType {
                         universe: ty::UniverseIndex::from_usize(0),
-                        name: ty::BoundTyKind::Anon(idx as u32),
+                        bound: ty::BoundTy {
+                            var: ty::BoundVar::from_usize(idx),
+                            kind: ty::BoundTyKind::Anon(idx as u32),
+                        },
                     })
                 }
             },
@@ -1156,12 +1168,13 @@ impl<'tcx> TypeFolder> for ReverseParamsSubstitutor<'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
-            ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, name }) => {
-                match self.params.get(&name.expect_anon()) {
-                    Some(&ty::ParamTy { index, name }) => self.tcx.mk_ty_param(index, name),
-                    None => t,
-                }
-            }
+            ty::Placeholder(ty::PlaceholderType {
+                universe: ty::UniverseIndex::ROOT,
+                bound: ty::BoundTy { kind: name, .. },
+            }) => match self.params.get(&name.expect_anon()) {
+                Some(&ty::ParamTy { index, name }) => self.tcx.mk_ty_param(index, name),
+                None => t,
+            },
 
             _ => t.super_fold_with(self),
         }
@@ -1190,7 +1203,7 @@ impl<'tcx> TypeVisitor> for PlaceholdersCollector {
         match t.kind() {
             ty::Placeholder(p) if p.universe == self.universe_index => {
                 self.next_ty_placeholder =
-                    self.next_ty_placeholder.max(p.name.expect_anon() as usize + 1);
+                    self.next_ty_placeholder.max(p.bound.kind.expect_anon() as usize + 1);
             }
 
             _ => (),
@@ -1202,7 +1215,7 @@ impl<'tcx> TypeVisitor> for PlaceholdersCollector {
     fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow {
         match *r {
             ty::RePlaceholder(p) if p.universe == self.universe_index => {
-                if let ty::BoundRegionKind::BrAnon(anon, _) = p.name {
+                if let ty::BoundRegionKind::BrAnon(anon, _) = p.bound.kind {
                     self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
                 }
                 // FIXME: This doesn't seem to handle BrNamed at all?

From 167b70692ba2a97521237d36b487fbfccd3fb72b Mon Sep 17 00:00:00 2001
From: Jack Huey <31162821+jackh726@users.noreply.github.com>
Date: Thu, 6 Apr 2023 21:26:38 -0400
Subject: [PATCH 197/267] Remove expect_anon and expect_anon_placeholder in
 favor of var

---
 compiler/rustc_middle/src/infer/canonical.rs   | 10 ++++------
 compiler/rustc_middle/src/ty/sty.rs            | 18 ------------------
 .../src/solve/eval_ctxt/canonical.rs           |  2 +-
 compiler/rustc_traits/src/chalk/lowering.rs    | 16 +++++++---------
 4 files changed, 12 insertions(+), 34 deletions(-)

diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index d3f71e75d991..6bbf9690bf64 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -149,17 +149,15 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
         }
     }
 
-    pub fn expect_anon_placeholder(self) -> u32 {
+    pub fn expect_placeholder_index(self) -> usize {
         match self.kind {
             CanonicalVarKind::Ty(_)
             | CanonicalVarKind::Region(_)
             | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
 
-            CanonicalVarKind::PlaceholderRegion(placeholder) => {
-                placeholder.bound.kind.expect_anon()
-            }
-            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.kind.expect_anon(),
-            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_u32(),
+            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(),
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(),
+            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_usize(),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index f6d79e94a511..76194f350f5c 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -107,15 +107,6 @@ impl BoundRegionKind {
             _ => None,
         }
     }
-
-    pub fn expect_anon(&self) -> u32 {
-        match *self {
-            BoundRegionKind::BrNamed(_, _) | BoundRegionKind::BrEnv => {
-                bug!("expected anon region: {self:?}")
-            }
-            BoundRegionKind::BrAnon(idx, _) => idx,
-        }
-    }
 }
 
 pub trait Article {
@@ -1537,15 +1528,6 @@ pub enum BoundTyKind {
     Param(DefId, Symbol),
 }
 
-impl BoundTyKind {
-    pub fn expect_anon(self) -> u32 {
-        match self {
-            BoundTyKind::Anon(i) => i,
-            _ => bug!(),
-        }
-    }
-}
-
 impl From for BoundTy {
     fn from(var: BoundVar) -> Self {
         BoundTy { var, kind: BoundTyKind::Anon(var.as_u32()) }
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index ee90488730a6..714b6dfb7176 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -188,7 +188,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 } else {
                     // For placeholders which were already part of the input, we simply map this
                     // universal bound variable back the placeholder of the input.
-                    original_values[info.expect_anon_placeholder() as usize]
+                    original_values[info.expect_placeholder_index()]
                 }
             },
         ));
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index f7caf50c56ac..c59e496eb0ac 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -1168,13 +1168,12 @@ impl<'tcx> TypeFolder> for ReverseParamsSubstitutor<'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
-            ty::Placeholder(ty::PlaceholderType {
-                universe: ty::UniverseIndex::ROOT,
-                bound: ty::BoundTy { kind: name, .. },
-            }) => match self.params.get(&name.expect_anon()) {
-                Some(&ty::ParamTy { index, name }) => self.tcx.mk_ty_param(index, name),
-                None => t,
-            },
+            ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, bound }) => {
+                match self.params.get(&bound.var.as_u32()) {
+                    Some(&ty::ParamTy { index, name }) => self.tcx.mk_ty_param(index, name),
+                    None => t,
+                }
+            }
 
             _ => t.super_fold_with(self),
         }
@@ -1202,8 +1201,7 @@ impl<'tcx> TypeVisitor> for PlaceholdersCollector {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow {
         match t.kind() {
             ty::Placeholder(p) if p.universe == self.universe_index => {
-                self.next_ty_placeholder =
-                    self.next_ty_placeholder.max(p.bound.kind.expect_anon() as usize + 1);
+                self.next_ty_placeholder = self.next_ty_placeholder.max(p.bound.var.as_usize() + 1);
             }
 
             _ => (),

From e4edf00f12527bdaa20879f0ace46a1d7f46eb6d Mon Sep 17 00:00:00 2001
From: Jack Huey <31162821+jackh726@users.noreply.github.com>
Date: Thu, 6 Apr 2023 21:40:43 -0400
Subject: [PATCH 198/267] Don't use BrAnon index in diagnostics

---
 compiler/rustc_infer/src/errors/note_and_explain.rs   | 5 ++---
 compiler/rustc_infer/src/infer/error_reporting/mod.rs | 4 ++--
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index ef543b1fb935..9058ed7e45b3 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -90,9 +90,8 @@ impl<'a> DescriptionCtx<'a> {
                             };
                             me.span = Some(sp);
                         }
-                        ty::BrAnon(idx, span) => {
-                            me.kind = "anon_num_here";
-                            me.num_arg = idx+1;
+                        ty::BrAnon(_, span) => {
+                            me.kind = "defined_here";
                             me.span = match span {
                                 Some(_) => span,
                                 None => Some(tcx.def_span(scope)),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 40d576068171..ad495ee9fc58 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -226,8 +226,8 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
                         };
                         (text, sp)
                     }
-                    ty::BrAnon(idx, span) => (
-                        format!("the anonymous lifetime #{} defined here", idx + 1),
+                    ty::BrAnon(_, span) => (
+                        "the anonymous lifetime as defined here".to_string(),
                         match span {
                             Some(span) => span,
                             None => tcx.def_span(scope)

From f0edcc8a6f457cbb27ae4559719cc42a5610378e Mon Sep 17 00:00:00 2001
From: Jack Huey <31162821+jackh726@users.noreply.github.com>
Date: Thu, 6 Apr 2023 22:07:21 -0400
Subject: [PATCH 199/267] Remove index from BrAnon

---
 compiler/rustc_borrowck/src/type_check/mod.rs |  4 +--
 .../src/type_check/relate_tys.rs              |  2 +-
 .../rustc_hir_analysis/src/check/intrinsic.rs | 10 +++---
 .../src/generator_interior/mod.rs             |  6 ++--
 .../src/errors/note_and_explain.rs            |  2 +-
 .../src/infer/canonical/canonicalizer.rs      |  2 +-
 .../src/infer/error_reporting/mod.rs          |  6 ++--
 .../nice_region_error/placeholder_relation.rs |  4 +--
 compiler/rustc_middle/src/infer/canonical.rs  |  2 +-
 compiler/rustc_middle/src/mir/query.rs        |  6 ++--
 compiler/rustc_middle/src/ty/context.rs       | 12 +++----
 compiler/rustc_middle/src/ty/fold.rs          |  4 +--
 .../rustc_middle/src/ty/structural_impls.rs   |  2 +-
 compiler/rustc_middle/src/ty/sty.rs           |  2 +-
 compiler/rustc_symbol_mangling/src/v0.rs      | 33 +++++++------------
 .../src/solve/canonicalize.rs                 |  2 +-
 .../src/traits/select/mod.rs                  |  4 +--
 compiler/rustc_traits/src/chalk/db.rs         |  2 +-
 compiler/rustc_traits/src/chalk/lowering.rs   | 19 ++++++-----
 .../impl-trait/impl-fn-hrtb-bounds-2.stderr   |  2 +-
 .../escape-argument-callee.stderr             |  2 +-
 .../escape-argument.stderr                    |  2 +-
 ...pagate-approximated-fail-no-postdom.stderr |  2 +-
 .../propagate-approximated-ref.stderr         |  2 +-
 ...er-to-static-comparing-against-free.stderr |  4 +--
 ...oximated-shorter-to-static-no-bound.stderr |  2 +-
 ...mated-shorter-to-static-wrong-bound.stderr |  2 +-
 .../propagate-approximated-val.stderr         |  2 +-
 .../propagate-despite-same-free-region.stderr |  2 +-
 ...ail-to-approximate-longer-no-bounds.stderr |  2 +-
 ...-to-approximate-longer-wrong-bounds.stderr |  2 +-
 .../return-wrong-bound-region.stderr          |  2 +-
 ...ram-closure-approximate-lower-bound.stderr |  4 +--
 33 files changed, 68 insertions(+), 88 deletions(-)

diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 2fc4e32ecb24..1a5638069d2c 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1342,9 +1342,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                     let region_ctxt_fn = || {
                         let reg_info = match br.kind {
-                            ty::BoundRegionKind::BrAnon(_, Some(span)) => {
-                                BoundRegionInfo::Span(span)
-                            }
+                            ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span),
                             ty::BoundRegionKind::BrAnon(..) => {
                                 BoundRegionInfo::Name(Symbol::intern("anon"))
                             }
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index cdc916457ca6..83429f2ddef3 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -124,7 +124,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
             .placeholder_region(self.type_checker.infcx, placeholder);
 
         let reg_info = match placeholder.bound.kind {
-            ty::BoundRegionKind::BrAnon(_, Some(span)) => BoundRegionInfo::Span(span),
+            ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span),
             ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(Symbol::intern("anon")),
             ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
             ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(Symbol::intern("env")),
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 1b7475486dce..854974d1605a 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -139,14 +139,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     let name_str = intrinsic_name.as_str();
 
     let bound_vars = tcx.mk_bound_variable_kinds(&[
-        ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
+        ty::BoundVariableKind::Region(ty::BrAnon(None)),
         ty::BoundVariableKind::Region(ty::BrEnv),
     ]);
     let mk_va_list_ty = |mutbl| {
         tcx.lang_items().va_list().map(|did| {
             let region = tcx.mk_re_late_bound(
                 ty::INNERMOST,
-                ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
+                ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
             );
             let env_region = tcx.mk_re_late_bound(
                 ty::INNERMOST,
@@ -387,8 +387,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 );
                 let discriminant_def_id = assoc_items[0];
 
-                let br =
-                    ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
+                let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
                 (
                     1,
                     vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))],
@@ -440,8 +439,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
 
             sym::raw_eq => {
-                let br =
-                    ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
+                let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
                 let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0));
                 (1, vec![param_ty; 2], tcx.types.bool)
             }
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 9ecc870a70db..84ed8f3780e1 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -240,7 +240,7 @@ pub fn resolve_interior<'a, 'tcx>(
 
             let mut counter = 0;
             let mut mk_bound_region = |span| {
-                let kind = ty::BrAnon(counter, span);
+                let kind = ty::BrAnon(span);
                 let var = ty::BoundVar::from_u32(counter);
                 counter += 1;
                 ty::BoundRegion { var, kind }
@@ -263,7 +263,7 @@ pub fn resolve_interior<'a, 'tcx>(
                     }
                     ty::ReLateBound(_, ty::BoundRegion { kind, .. })
                     | ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
-                        ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span),
+                        ty::BoundRegionKind::BrAnon(span) => mk_bound_region(span),
                         ty::BoundRegionKind::BrNamed(def_id, _) => {
                             mk_bound_region(Some(fcx.tcx.def_span(def_id)))
                         }
@@ -294,7 +294,7 @@ pub fn resolve_interior<'a, 'tcx>(
             FnMutDelegate {
                 regions: &mut |br| {
                     let kind = match br.kind {
-                        ty::BrAnon(_, span) => ty::BrAnon(counter, span),
+                        ty::BrAnon(span) => ty::BrAnon(span),
                         _ => br.kind,
                     };
                     let var = ty::BoundVar::from_usize(bound_vars.len());
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 9058ed7e45b3..30f6af74b83e 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -90,7 +90,7 @@ impl<'a> DescriptionCtx<'a> {
                             };
                             me.span = Some(sp);
                         }
-                        ty::BrAnon(_, span) => {
+                        ty::BrAnon(span) => {
                             me.kind = "defined_here";
                             me.span = match span {
                                 Some(_) => span,
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 3bbd01f82736..e808911a38b1 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -772,7 +772,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
         let var = self.canonical_var(info, r.into());
-        let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) };
+        let br = ty::BoundRegion { var, kind: ty::BrAnon(None) };
         self.interner().mk_re_late_bound(self.binder_index, br)
     }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ad495ee9fc58..86fca9797d02 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -174,11 +174,11 @@ fn msg_span_from_named_region<'tcx>(
             ..
         }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(_, Some(span)), .. },
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(Some(span)), .. },
             ..
         }) => (format!("the anonymous lifetime defined here"), Some(span)),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(_, None), .. },
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(None), .. },
             ..
         }) => (format!("an anonymous lifetime"), None),
         _ => bug!("{:?}", region),
@@ -226,7 +226,7 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
                         };
                         (text, sp)
                     }
-                    ty::BrAnon(_, span) => (
+                    ty::BrAnon(span) => (
                         "the anonymous lifetime as defined here".to_string(),
                         match span {
                             Some(span) => span,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
index 06aff52681fd..8a78a1956c99 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
@@ -36,14 +36,14 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                     ty::BrNamed(def_id, symbol) => {
                         (Some(self.tcx().def_span(def_id)), Some(symbol))
                     }
-                    ty::BrAnon(_, span) => (*span, None),
+                    ty::BrAnon(span) => (*span, None),
                     ty::BrEnv => (None, None),
                 };
                 let (sup_span, sup_symbol) = match sup_name {
                     ty::BrNamed(def_id, symbol) => {
                         (Some(self.tcx().def_span(def_id)), Some(symbol))
                     }
-                    ty::BrAnon(_, span) => (*span, None),
+                    ty::BrAnon(span) => (*span, None),
                     ty::BrEnv => (None, None),
                 };
                 let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 6bbf9690bf64..f668c4e77bea 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -411,7 +411,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
                         CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
                             let br = ty::BoundRegion {
                                 var: ty::BoundVar::from_usize(i),
-                                kind: ty::BrAnon(i as u32, None),
+                                kind: ty::BrAnon(None),
                             };
                             tcx.mk_re_late_bound(ty::INNERMOST, br).into()
                         }
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 68561cf6dd77..cfdf1dcf5c02 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -411,10 +411,8 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
     pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
         let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
             ty::ReVar(vid) => {
-                let br = ty::BoundRegion {
-                    var: ty::BoundVar::new(vid.index()),
-                    kind: ty::BrAnon(vid.as_u32(), None),
-                };
+                let br =
+                    ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) };
                 tcx.mk_re_late_bound(depth, br)
             }
             _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8d0aa622244c..299b1bf1d96e 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -311,7 +311,7 @@ pub struct CommonLifetimes<'tcx> {
     pub re_vars: Vec>,
 
     /// Pre-interned values of the form:
-    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })`
+    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(None) })`
     /// for small values of `i` and `v`.
     pub re_late_bounds: Vec>>,
 }
@@ -386,10 +386,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
                     .map(|v| {
                         mk(ty::ReLateBound(
                             ty::DebruijnIndex::from(i),
-                            ty::BoundRegion {
-                                var: ty::BoundVar::from(v),
-                                kind: ty::BrAnon(v, None),
-                            },
+                            ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon(None) },
                         ))
                     })
                     .collect()
@@ -2075,10 +2072,9 @@ impl<'tcx> TyCtxt<'tcx> {
         bound_region: ty::BoundRegion,
     ) -> Region<'tcx> {
         // Use a pre-interned one when possible.
-        if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region
-            && var.as_u32() == v
+        if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region
             && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
-            && let Some(re) = inner.get(v as usize).copied()
+            && let Some(re) = inner.get(var.as_usize()).copied()
         {
             re
         } else {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 6205e2bf24dd..b5c2bc609529 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -379,9 +379,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 let index = entry.index();
                 let var = ty::BoundVar::from_usize(index);
                 let kind = entry
-                    .or_insert_with(|| {
-                        ty::BoundVariableKind::Region(ty::BrAnon(index as u32, None))
-                    })
+                    .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None)))
                     .expect_region();
                 let br = ty::BoundRegion { var, kind };
                 self.tcx.mk_re_late_bound(ty::INNERMOST, br)
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 3eda2b2d9843..5c604bb6db27 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
 impl fmt::Debug for ty::BoundRegionKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"),
+            ty::BrAnon(span) => write!(f, "BrAnon({span:?})"),
             ty::BrNamed(did, name) => {
                 if did.is_crate_root() {
                     write!(f, "BrNamed({})", name)
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 76194f350f5c..7e526e631ce6 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -60,7 +60,7 @@ pub struct FreeRegion {
 #[derive(HashStable)]
 pub enum BoundRegionKind {
     /// An anonymous region parameter for a given fn (&T)
-    BrAnon(u32, Option),
+    BrAnon(Option),
 
     /// Named region parameters for functions (a in &'a T)
     ///
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index cac7ff72267d..ee883285531d 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::base_n;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::intern::Interned;
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
@@ -81,9 +81,9 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
 struct BinderLevel {
     /// The range of distances from the root of what's
     /// being printed, to the lifetimes in a binder.
-    /// Specifically, a `BrAnon(i)` lifetime has depth
-    /// `lifetime_depths.start + i`, going away from the
-    /// the root and towards its use site, as `i` increases.
+    /// Specifically, a `BrAnon` lifetime has depth
+    /// `lifetime_depths.start + index`, going away from the
+    /// the root and towards its use site, as the var index increases.
     /// This is used to flatten rustc's pairing of `BrAnon`
     /// (intra-binder disambiguation) with a `DebruijnIndex`
     /// (binder addressing), to "true" de Bruijn indices,
@@ -208,24 +208,15 @@ impl<'tcx> SymbolMangler<'tcx> {
     where
         T: TypeVisitable>,
     {
-        // FIXME(non-lifetime-binders): What to do here?
-        let regions = if value.has_late_bound_regions() {
-            self.tcx.collect_referenced_late_bound_regions(value)
-        } else {
-            FxHashSet::default()
-        };
-
         let mut lifetime_depths =
             self.binders.last().map(|b| b.lifetime_depths.end).map_or(0..0, |i| i..i);
 
-        let lifetimes = regions
-            .into_iter()
-            .map(|br| match br {
-                ty::BrAnon(i, _) => i,
-                _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value),
-            })
-            .max()
-            .map_or(0, |max| max + 1);
+        // FIXME(non-lifetime-binders): What to do here?
+        let lifetimes = value
+            .bound_vars()
+            .iter()
+            .filter(|var| matches!(var, ty::BoundVariableKind::Region(..)))
+            .count() as u32;
 
         self.push_opt_integer_62("G", lifetimes as u64);
         lifetime_depths.end += lifetimes;
@@ -338,9 +329,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
             // Late-bound lifetimes use indices starting at 1,
             // see `BinderLevel` for more details.
-            ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i, _), .. }) => {
+            ty::ReLateBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon(_) }) => {
                 let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
-                let depth = binder.lifetime_depths.start + i;
+                let depth = binder.lifetime_depths.start + var.as_u32();
 
                 1 + (self.binders.last().unwrap().lifetime_depths.end - 1 - depth)
             }
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index 848554e89efc..60d96e28cd38 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -257,7 +257,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> {
             self.primitive_var_infos.push(CanonicalVarInfo { kind });
             var
         });
-        let br = ty::BoundRegion { var, kind: BrAnon(var.as_u32(), None) };
+        let br = ty::BoundRegion { var, kind: BrAnon(None) };
         self.interner().mk_re_late_bound(self.binder_index, br)
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index b58e62536d60..d2d75d2aa4cc 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -3017,7 +3017,7 @@ fn bind_generator_hidden_types_above<'tcx>(
                     if let ty::ReErased = r.kind() {
                         let br = ty::BoundRegion {
                             var: ty::BoundVar::from_u32(counter),
-                            kind: ty::BrAnon(counter, None),
+                            kind: ty::BrAnon(None),
                         };
                         counter += 1;
                         r = tcx.mk_re_late_bound(current_depth, br);
@@ -3033,7 +3033,7 @@ fn bind_generator_hidden_types_above<'tcx>(
         debug_assert!(!hidden_types.has_erased_regions());
     }
     let bound_vars = tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain(
-        (num_bound_variables..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
+        (num_bound_variables..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))),
     ));
     ty::Binder::bind_with_vars(hidden_types, bound_vars)
 }
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index f8c8f744e6d5..9683e48478ed 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -730,7 +730,7 @@ fn bound_vars_for_item(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
         ty::GenericParamDefKind::Lifetime => {
             let br = ty::BoundRegion {
                 var: ty::BoundVar::from_usize(substs.len()),
-                kind: ty::BrAnon(substs.len() as u32, None),
+                kind: ty::BrAnon(None),
             };
             tcx.mk_re_late_bound(ty::INNERMOST, br).into()
         }
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index c59e496eb0ac..373082d8092a 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -533,7 +533,7 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime unimplemented!(),
@@ -541,7 +541,7 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime tcx.lifetimes.re_static,
@@ -976,7 +976,7 @@ impl<'tcx> TypeVisitor> for BoundVarsCollector<'tcx> {
                     }
                 }
 
-                ty::BoundRegionKind::BrAnon(var, _) => match self.parameters.entry(var) {
+                ty::BoundRegionKind::BrAnon(_) => match self.parameters.entry(br.var.as_u32()) {
                     Entry::Vacant(entry) => {
                         entry.insert(chalk_ir::VariableKind::Lifetime);
                     }
@@ -1036,8 +1036,8 @@ impl<'a, 'tcx> TypeFolder> for NamedBoundVarSubstitutor<'a, 'tcx> {
         match *r {
             ty::ReLateBound(index, br) if index == self.binder_index => match br.kind {
                 ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
-                    Some(idx) => {
-                        let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) };
+                    Some(_) => {
+                        let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(None) };
                         return self.tcx.mk_re_late_bound(index, new_br);
                     }
                     None => panic!("Missing `BrNamed`."),
@@ -1127,7 +1127,7 @@ impl<'tcx> TypeFolder> for ParamsSubstitutor<'tcx> {
                 Some(idx) => {
                     let br = ty::BoundRegion {
                         var: ty::BoundVar::from_u32(*idx),
-                        kind: ty::BrAnon(*idx, None),
+                        kind: ty::BrAnon(None),
                     };
                     self.tcx.mk_re_late_bound(self.binder_index, br)
                 }
@@ -1135,7 +1135,7 @@ impl<'tcx> TypeFolder> for ParamsSubstitutor<'tcx> {
                     let idx = self.named_regions.len() as u32;
                     let br = ty::BoundRegion {
                         var: ty::BoundVar::from_u32(idx),
-                        kind: ty::BrAnon(idx, None),
+                        kind: ty::BrAnon(None),
                     };
                     self.named_regions.insert(_re.def_id, idx);
                     self.tcx.mk_re_late_bound(self.binder_index, br)
@@ -1213,8 +1213,9 @@ impl<'tcx> TypeVisitor> for PlaceholdersCollector {
     fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow {
         match *r {
             ty::RePlaceholder(p) if p.universe == self.universe_index => {
-                if let ty::BoundRegionKind::BrAnon(anon, _) = p.bound.kind {
-                    self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
+                if let ty::BoundRegionKind::BrAnon(_) = p.bound.kind {
+                    self.next_anon_region_placeholder =
+                        self.next_anon_region_placeholder.max(p.bound.var.as_u32());
                 }
                 // FIXME: This doesn't seem to handle BrNamed at all?
             }
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
index d56e1273f241..835f7f765600 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
@@ -6,7 +6,7 @@ LL | fn a() -> impl Fn(&u8) -> impl Debug {
 LL |     |x| x
    |     --- ^
    |     |
-   |     hidden type `&u8` captures the anonymous lifetime #1 defined here
+   |     hidden type `&u8` captures the anonymous lifetime as defined here
 
 error: aborting due to previous error
 
diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr
index 363ddfaffe06..c0d95ddaa079 100644
--- a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) i32)),
+               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) i32)),
                (),
            ]
 
diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr
index 5a8462d4dc56..61e2a1ea6f01 100644
--- a/tests/ui/nll/closure-requirements/escape-argument.stderr
+++ b/tests/ui/nll/closure-requirements/escape-argument.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32)),
+               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32)),
                (),
            ]
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 7da6ce58bf7f..5a7b12732df6 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -6,7 +6,7 @@ LL |         |_outlives1, _outlives2, _outlives3, x, y| {
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)),
+               for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#4r
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index 993687605c4a..db2ecc779ef9 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)),
+               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 721cd45ded98..1d9dafbe55f6 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -6,7 +6,7 @@ LL |     foo(cell, |cell_a, cell_x| {
    |
    = note: defining type: case1::{closure#0} with closure substs [
                i32,
-               for extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>)),
+               for extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)),
                (),
            ]
 
@@ -36,7 +36,7 @@ LL |     foo(cell, |cell_a, cell_x| {
    |
    = note: defining type: case2::{closure#0} with closure substs [
                i32,
-               for extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>)),
+               for extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: number of external vids: 2
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index 43dfc3bb9f83..85f7fe35c0aa 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) u32>)),
+               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#2r
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index 96c734226eff..7194843e203f 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)),
+               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 03dbd686e497..71f8a1c67c67 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)),
+               for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index d716d3de2a11..e1cb97b1c7d9 100644
--- a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -6,7 +6,7 @@ LL |         |_outlives1, _outlives2, x, y| {
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)),
+               for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index b924873fca6f..b66e8391c013 100644
--- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)),
+               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#2r
diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 9b25efd0b66b..49641fd06fdb 100644
--- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)),
+               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index 6db72b886325..4e34ba516595 100644
--- a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -6,7 +6,7 @@ LL |     expect_sig(|a, b| b); // ought to return `a`
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) i32,
+               for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) i32,
                (),
            ]
 
diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index a442cf12d820..2c4a0597554a 100644
--- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -6,7 +6,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    |
    = note: defining type: generic::::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) T)),
+               for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)),
                (),
            ]
    = note: number of external vids: 2
@@ -28,7 +28,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    |
    = note: defining type: generic_fail::::{closure#0} with closure substs [
                i16,
-               for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) T)),
+               for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)),
                (),
            ]
    = note: late-bound region is '_#2r

From b15195a304ff4404c4f67f19b5e1dc3efc587a6d Mon Sep 17 00:00:00 2001
From: Jack Huey <31162821+jackh726@users.noreply.github.com>
Date: Thu, 6 Apr 2023 22:32:09 -0400
Subject: [PATCH 200/267] Remove u32 on BoundTyKind::Anon

---
 compiler/rustc_infer/src/infer/mod.rs                  |  2 +-
 compiler/rustc_middle/src/ty/fold.rs                   |  4 +---
 compiler/rustc_middle/src/ty/print/pretty.rs           |  6 ++----
 compiler/rustc_middle/src/ty/sty.rs                    |  4 ++--
 .../rustc_trait_selection/src/solve/canonicalize.rs    |  6 +++---
 .../src/solve/trait_goals/structural_traits.rs         |  8 +++-----
 compiler/rustc_traits/src/chalk/lowering.rs            | 10 +++++-----
 7 files changed, 17 insertions(+), 23 deletions(-)

diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index ac8349e4c3ab..b4f2ad0bb343 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -2139,7 +2139,7 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
                     universe: ty::UniverseIndex::ROOT,
                     bound: ty::BoundTy {
                         var: ty::BoundVar::from_u32(idx),
-                        kind: ty::BoundTyKind::Anon(idx),
+                        kind: ty::BoundTyKind::Anon,
                     },
                 })
             } else {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index b5c2bc609529..203e16bea27f 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -389,9 +389,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 let index = entry.index();
                 let var = ty::BoundVar::from_usize(index);
                 let kind = entry
-                    .or_insert_with(|| {
-                        ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon(index as u32))
-                    })
+                    .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
                     .expect_ty();
                 self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind })
             }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index fb681f1114d6..bc0ccc1ebc3a 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -701,9 +701,7 @@ pub trait PrettyPrinter<'tcx>:
             ty::Error(_) => p!("[type error]"),
             ty::Param(ref param_ty) => p!(print(param_ty)),
             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
-                ty::BoundTyKind::Anon(bv) => {
-                    self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))?
-                }
+                ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
                 ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
                     true if debruijn == ty::INNERMOST => p!(write("^{}", s)),
                     true => p!(write("^{}_{}", debruijn.index(), s)),
@@ -740,7 +738,7 @@ pub trait PrettyPrinter<'tcx>:
                 }
             }
             ty::Placeholder(placeholder) => match placeholder.bound.kind {
-                ty::BoundTyKind::Anon(_) => p!(write("Placeholder({:?})", placeholder)),
+                ty::BoundTyKind::Anon => p!(write("Placeholder({:?})", placeholder)),
                 ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
             },
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 7e526e631ce6..d542d93b8c81 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1524,13 +1524,13 @@ pub struct BoundTy {
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum BoundTyKind {
-    Anon(u32),
+    Anon,
     Param(DefId, Symbol),
 }
 
 impl From for BoundTy {
     fn from(var: BoundVar) -> Self {
-        BoundTy { var, kind: BoundTyKind::Anon(var.as_u32()) }
+        BoundTy { var, kind: BoundTyKind::Anon }
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index 60d96e28cd38..55025e2e72b9 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -302,7 +302,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> {
                     universe: placeholder.universe,
                     bound: ty::BoundTy {
                         var: ty::BoundVar::from_usize(self.variables.len()),
-                        kind: ty::BoundTyKind::Anon(self.variables.len() as u32),
+                        kind: ty::BoundTyKind::Anon,
                     },
                 }),
                 CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
@@ -312,7 +312,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> {
                     universe: ty::UniverseIndex::ROOT,
                     bound: ty::BoundTy {
                         var: ty::BoundVar::from_usize(self.variables.len()),
-                        kind: ty::BoundTyKind::Anon(self.variables.len() as u32),
+                        kind: ty::BoundTyKind::Anon,
                     },
                 }),
                 CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"),
@@ -351,7 +351,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> {
                 var
             }),
         );
-        let bt = ty::BoundTy { var, kind: BoundTyKind::Anon(var.index() as u32) };
+        let bt = ty::BoundTy { var, kind: BoundTyKind::Anon };
         self.interner().mk_bound(self.binder_index, bt)
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
index 4a3b7e42bac1..9e851b788a54 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
@@ -95,17 +95,15 @@ fn replace_erased_lifetimes_with_bound_vars<'tcx>(
     let mut counter = 0;
     let ty = tcx.fold_regions(ty, |mut r, current_depth| {
         if let ty::ReErased = r.kind() {
-            let br = ty::BoundRegion {
-                var: ty::BoundVar::from_u32(counter),
-                kind: ty::BrAnon(counter, None),
-            };
+            let br =
+                ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) };
             counter += 1;
             r = tcx.mk_re_late_bound(current_depth, br);
         }
         r
     });
     let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
-        (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
+        (0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))),
     );
     ty::Binder::bind_with_vars(ty, bound_vars)
 }
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 373082d8092a..2be72879b7b1 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -479,14 +479,14 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty> {
                 ty::DebruijnIndex::from_usize(bound.debruijn.depth() as usize),
                 ty::BoundTy {
                     var: ty::BoundVar::from_usize(bound.index),
-                    kind: ty::BoundTyKind::Anon(bound.index as u32),
+                    kind: ty::BoundTyKind::Anon,
                 },
             ),
             TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
                 universe: ty::UniverseIndex::from_usize(placeholder.ui.counter),
                 bound: ty::BoundTy {
                     var: ty::BoundVar::from_usize(placeholder.idx),
-                    kind: ty::BoundTyKind::Anon(placeholder.idx as u32),
+                    kind: ty::BoundTyKind::Anon,
                 },
             }),
             TyKind::InferenceVar(_, _) => unimplemented!(),
@@ -691,7 +691,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders TypeFolder> for ParamsSubstitutor<'tcx> {
                     universe: ty::UniverseIndex::from_usize(0),
                     bound: ty::BoundTy {
                         var: ty::BoundVar::from_usize(idx),
-                        kind: ty::BoundTyKind::Anon(idx as u32),
+                        kind: ty::BoundTyKind::Anon,
                     },
                 }),
                 None => {
@@ -1109,7 +1109,7 @@ impl<'tcx> TypeFolder> for ParamsSubstitutor<'tcx> {
                         universe: ty::UniverseIndex::from_usize(0),
                         bound: ty::BoundTy {
                             var: ty::BoundVar::from_usize(idx),
-                            kind: ty::BoundTyKind::Anon(idx as u32),
+                            kind: ty::BoundTyKind::Anon,
                         },
                     })
                 }

From 5cad51c0c5a21c94bb119277131ac4b60576041a Mon Sep 17 00:00:00 2001
From: Michael Howell 
Date: Thu, 6 Apr 2023 20:25:07 -0700
Subject: [PATCH 201/267] rustdoc: add test and bug fix for theme defaults

---
 src/librustdoc/html/static/js/storage.js |  1 +
 tests/rustdoc-gui/theme-defaults.goml    | 24 ++++++++++++++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 tests/rustdoc-gui/theme-defaults.goml

diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 8d82b5b78edb..67d3981ce07c 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -158,6 +158,7 @@ const updateTheme = (function() {
         if (getSettingValue("use-system-theme") !== "false") {
             const lightTheme = getSettingValue("preferred-light-theme") || "light";
             const darkTheme = getSettingValue("preferred-dark-theme") || "dark";
+            updateLocalStorage("use-system-theme", "true");
 
             if (mql.matches) {
                 use(darkTheme, true);
diff --git a/tests/rustdoc-gui/theme-defaults.goml b/tests/rustdoc-gui/theme-defaults.goml
new file mode 100644
index 000000000000..d5ed536b1a96
--- /dev/null
+++ b/tests/rustdoc-gui/theme-defaults.goml
@@ -0,0 +1,24 @@
+// Ensure that the theme picker always starts with the actual defaults.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+click: "#settings-menu"
+wait-for: "#theme-system-preference"
+assert: "#theme-system-preference:checked"
+assert: "#preferred-light-theme-light:checked"
+assert: "#preferred-dark-theme-dark:checked"
+assert-false: "#preferred-dark-theme-ayu:checked"
+
+// Test legacy migration from old theme setup without system-preference matching.
+// See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
+local-storage: {
+    "rustdoc-preferred-light-theme": null,
+    "rustdoc-preferred-dark-theme": null,
+    "rustdoc-use-system-theme": null,
+    "rustdoc-theme": "ayu"
+}
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+click: "#settings-menu"
+wait-for: "#theme-system-preference"
+assert: "#theme-system-preference:checked"
+assert: "#preferred-light-theme-light:checked"
+assert-false: "#preferred-dark-theme-dark:checked"
+assert: "#preferred-dark-theme-ayu:checked"

From d5b1ef1c3f5f5fae73baee4b463e264842c8a73d Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Mon, 3 Apr 2023 21:41:16 +0000
Subject: [PATCH 202/267] Use smart-resolve when checking for trait in RHS of
 UFCS

---
 compiler/rustc_resolve/src/late.rs            |  32 ++-
 tests/ui/parser/dyn-trait-compatibility.rs    |   2 +-
 .../ui/parser/dyn-trait-compatibility.stderr  |  16 +-
 .../edition-lint-fully-qualified-paths.fixed  |   6 +-
 .../edition-lint-fully-qualified-paths.rs     |   6 +-
 .../edition-lint-fully-qualified-paths.stderr |  13 +-
 .../assoc_type_bound_with_struct.rs           |   2 +-
 .../assoc_type_bound_with_struct.stderr       |  14 +-
 tests/ui/ufcs/ufcs-partially-resolved.rs      |  44 ++--
 tests/ui/ufcs/ufcs-partially-resolved.stderr  | 190 +++++++++++-------
 10 files changed, 205 insertions(+), 120 deletions(-)

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 19f46d45af67..b1a696d093eb 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -122,6 +122,12 @@ pub(crate) enum ConstantItemKind {
     Static,
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+enum RecordPartialRes {
+    Yes,
+    No,
+}
+
 /// The rib kind restricts certain accesses,
 /// e.g. to a `Res::Local` of an outer item.
 #[derive(Copy, Clone, Debug)]
@@ -2682,6 +2688,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 &path,
                 PathSource::Trait(AliasPossibility::No),
                 Finalize::new(trait_ref.ref_id, trait_ref.path.span),
+                RecordPartialRes::Yes,
             );
             self.diagnostic_metadata.currently_processing_impl_trait = None;
             if let Some(def_id) = res.expect_full_res().opt_def_id() {
@@ -3420,6 +3427,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             &Segment::from_path(path),
             source,
             Finalize::new(id, path.span),
+            RecordPartialRes::Yes,
         );
     }
 
@@ -3430,6 +3438,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         path: &[Segment],
         source: PathSource<'ast>,
         finalize: Finalize,
+        record_partial_res: RecordPartialRes,
     ) -> PartialRes {
         let ns = source.namespace();
 
@@ -3636,7 +3645,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             _ => report_errors(self, None),
         };
 
-        if !matches!(source, PathSource::TraitItem(..)) {
+        if record_partial_res == RecordPartialRes::Yes {
             // Avoid recording definition of `A::B` in `::B::C`.
             self.r.record_partial_res(node_id, partial_res);
             self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span);
@@ -3740,7 +3749,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 )));
             }
 
-            // Make sure `A::B` in `::C` is a trait item.
+            let num_privacy_errors = self.r.privacy_errors.len();
+            // Make sure that `A` in `::B::C` is a trait.
+            let trait_res = self.smart_resolve_path_fragment(
+                &None,
+                &path[..qself.position],
+                PathSource::Trait(AliasPossibility::No),
+                Finalize::new(finalize.node_id, qself.path_span),
+                RecordPartialRes::No,
+            );
+
+            if trait_res.expect_full_res() == Res::Err {
+                return Ok(Some(trait_res));
+            }
+
+            // Truncate additional privacy errors reported above,
+            // because they'll be recomputed below.
+            self.r.privacy_errors.truncate(num_privacy_errors);
+
+            // Make sure `A::B` in `::B::C` is a trait item.
             //
             // Currently, `path` names the full item (`A::B::C`, in
             // our example). so we extract the prefix of that that is
@@ -3753,6 +3780,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 &path[..=qself.position],
                 PathSource::TraitItem(ns),
                 Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
+                RecordPartialRes::No,
             );
 
             // The remaining segments (the `C` in our example) will
diff --git a/tests/ui/parser/dyn-trait-compatibility.rs b/tests/ui/parser/dyn-trait-compatibility.rs
index d2b02cc2af54..6341e0532775 100644
--- a/tests/ui/parser/dyn-trait-compatibility.rs
+++ b/tests/ui/parser/dyn-trait-compatibility.rs
@@ -9,6 +9,6 @@ type A2 = dyn;
 type A3 = dyn<::dyn>;
 //~^ ERROR cannot find type `dyn` in this scope
 //~| ERROR cannot find type `dyn` in this scope
-//~| ERROR use of undeclared crate or module `dyn`
+//~| ERROR cannot find trait `dyn` in this scope
 
 fn main() {}
diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr
index 0cae01bd1e32..653be5b3b717 100644
--- a/tests/ui/parser/dyn-trait-compatibility.stderr
+++ b/tests/ui/parser/dyn-trait-compatibility.stderr
@@ -4,12 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `dyn`
 LL | type A1 = dyn::dyn;
    |           ^^^ use of undeclared crate or module `dyn`
 
-error[E0433]: failed to resolve: use of undeclared crate or module `dyn`
-  --> $DIR/dyn-trait-compatibility.rs:9:23
-   |
-LL | type A3 = dyn<::dyn>;
-   |                       ^^^ use of undeclared crate or module `dyn`
-
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:1:11
    |
@@ -40,6 +34,12 @@ error[E0412]: cannot find type `dyn` in this scope
 LL | type A3 = dyn<::dyn>;
    |           ^^^ not found in this scope
 
+error[E0405]: cannot find trait `dyn` in this scope
+  --> $DIR/dyn-trait-compatibility.rs:9:23
+   |
+LL | type A3 = dyn<::dyn>;
+   |                       ^^^ not found in this scope
+
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:9:16
    |
@@ -48,5 +48,5 @@ LL | type A3 = dyn<::dyn>;
 
 error: aborting due to 8 previous errors
 
-Some errors have detailed explanations: E0412, E0433.
-For more information about an error, try `rustc --explain E0412`.
+Some errors have detailed explanations: E0405, E0412, E0433.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
index 85d106bc11f6..ede0c2e8eaf0 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
@@ -18,9 +18,11 @@ mod foo {
 fn main() {
     let _: ::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
+    //~| ERROR absolute paths must start with
+    //~| WARN this is accepted in the current edition
 
     let _: ::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
 }
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs
index 9ff3c2e5fcff..48b091ddb45e 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs
@@ -18,9 +18,11 @@ mod foo {
 fn main() {
     let _: ::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
+    //~| ERROR absolute paths must start with
+    //~| WARN this is accepted in the current edition
 
     let _: <::foo::Baz as foo::Foo>::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
 }
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
index e1709db0990c..497ee440dfdb 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
@@ -13,7 +13,16 @@ LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-fully-qualified-paths.rs:23:13
+  --> $DIR/edition-lint-fully-qualified-paths.rs:19:25
+   |
+LL |     let _: ::Bar = ();
+   |                         ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo`
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+   = note: for more information, see issue #53130 
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-fully-qualified-paths.rs:25:13
    |
 LL |     let _: <::foo::Baz as foo::Foo>::Bar = ();
    |             ^^^^^^^^^^ help: use `crate`: `crate::foo::Baz`
@@ -21,5 +30,5 @@ LL |     let _: <::foo::Baz as foo::Foo>::Bar = ();
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
index 471a6b836b51..8e43b7249f7c 100644
--- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
+++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
@@ -18,6 +18,6 @@ fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expec
 
 fn issue_95327() where ::Assoc: String {}
 //~^ ERROR expected trait, found struct
-//~| ERROR use of undeclared type `Unresolved`
+//~| ERROR cannot find trait `Unresolved` in this scope
 
 fn main() {}
diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
index 5be334986418..0020f9e416df 100644
--- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
+++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
@@ -1,9 +1,3 @@
-error[E0433]: failed to resolve: use of undeclared type `Unresolved`
-  --> $DIR/assoc_type_bound_with_struct.rs:19:31
-   |
-LL | fn issue_95327() where ::Assoc: String {}
-   |                               ^^^^^^^^^^ use of undeclared type `Unresolved`
-
 error[E0404]: expected trait, found struct `String`
   --> $DIR/assoc_type_bound_with_struct.rs:5:46
    |
@@ -76,6 +70,12 @@ help: a trait with a similar name exists
 LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString {
    |                                                         ~~~~~~~~
 
+error[E0405]: cannot find trait `Unresolved` in this scope
+  --> $DIR/assoc_type_bound_with_struct.rs:19:31
+   |
+LL | fn issue_95327() where ::Assoc: String {}
+   |                               ^^^^^^^^^^ not found in this scope
+
 error[E0404]: expected trait, found struct `String`
   --> $DIR/assoc_type_bound_with_struct.rs:19:51
    |
@@ -87,5 +87,5 @@ LL | fn issue_95327() where ::Assoc: String {}
 
 error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0404, E0433.
+Some errors have detailed explanations: E0404, E0405.
 For more information about an error, try `rustc --explain E0404`.
diff --git a/tests/ui/ufcs/ufcs-partially-resolved.rs b/tests/ui/ufcs/ufcs-partially-resolved.rs
index e6470aa6d64f..712668728c9e 100644
--- a/tests/ui/ufcs/ufcs-partially-resolved.rs
+++ b/tests/ui/ufcs/ufcs-partially-resolved.rs
@@ -17,37 +17,37 @@ type A = u32;
 
 fn main() {
     let _: ::N; //~ ERROR cannot find associated type `N` in trait `Tr`
-    let _: ::N; //~ ERROR cannot find associated type `N` in enum `E`
-    let _: ::N; //~ ERROR cannot find associated type `N` in `A`
+    let _: ::N; //~ ERROR expected trait, found enum `E`
+    let _: ::N; //~ ERROR expected trait, found type alias `A`
     ::N; //~ ERROR cannot find method or associated constant `N` in trait `Tr`
-    ::N; //~ ERROR cannot find method or associated constant `N` in enum `E`
-    ::N; //~ ERROR cannot find method or associated constant `N` in `A`
+    ::N; //~ ERROR expected trait, found enum `E`
+    ::N; //~ ERROR expected trait, found type alias `A`
     let _: ::Y; // OK
-    let _: ::Y; //~ ERROR expected associated type, found variant `E::Y`
+    let _: ::Y; //~ ERROR expected trait, found enum `E`
     ::Y; // OK
-    ::Y; //~ ERROR expected method or associated constant, found unit variant `E::Y`
+    ::Y; //~ ERROR expected trait, found enum `E`
 
     let _: ::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr`
-    let _: ::N::NN; //~ ERROR cannot find associated type `N` in enum `E`
-    let _: ::N::NN; //~ ERROR cannot find associated type `N` in `A`
+    let _: ::N::NN; //~ ERROR expected trait, found enum `E`
+    let _: ::N::NN; //~ ERROR expected trait, found type alias `A`
     ::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr`
-    ::N::NN; //~ ERROR cannot find associated type `N` in enum `E`
-    ::N::NN; //~ ERROR cannot find associated type `N` in `A`
+    ::N::NN; //~ ERROR expected trait, found enum `E`
+    ::N::NN; //~ ERROR expected trait, found type alias `A`
     let _: ::Y::NN; //~ ERROR ambiguous associated type
-    let _: ::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
+    let _: ::Y::NN; //~ ERROR expected trait, found enum `E`
     ::Y::NN; //~ ERROR no associated item named `NN` found for type `u16`
-    ::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
+    ::Y::NN; //~ ERROR expected trait, found enum `E`
 
-    let _: ::NN; //~ ERROR cannot find associated type `NN` in `Tr::N`
-    let _: ::NN; //~ ERROR cannot find associated type `NN` in `E::N`
-    let _: ::NN; //~ ERROR cannot find associated type `NN` in `A::N`
-    ::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::N`
-    ::NN; //~ ERROR cannot find method or associated constant `NN` in `E::N`
-    ::NN; //~ ERROR cannot find method or associated constant `NN` in `A::N`
-    let _: ::NN; //~ ERROR cannot find associated type `NN` in `Tr::Y`
-    let _: ::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module
-    ::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::Y`
-    ::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module
+    let _: ::NN; //~ ERROR cannot find trait `N` in trait `Tr`
+    let _: ::NN; //~ ERROR cannot find trait `N` in enum `E`
+    let _: ::NN; //~ ERROR cannot find trait `N` in `A`
+    ::NN; //~ ERROR cannot find trait `N` in trait `Tr`
+    ::NN; //~ ERROR cannot find trait `N` in enum `E`
+    ::NN; //~ ERROR cannot find trait `N` in `A`
+    let _: ::NN; //~ ERROR expected trait, found associated type `Tr::Y
+    let _: ::NN; //~ ERROR expected trait, found variant `E::Y`
+    ::NN; //~ ERROR expected trait, found associated type `Tr::Y`
+    ::NN; //~ ERROR expected trait, found variant `E::Y`
 
     let _: ::Z; //~ ERROR expected associated type, found associated function `Dr::Z`
     ::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr
index 72fccea8ae39..eef55c8dc686 100644
--- a/tests/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr
@@ -1,15 +1,3 @@
-error[E0433]: failed to resolve: `Y` is a variant, not a module
-  --> $DIR/ufcs-partially-resolved.rs:48:22
-   |
-LL |     let _: ::NN;
-   |                      ^ `Y` is a variant, not a module
-
-error[E0433]: failed to resolve: `Y` is a variant, not a module
-  --> $DIR/ufcs-partially-resolved.rs:50:15
-   |
-LL |     ::NN;
-   |               ^ `Y` is a variant, not a module
-
 error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:19:24
    |
@@ -19,17 +7,25 @@ LL |     type Y = u16;
 LL |     let _: ::N;
    |                        ^ help: an associated type with a similar name exists: `Y`
 
-error[E0576]: cannot find associated type `N` in enum `E`
-  --> $DIR/ufcs-partially-resolved.rs:20:23
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:20:19
    |
 LL |     let _: ::N;
-   |                       ^ not found in `E`
+   |                   ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find associated type `N` in `A`
-  --> $DIR/ufcs-partially-resolved.rs:21:23
+error[E0404]: expected trait, found type alias `A`
+  --> $DIR/ufcs-partially-resolved.rs:21:19
    |
 LL |     let _: ::N;
-   |                       ^ not found in `A`
+   |                   ^ type aliases cannot be used as traits
+   |
+help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+   |
+LL | trait A = u32;
+   |
 
 error[E0576]: cannot find method or associated constant `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:22:17
@@ -40,29 +36,43 @@ LL |     fn Y() {}
 LL |     ::N;
    |                 ^ help: an associated function with a similar name exists: `Y`
 
-error[E0576]: cannot find method or associated constant `N` in enum `E`
-  --> $DIR/ufcs-partially-resolved.rs:23:16
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:23:12
    |
 LL |     ::N;
-   |                ^ not found in `E`
+   |            ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find method or associated constant `N` in `A`
-  --> $DIR/ufcs-partially-resolved.rs:24:16
+error[E0404]: expected trait, found type alias `A`
+  --> $DIR/ufcs-partially-resolved.rs:24:12
    |
 LL |     ::N;
-   |                ^ not found in `A`
+   |            ^ type aliases cannot be used as traits
+   |
+help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+   |
+LL | trait A = u32;
+   |
 
-error[E0575]: expected associated type, found variant `E::Y`
-  --> $DIR/ufcs-partially-resolved.rs:26:12
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:26:19
    |
 LL |     let _: ::Y;
-   |            ^^^^^^^^^^^^ not a associated type
+   |                   ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0575]: expected method or associated constant, found unit variant `E::Y`
-  --> $DIR/ufcs-partially-resolved.rs:28:5
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:28:12
    |
 LL |     ::Y;
-   |     ^^^^^^^^^^^^ not a method or associated constant
+   |            ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
 error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:30:24
@@ -73,17 +83,25 @@ LL |     type Y = u16;
 LL |     let _: ::N::NN;
    |                        ^ help: an associated type with a similar name exists: `Y`
 
-error[E0576]: cannot find associated type `N` in enum `E`
-  --> $DIR/ufcs-partially-resolved.rs:31:23
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:31:19
    |
 LL |     let _: ::N::NN;
-   |                       ^ not found in `E`
+   |                   ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find associated type `N` in `A`
-  --> $DIR/ufcs-partially-resolved.rs:32:23
+error[E0404]: expected trait, found type alias `A`
+  --> $DIR/ufcs-partially-resolved.rs:32:19
    |
 LL |     let _: ::N::NN;
-   |                       ^ not found in `A`
+   |                   ^ type aliases cannot be used as traits
+   |
+help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+   |
+LL | trait A = u32;
+   |
 
 error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:33:17
@@ -94,77 +112,103 @@ LL |     type Y = u16;
 LL |     ::N::NN;
    |                 ^ help: an associated type with a similar name exists: `Y`
 
-error[E0576]: cannot find associated type `N` in enum `E`
-  --> $DIR/ufcs-partially-resolved.rs:34:16
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:34:12
    |
 LL |     ::N::NN;
-   |                ^ not found in `E`
+   |            ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find associated type `N` in `A`
-  --> $DIR/ufcs-partially-resolved.rs:35:16
+error[E0404]: expected trait, found type alias `A`
+  --> $DIR/ufcs-partially-resolved.rs:35:12
    |
 LL |     ::N::NN;
-   |                ^ not found in `A`
+   |            ^ type aliases cannot be used as traits
+   |
+help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+   |
+LL | trait A = u32;
+   |
 
-error[E0575]: expected associated type, found variant `E::Y`
-  --> $DIR/ufcs-partially-resolved.rs:37:12
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:37:19
    |
 LL |     let _: ::Y::NN;
-   |            ^^^^^^^^^^^^^^^^ not a associated type
+   |                   ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0575]: expected associated type, found variant `E::Y`
-  --> $DIR/ufcs-partially-resolved.rs:39:5
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:39:12
    |
 LL |     ::Y::NN;
-   |     ^^^^^^^^^^^^^^^^ not a associated type
+   |            ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find associated type `NN` in `Tr::N`
-  --> $DIR/ufcs-partially-resolved.rs:41:27
+error[E0405]: cannot find trait `N` in trait `Tr`
+  --> $DIR/ufcs-partially-resolved.rs:41:23
    |
 LL |     let _: ::NN;
-   |                           ^^ not found in `Tr::N`
+   |                       ^ not found in `Tr`
 
-error[E0576]: cannot find associated type `NN` in `E::N`
-  --> $DIR/ufcs-partially-resolved.rs:42:26
+error[E0405]: cannot find trait `N` in enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:42:22
    |
 LL |     let _: ::NN;
-   |                          ^^ not found in `E::N`
+   |                      ^ not found in `E`
 
-error[E0576]: cannot find associated type `NN` in `A::N`
-  --> $DIR/ufcs-partially-resolved.rs:43:26
+error[E0405]: cannot find trait `N` in `A`
+  --> $DIR/ufcs-partially-resolved.rs:43:22
    |
 LL |     let _: ::NN;
-   |                          ^^ not found in `A::N`
+   |                      ^ not found in `A`
 
-error[E0576]: cannot find method or associated constant `NN` in `Tr::N`
-  --> $DIR/ufcs-partially-resolved.rs:44:20
+error[E0405]: cannot find trait `N` in trait `Tr`
+  --> $DIR/ufcs-partially-resolved.rs:44:16
    |
 LL |     ::NN;
-   |                    ^^ not found in `Tr::N`
+   |                ^ not found in `Tr`
 
-error[E0576]: cannot find method or associated constant `NN` in `E::N`
-  --> $DIR/ufcs-partially-resolved.rs:45:19
+error[E0405]: cannot find trait `N` in enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:45:15
    |
 LL |     ::NN;
-   |                   ^^ not found in `E::N`
+   |               ^ not found in `E`
 
-error[E0576]: cannot find method or associated constant `NN` in `A::N`
-  --> $DIR/ufcs-partially-resolved.rs:46:19
+error[E0405]: cannot find trait `N` in `A`
+  --> $DIR/ufcs-partially-resolved.rs:46:15
    |
 LL |     ::NN;
-   |                   ^^ not found in `A::N`
+   |               ^ not found in `A`
 
-error[E0576]: cannot find associated type `NN` in `Tr::Y`
-  --> $DIR/ufcs-partially-resolved.rs:47:27
+error[E0404]: expected trait, found associated type `Tr::Y`
+  --> $DIR/ufcs-partially-resolved.rs:47:19
    |
 LL |     let _: ::NN;
-   |                           ^^ not found in `Tr::Y`
+   |                   ^^^^^ not a trait
 
-error[E0576]: cannot find method or associated constant `NN` in `Tr::Y`
-  --> $DIR/ufcs-partially-resolved.rs:49:20
+error[E0404]: expected trait, found variant `E::Y`
+  --> $DIR/ufcs-partially-resolved.rs:48:19
+   |
+LL |     let _: ::NN;
+   |                   ^^^^ not a trait
+
+error[E0404]: expected trait, found associated type `Tr::Y`
+  --> $DIR/ufcs-partially-resolved.rs:49:12
    |
 LL |     ::NN;
-   |                    ^^ not found in `Tr::Y`
+   |            ^^^^^ not a trait
+
+error[E0404]: expected trait, found variant `E::Y`
+  --> $DIR/ufcs-partially-resolved.rs:50:12
+   |
+LL |     ::NN;
+   |            ^^^^ not a trait
 
 error[E0575]: expected associated type, found associated function `Dr::Z`
   --> $DIR/ufcs-partially-resolved.rs:52:12
@@ -226,5 +270,5 @@ LL |     ::X::N;
 
 error: aborting due to 32 previous errors
 
-Some errors have detailed explanations: E0223, E0433, E0575, E0576, E0599.
+Some errors have detailed explanations: E0223, E0404, E0405, E0575, E0576, E0599.
 For more information about an error, try `rustc --explain E0223`.

From f2acafe9e280bc234a06fcd5f6e9a55dac109914 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= 
Date: Fri, 7 Apr 2023 09:00:27 +0200
Subject: [PATCH 203/267] suggest adding const param

---
 compiler/rustc_resolve/src/late.rs            |  4 +-
 .../rustc_resolve/src/late/diagnostics.rs     | 15 +++--
 .../missing-items/missing-const-parameter.rs  | 24 +++++++
 .../missing-const-parameter.stderr            | 64 +++++++++++++++++++
 4 files changed, 100 insertions(+), 7 deletions(-)
 create mode 100644 tests/ui/missing/missing-items/missing-const-parameter.rs
 create mode 100644 tests/ui/missing/missing-items/missing-const-parameter.stderr

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 19f46d45af67..10f0fc2a7e34 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -3458,8 +3458,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                         sugg.to_string(),
                         Applicability::MaybeIncorrect,
                     ))
-                } else if res.is_none() && matches!(source, PathSource::Type) {
-                    this.report_missing_type_error(path)
+                } else if res.is_none() && let PathSource::Type | PathSource::Expr(_) = source {
+                    this.suggest_adding_generic_parameter(path, source)
                 } else {
                     None
                 };
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index df7681dc4267..37fbfad2de63 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2110,9 +2110,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
     }
 
-    pub(crate) fn report_missing_type_error(
+    pub(crate) fn suggest_adding_generic_parameter(
         &self,
         path: &[Segment],
+        source: PathSource<'_>,
     ) -> Option<(Span, &'static str, String, Applicability)> {
         let (ident, span) = match path {
             [segment]
@@ -2148,7 +2149,6 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             // Without the 2nd `true`, we'd suggest `impl ` for `impl T` when a type `T` isn't found
             | (Some(Item { kind: kind @ ItemKind::Impl(..), .. }), true, true)
             | (Some(Item { kind, .. }), false, _) => {
-                // Likely missing type parameter.
                 if let Some(generics) = kind.generics() {
                     if span.overlaps(generics.span) {
                         // Avoid the following:
@@ -2161,7 +2161,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         //   |           not found in this scope
                         return None;
                     }
-                    let msg = "you might be missing a type parameter";
+
+                    let (msg, sugg) = match source {
+                        PathSource::Type => ("you might be missing a type parameter", ident),
+                        PathSource::Expr(_) => ("you might be missing a const parameter", format!("const {ident}: /* Type */")),
+                        _ => return None,
+                    };
                     let (span, sugg) = if let [.., param] = &generics.params[..] {
                         let span = if let [.., bound] = ¶m.bounds[..] {
                             bound.span()
@@ -2172,9 +2177,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         } else {
                             param.ident.span
                         };
-                        (span, format!(", {}", ident))
+                        (span, format!(", {sugg}"))
                     } else {
-                        (generics.span, format!("<{}>", ident))
+                        (generics.span, format!("<{sugg}>"))
                     };
                     // Do not suggest if this is coming from macro expansion.
                     if span.can_be_used_for_suggestions() {
diff --git a/tests/ui/missing/missing-items/missing-const-parameter.rs b/tests/ui/missing/missing-items/missing-const-parameter.rs
new file mode 100644
index 000000000000..a3af88f26333
--- /dev/null
+++ b/tests/ui/missing/missing-items/missing-const-parameter.rs
@@ -0,0 +1,24 @@
+struct Struct;
+
+impl Struct<{ N }> {}
+//~^ ERROR cannot find value `N` in this scope
+//~| HELP you might be missing a const parameter
+
+fn func0(_: Struct<{ N }>) {}
+//~^ ERROR cannot find value `N` in this scope
+//~| HELP you might be missing a const parameter
+
+fn func1(_: [u8; N]) {}
+//~^ ERROR cannot find value `N` in this scope
+//~| HELP you might be missing a const parameter
+
+fn func2(_: [T; N]) {}
+//~^ ERROR cannot find value `N` in this scope
+//~| HELP you might be missing a const parameter
+
+struct Image([[u32; C]; R]);
+//~^ ERROR cannot find value `C` in this scope
+//~| HELP a const parameter with a similar name exists
+//~| HELP you might be missing a const parameter
+
+fn main() {}
diff --git a/tests/ui/missing/missing-items/missing-const-parameter.stderr b/tests/ui/missing/missing-items/missing-const-parameter.stderr
new file mode 100644
index 000000000000..d9fea1306514
--- /dev/null
+++ b/tests/ui/missing/missing-items/missing-const-parameter.stderr
@@ -0,0 +1,64 @@
+error[E0425]: cannot find value `N` in this scope
+  --> $DIR/missing-const-parameter.rs:3:15
+   |
+LL | impl Struct<{ N }> {}
+   |               ^ not found in this scope
+   |
+help: you might be missing a const parameter
+   |
+LL | impl Struct<{ N }> {}
+   |     +++++++++++++++++++++
+
+error[E0425]: cannot find value `N` in this scope
+  --> $DIR/missing-const-parameter.rs:7:22
+   |
+LL | fn func0(_: Struct<{ N }>) {}
+   |                      ^ not found in this scope
+   |
+help: you might be missing a const parameter
+   |
+LL | fn func0(_: Struct<{ N }>) {}
+   |         +++++++++++++++++++++
+
+error[E0425]: cannot find value `N` in this scope
+  --> $DIR/missing-const-parameter.rs:11:18
+   |
+LL | fn func1(_: [u8; N]) {}
+   |                  ^ not found in this scope
+   |
+help: you might be missing a const parameter
+   |
+LL | fn func1(_: [u8; N]) {}
+   |         +++++++++++++++++++++
+
+error[E0425]: cannot find value `N` in this scope
+  --> $DIR/missing-const-parameter.rs:15:20
+   |
+LL | fn func2(_: [T; N]) {}
+   |                    ^ not found in this scope
+   |
+help: you might be missing a const parameter
+   |
+LL | fn func2(_: [T; N]) {}
+   |           +++++++++++++++++++++
+
+error[E0425]: cannot find value `C` in this scope
+  --> $DIR/missing-const-parameter.rs:19:37
+   |
+LL | struct Image([[u32; C]; R]);
+   |                    -                ^
+   |                    |
+   |                    similarly named const parameter `R` defined here
+   |
+help: a const parameter with a similar name exists
+   |
+LL | struct Image([[u32; R]; R]);
+   |                                     ~
+help: you might be missing a const parameter
+   |
+LL | struct Image([[u32; C]; R]);
+   |                            +++++++++++++++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0425`.

From 726598ed9ad7d1566e5a6d915673a22b907c3552 Mon Sep 17 00:00:00 2001
From: ickk 
Date: Fri, 7 Apr 2023 17:42:17 +1000
Subject: [PATCH 204/267] fix infer_source_kind_subdiag_let help message -
 remove double "the"

---
 compiler/rustc_infer/messages.ftl | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 15780898dc6a..1e43644be89a 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -30,8 +30,8 @@ infer_source_kind_subdiag_let = {$kind ->
 }{$x_kind ->
     [has_name] , where the {$prefix_kind ->
         *[type] type for {$prefix}
-        [const_with_param] the value of const parameter
-        [const] the value of the constant
+        [const_with_param] value of const parameter
+        [const] value of the constant
     } `{$arg_name}` is specified
     [underscore] , where the placeholders `_` are specified
     *[empty] {""}

From 30f458ed1e5d4997ee70cb2347edbea6683f8922 Mon Sep 17 00:00:00 2001
From: ickk 
Date: Fri, 7 Apr 2023 18:07:11 +1000
Subject: [PATCH 205/267] update tests/ui

---
 tests/ui/const-generics/defaults/doesnt_infer.stderr | 2 +-
 tests/ui/inference/issue-83606.stderr                | 2 +-
 tests/ui/issues/issue-98299.stderr                   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr
index 227b2f402236..a61411d6eb6e 100644
--- a/tests/ui/const-generics/defaults/doesnt_infer.stderr
+++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo`
 LL |     let foo = Foo::foo();
    |         ^^^
    |
-help: consider giving `foo` an explicit type, where the the value of const parameter `N` is specified
+help: consider giving `foo` an explicit type, where the value of const parameter `N` is specified
    |
 LL |     let foo: Foo = Foo::foo();
    |            ++++++++
diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr
index f2ee8692e38a..97ed53fb3ce5 100644
--- a/tests/ui/inference/issue-83606.stderr
+++ b/tests/ui/inference/issue-83606.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; N]`
 LL |     let _ = foo("foo");
    |         ^
    |
-help: consider giving this pattern a type, where the the value of const parameter `N` is specified
+help: consider giving this pattern a type, where the value of const parameter `N` is specified
    |
 LL |     let _: [usize; N] = foo("foo");
    |          ++++++++++++
diff --git a/tests/ui/issues/issue-98299.stderr b/tests/ui/issues/issue-98299.stderr
index fd905392a21a..4fd9f3030fc5 100644
--- a/tests/ui/issues/issue-98299.stderr
+++ b/tests/ui/issues/issue-98299.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `SmallCString`
 LL |     SmallCString::try_from(p).map(|cstr| cstr);
    |                                    ^^^^
    |
-help: consider giving this closure parameter an explicit type, where the the value of const parameter `N` is specified
+help: consider giving this closure parameter an explicit type, where the value of const parameter `N` is specified
    |
 LL |     SmallCString::try_from(p).map(|cstr: SmallCString| cstr);
    |                                        +++++++++++++++++

From 1042b5df9bbfa29e87c09edb54aaeb667336d1b4 Mon Sep 17 00:00:00 2001
From: Scott McMurray 
Date: Fri, 7 Apr 2023 01:32:12 -0700
Subject: [PATCH 206/267] Avoid some manual slice length calculation

No need for us to write the multiplication when `size_of_val` does exactly what we need.
---
 library/core/src/mem/maybe_uninit.rs | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 3f491836551d..9c6d48675a6b 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -1241,13 +1241,9 @@ impl MaybeUninit {
     /// ```
     #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
     pub fn slice_as_bytes(this: &[MaybeUninit]) -> &[MaybeUninit] {
+        let bytes = mem::size_of_val(this);
         // SAFETY: MaybeUninit is always valid, even for padding bytes
-        unsafe {
-            slice::from_raw_parts(
-                this.as_ptr() as *const MaybeUninit,
-                this.len() * mem::size_of::(),
-            )
-        }
+        unsafe { slice::from_raw_parts(this.as_ptr() as *const MaybeUninit, bytes) }
     }
 
     /// Returns the contents of this mutable slice of `MaybeUninit` as a mutable slice of
@@ -1274,13 +1270,9 @@ impl MaybeUninit {
     /// ```
     #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
     pub fn slice_as_bytes_mut(this: &mut [MaybeUninit]) -> &mut [MaybeUninit] {
+        let bytes = mem::size_of_val(this);
         // SAFETY: MaybeUninit is always valid, even for padding bytes
-        unsafe {
-            slice::from_raw_parts_mut(
-                this.as_mut_ptr() as *mut MaybeUninit,
-                this.len() * mem::size_of::(),
-            )
-        }
+        unsafe { slice::from_raw_parts_mut(this.as_mut_ptr() as *mut MaybeUninit, bytes) }
     }
 }
 

From ea69dad8fa5db5fcd99fa0e4156efdb7a01b3f3a Mon Sep 17 00:00:00 2001
From: Gary Guo 
Date: Fri, 7 Apr 2023 10:18:28 +0100
Subject: [PATCH 207/267] Fix coverage test

---
 .../run-make/coverage-reports/expected_show_coverage.abort.txt  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
index ca7741f21e80..a71c58d618da 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
+++ b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
@@ -32,7 +32,7 @@
    30|       |// Notes:
    31|       |//   1. Compare this program and its coverage results to those of the similar tests
    32|       |//      `panic_unwind.rs` and `try_error_result.rs`.
-   33|       |//   2. This test confirms the coverage generated when a program includes  `UnwindAction::Terminate`.
+   33|       |//   2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`.
    34|       |//   3. The test does not invoke the abort. By executing to a successful completion, the coverage
    35|       |//      results show where the program did and did not execute.
    36|       |//   4. If the program actually aborted, the coverage counters would not be saved (which "works as

From fbe0591c6897216042a201795185bc0c0dac42c1 Mon Sep 17 00:00:00 2001
From: Maybe Waffle 
Date: Fri, 7 Apr 2023 10:14:50 +0000
Subject: [PATCH 208/267] Mark `OwnedSlice::{deref, borrow}` as `#[inline]`

---
 compiler/rustc_data_structures/src/owned_slice.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs
index c0a3cb071943..048401f66c27 100644
--- a/compiler/rustc_data_structures/src/owned_slice.rs
+++ b/compiler/rustc_data_structures/src/owned_slice.rs
@@ -92,6 +92,7 @@ where
 impl Deref for OwnedSlice {
     type Target = [u8];
 
+    #[inline]
     fn deref(&self) -> &[u8] {
         // Safety:
         // `self.bytes` is valid per the construction in `slice_owned`
@@ -101,6 +102,7 @@ impl Deref for OwnedSlice {
 }
 
 impl Borrow<[u8]> for OwnedSlice {
+    #[inline]
     fn borrow(&self) -> &[u8] {
         self
     }

From f08f15481afbd122355a6e1223c007fc774825ad Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Thu, 6 Apr 2023 15:35:14 +1000
Subject: [PATCH 209/267] Add a size assertion for `RegionKind`.

---
 compiler/rustc_middle/src/ty/sty.rs | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d542d93b8c81..0e2e2a956ec7 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -127,10 +127,6 @@ impl<'tcx> Article for TyKind<'tcx> {
     }
 }
 
-// `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(TyKind<'_>, 32);
-
 /// A closure can be modeled as a struct that looks like:
 /// ```ignore (illustrative)
 /// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
@@ -2496,3 +2492,14 @@ impl<'tcx> VarianceDiagInfo<'tcx> {
         }
     }
 }
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    use rustc_data_structures::static_assert_size;
+    // tidy-alphabetical-start
+    static_assert_size!(RegionKind<'_>, 28);
+    static_assert_size!(TyKind<'_>, 32);
+    // tidy-alphabetical-end
+}

From b76dd8c807c5ad32d2dac603937d6661b4685f59 Mon Sep 17 00:00:00 2001
From: kadmin 
Date: Tue, 4 Apr 2023 08:41:44 +0000
Subject: [PATCH 210/267] Add feature gate

---
 compiler/rustc_feature/src/active.rs          |  2 +
 compiler/rustc_hir_typeck/src/intrinsicck.rs  |  2 +-
 compiler/rustc_middle/src/ty/layout.rs        | 16 ++--
 compiler/rustc_span/src/symbol.rs             |  1 +
 tests/ui/const-generics/transmute-fail.rs     |  1 +
 tests/ui/const-generics/transmute-fail.stderr | 20 ++--
 tests/ui/const-generics/transmute.rs          |  1 +
 tests/ui/const-generics/transmute_no_gate.rs  | 91 +++++++++++++++++++
 .../const-generics/transmute_no_gate.stderr   | 84 +++++++++++++++++
 9 files changed, 200 insertions(+), 18 deletions(-)
 create mode 100644 tests/ui/const-generics/transmute_no_gate.rs
 create mode 100644 tests/ui/const-generics/transmute_no_gate.stderr

diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index b7d280b8751c..8fb8c9b1883f 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -516,6 +516,8 @@ declare_features! (
     /// Allows dyn upcasting trait objects via supertraits.
     /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
     (active, trait_upcasting, "1.56.0", Some(65991), None),
+    /// Allows for transmuting between arrays with sizes that contain generic consts.
+    (active, transmute_generic_consts, "CURRENT_RUSTC_VERSION", Some(109929), None),
     /// Allows #[repr(transparent)] on unions (RFC 2645).
     (active, transparent_unions, "1.37.0", Some(60405), None),
     /// Allows inconsistent bounds in where clauses.
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index eedab9fa1b0a..bb1d3bb7a308 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -88,7 +88,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if let Some(size) = size.try_eval_target_usize(tcx, self.param_env) {
                     format!("{size} bytes")
                 } else {
-                    format!("generic size")
+                    format!("generic size {size}")
                 }
             }
             Err(LayoutError::Unknown(bad)) => {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 2a057e71eac4..f52e785cd0ae 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -332,7 +332,9 @@ impl<'tcx> SizeSkeleton<'tcx> {
                     ),
                 }
             }
-            ty::Array(inner, len) if len.ty() == tcx.types.usize => {
+            ty::Array(inner, len)
+                if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts =>
+            {
                 match SizeSkeleton::compute(inner, tcx, param_env)? {
                     // This may succeed because the multiplication of two types may overflow
                     // but a single size of a nested array will not.
@@ -483,17 +485,17 @@ fn mul_sorted_consts<'tcx>(
     }
     let mut k = 1;
     let mut overflow = false;
-    for _ in done.drain_filter(|c| {
+    done.retain(|c| {
         let Some(c) = c.try_eval_target_usize(tcx, param_env) else {
-            return false;
+            return true;
         };
         let Some(next) = c.checked_mul(k) else {
             overflow = true;
-            return true;
+            return false;
         };
-        k *= next;
-        true
-    }) {}
+        k = next;
+        false
+    });
     if overflow {
         return None;
     }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 0ed993531450..bc2e9cbb8afe 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1493,6 +1493,7 @@ symbols! {
         trait_alias,
         trait_upcasting,
         transmute,
+        transmute_generic_consts,
         transmute_opts,
         transmute_trait,
         transparent,
diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs
index 490e4de9aac7..d7bf1b47fb5a 100644
--- a/tests/ui/const-generics/transmute-fail.rs
+++ b/tests/ui/const-generics/transmute-fail.rs
@@ -1,3 +1,4 @@
+#![feature(transmute_generic_consts)]
 #![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index bf6a3b61dbb2..41b098135e81 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -1,14 +1,14 @@
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:6:5
+  --> $DIR/transmute-fail.rs:7:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[u32; H+1]; W]` (generic size)
-   = note: target type: `[[u32; W+1]; H]` (generic size)
+   = note: source type: `[[u32; H+1]; W]` (generic size [const expr])
+   = note: target type: `[[u32; W+1]; H]` (generic size [const expr])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:15:5
+  --> $DIR/transmute-fail.rs:16:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -17,28 +17,28 @@ LL |     std::mem::transmute(v)
    = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
 
 error[E0308]: mismatched types
-  --> $DIR/transmute-fail.rs:11:53
+  --> $DIR/transmute-fail.rs:12:53
    |
 LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] {
    |                                                     ^ expected `usize`, found `bool`
 
 error[E0308]: mismatched types
-  --> $DIR/transmute-fail.rs:11:67
+  --> $DIR/transmute-fail.rs:12:67
    |
 LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] {
    |                                                                   ^ expected `usize`, found `bool`
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:22:5
+  --> $DIR/transmute-fail.rs:23:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[u32; H]; W]` (generic size)
-   = note: target type: `[u32; W * H * H]` (generic size)
+   = note: source type: `[[u32; H]; W]` (generic size [const expr])
+   = note: target type: `[u32; W * H * H]` (generic size [const expr])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:29:5
+  --> $DIR/transmute-fail.rs:30:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/const-generics/transmute.rs b/tests/ui/const-generics/transmute.rs
index 9571b9157049..30560a95b5e1 100644
--- a/tests/ui/const-generics/transmute.rs
+++ b/tests/ui/const-generics/transmute.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![feature(generic_const_exprs)]
+#![feature(transmute_generic_consts)]
 #![allow(incomplete_features)]
 
 fn transpose(v: [[u32;H]; W]) -> [[u32; W]; H] {
diff --git a/tests/ui/const-generics/transmute_no_gate.rs b/tests/ui/const-generics/transmute_no_gate.rs
new file mode 100644
index 000000000000..e1ac44390a5f
--- /dev/null
+++ b/tests/ui/const-generics/transmute_no_gate.rs
@@ -0,0 +1,91 @@
+// gate-test-transmute_generic_consts
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn transpose(v: [[u32;H]; W]) -> [[u32; W]; H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn ident(v: [[u32; H]; W]) -> [[u32; H]; W] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn flatten(v: [[u32; H]; W]) -> [u32; W * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn coagulate(v: [u32; H*W]) -> [[u32; W];H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn flatten_3d(
+  v: [[[u32; D]; H]; W]
+) -> [u32; D * W * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn flatten_somewhat(
+  v: [[[u32; D]; H]; W]
+) -> [[u32; D * W]; H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn known_size(v: [u16; L]) -> [u8; L * 2] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn condense_bytes(v: [u8; L * 2]) -> [u16; L] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn singleton_each(v: [u8; L]) -> [[u8;1]; L] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn transpose_with_const(
+  v: [[u32; 2 * H]; W + W]
+) -> [[u32; W + W]; 2 * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn main() {
+  let _ = transpose([[0; 8]; 16]);
+  let _ = transpose_with_const::<8,4>([[0; 8]; 16]);
+  let _ = ident([[0; 8]; 16]);
+  let _ = flatten([[0; 13]; 5]);
+  let _: [[_; 5]; 13] = coagulate([0; 65]);
+  let _ = flatten_3d([[[0; 3]; 13]; 5]);
+  let _ = flatten_somewhat([[[0; 3]; 13]; 5]);
+  let _ = known_size([16; 13]);
+  let _: [u16; 5] = condense_bytes([16u8; 10]);
+  let _ = singleton_each([16; 10]);
+}
diff --git a/tests/ui/const-generics/transmute_no_gate.stderr b/tests/ui/const-generics/transmute_no_gate.stderr
new file mode 100644
index 000000000000..9c271b34849c
--- /dev/null
+++ b/tests/ui/const-generics/transmute_no_gate.stderr
@@ -0,0 +1,84 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:7:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; H]; W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; W]; H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:20:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; H]; W]` (this type does not have a fixed size)
+   = note: target type: `[u32; W * H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:27:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u32; H*W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; W]; H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:36:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[[u32; D]; H]; W]` (this type does not have a fixed size)
+   = note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:45:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[[u32; D]; H]; W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; D * W]; H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:52:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u16; L]` (this type does not have a fixed size)
+   = note: target type: `[u8; L * 2]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:59:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u8; L * 2]` (this type does not have a fixed size)
+   = note: target type: `[u16; L]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:66:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u8; L]` (this type does not have a fixed size)
+   = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:75:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; 2 * H]; W + W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; W + W]; 2 * H]` (this type does not have a fixed size)
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0512`.

From 5f50c0f7ac668bf1b2a29aa706d5b645e7060f65 Mon Sep 17 00:00:00 2001
From: Maybe Waffle 
Date: Fri, 7 Apr 2023 18:36:48 +0000
Subject: [PATCH 211/267] Document that `&T` and `&mut T` are `Sync` if `T` is

---
 library/core/src/primitive_docs.rs | 1 +
 library/std/src/primitive_docs.rs  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index bf8339335dd7..51e6947a9c25 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1362,6 +1362,7 @@ mod prim_usize {}
 /// * [`Hash`]
 /// * [`ToSocketAddrs`]
 /// * [`Send`] \(`&T` references also require T: [Sync])
+/// * [`Sync`]
 ///
 /// [`std::fmt`]: fmt
 /// [`Hash`]: hash::Hash
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index bf8339335dd7..51e6947a9c25 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -1362,6 +1362,7 @@ mod prim_usize {}
 /// * [`Hash`]
 /// * [`ToSocketAddrs`]
 /// * [`Send`] \(`&T` references also require T: [Sync])
+/// * [`Sync`]
 ///
 /// [`std::fmt`]: fmt
 /// [`Hash`]: hash::Hash

From f7f2eb3e4171e4b87dbcab3a9a6709d5d084c54f Mon Sep 17 00:00:00 2001
From: Matthew Jasper 
Date: Fri, 7 Apr 2023 19:45:17 +0100
Subject: [PATCH 212/267] Move `FnPtrAddr` error to `SessionDiagnostic`

---
 compiler/rustc_ty_utils/messages.ftl    | 2 ++
 compiler/rustc_ty_utils/src/errors.rs   | 7 +++++++
 compiler/rustc_ty_utils/src/instance.rs | 9 +++++----
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl
index abe65a0e3fef..e0aa27b73f62 100644
--- a/compiler/rustc_ty_utils/messages.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -45,3 +45,5 @@ ty_utils_control_flow_not_supported = control flow is not supported in generic c
 ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
 
 ty_utils_operation_not_supported = unsupported operation in generic constants
+
+ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index ab3e62f04845..c05815d510ae 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -67,3 +67,10 @@ pub enum GenericConstantTooComplexSub {
     #[label(ty_utils_operation_not_supported)]
     OperationNotSupported(#[primary_span] Span),
 }
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_unexpected_fnptr_associated_item)]
+pub struct UnexpectedFnPtrAssociatedItem {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index ad70154c98ef..0a6c118093e5 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -8,6 +8,8 @@ use rustc_span::sym;
 use rustc_trait_selection::traits;
 use traits::{translate_substs, Reveal};
 
+use crate::errors::UnexpectedFnPtrAssociatedItem;
+
 fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
@@ -282,10 +284,9 @@ fn resolve_associated_item<'tcx>(
                         substs: rcvr_substs,
                     })
                 } else {
-                    tcx.sess.span_fatal(
-                        tcx.def_span(trait_item_id),
-                        "`FnPtrAddr` trait with unexpected assoc item",
-                    )
+                    tcx.sess.emit_fatal(UnexpectedFnPtrAssociatedItem {
+                        span: tcx.def_span(trait_item_id),
+                    })
                 }
             } else {
                 None

From eeec73244d2ab68e23b17b13f1163b254e597718 Mon Sep 17 00:00:00 2001
From: ozkanonur 
Date: Sat, 8 Apr 2023 00:30:49 +0300
Subject: [PATCH 213/267] download beta compiler toolchain in bootstrap if it
 doesn't yet exist

This is needed for when the shell scripts bypass python altogether and run the downloaded
bootstrap directly. Changes are mainly provided from @jyn514, I just fixed the review notes.

Signed-off-by: ozkanonur 
---
 src/bootstrap/config.rs   | 21 +++++++++----
 src/bootstrap/download.rs | 64 +++++++++++++++++++++++++++++++++------
 src/bootstrap/test.rs     |  2 +-
 3 files changed, 70 insertions(+), 17 deletions(-)

diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 0fee094c2223..ec41288d25c1 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -223,25 +223,34 @@ pub struct Config {
     pub reuse: Option,
     pub cargo_native_static: bool,
     pub configure_args: Vec,
+    pub out: PathBuf,
+    pub rust_info: channel::GitInfo,
 
     // These are either the stage0 downloaded binaries or the locally installed ones.
     pub initial_cargo: PathBuf,
     pub initial_rustc: PathBuf,
+
     #[cfg(not(test))]
     initial_rustfmt: RefCell,
     #[cfg(test)]
     pub initial_rustfmt: RefCell,
-    pub out: PathBuf,
-    pub rust_info: channel::GitInfo,
 }
 
 #[derive(Default, Deserialize)]
 #[cfg_attr(test, derive(Clone))]
 pub struct Stage0Metadata {
+    pub compiler: CompilerMetadata,
     pub config: Stage0Config,
     pub checksums_sha256: HashMap,
     pub rustfmt: Option,
 }
+#[derive(Default, Deserialize)]
+#[cfg_attr(test, derive(Clone))]
+pub struct CompilerMetadata {
+    pub date: String,
+    pub version: String,
+}
+
 #[derive(Default, Deserialize)]
 #[cfg_attr(test, derive(Clone))]
 pub struct Stage0Config {
@@ -989,10 +998,10 @@ impl Config {
             config.out = crate::util::absolute(&config.out);
         }
 
-        config.initial_rustc = build
-            .rustc
-            .map(PathBuf::from)
-            .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/rustc"));
+        config.initial_rustc = build.rustc.map(PathBuf::from).unwrap_or_else(|| {
+            config.download_beta_toolchain();
+            config.out.join(config.build.triple).join("stage0/bin/rustc")
+        });
         config.initial_cargo = build
             .cargo
             .map(PathBuf::from)
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index d1e2149d3f95..478d2e8cacc3 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -367,26 +367,70 @@ impl Config {
 
     pub(crate) fn download_ci_rustc(&self, commit: &str) {
         self.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})"));
+
         let version = self.artifact_version_part(commit);
+        // download-rustc doesn't need its own cargo, it can just use beta's. But it does need the
+        // `rustc_private` crates for tools.
+        let extra_components = ["rustc-dev"];
+
+        self.download_toolchain(
+            &version,
+            "ci-rustc",
+            commit,
+            &extra_components,
+            Self::download_ci_component,
+        );
+    }
+
+    pub(crate) fn download_beta_toolchain(&self) {
+        self.verbose(&format!("downloading stage0 beta artifacts"));
+
+        let date = &self.stage0_metadata.compiler.date;
+        let version = &self.stage0_metadata.compiler.version;
+        let extra_components = ["cargo"];
+
+        let download_beta_component = |config: &Config, filename, prefix: &_, date: &_| {
+            config.download_component(DownloadSource::Dist, filename, prefix, date, "stage0")
+        };
+
+        self.download_toolchain(
+            version,
+            "stage0",
+            date,
+            &extra_components,
+            download_beta_component,
+        );
+    }
+
+    fn download_toolchain(
+        &self,
+        // FIXME(ozkanonur) use CompilerMetadata instead of `version: &str`
+        version: &str,
+        sysroot: &str,
+        stamp_key: &str,
+        extra_components: &[&str],
+        download_component: fn(&Config, String, &str, &str),
+    ) {
         let host = self.build.triple;
-        let bin_root = self.out.join(host).join("ci-rustc");
+        let bin_root = self.out.join(host).join(sysroot);
         let rustc_stamp = bin_root.join(".rustc-stamp");
 
-        if !bin_root.join("bin").join("rustc").exists() || program_out_of_date(&rustc_stamp, commit)
+        if !bin_root.join("bin").join(exe("rustc", self.build)).exists()
+            || program_out_of_date(&rustc_stamp, stamp_key)
         {
             if bin_root.exists() {
                 t!(fs::remove_dir_all(&bin_root));
             }
             let filename = format!("rust-std-{version}-{host}.tar.xz");
             let pattern = format!("rust-std-{host}");
-            self.download_ci_component(filename, &pattern, commit);
+            download_component(self, filename, &pattern, stamp_key);
             let filename = format!("rustc-{version}-{host}.tar.xz");
-            self.download_ci_component(filename, "rustc", commit);
-            // download-rustc doesn't need its own cargo, it can just use beta's.
-            let filename = format!("rustc-dev-{version}-{host}.tar.xz");
-            self.download_ci_component(filename, "rustc-dev", commit);
-            let filename = format!("rust-src-{version}.tar.xz");
-            self.download_ci_component(filename, "rust-src", commit);
+            download_component(self, filename, "rustc", stamp_key);
+
+            for component in extra_components {
+                let filename = format!("{component}-{version}-{host}.tar.xz");
+                download_component(self, filename, component, stamp_key);
+            }
 
             if self.should_fix_bins_and_dylibs() {
                 self.fix_bin_or_dylib(&bin_root.join("bin").join("rustc"));
@@ -403,7 +447,7 @@ impl Config {
                 }
             }
 
-            t!(fs::write(rustc_stamp, commit));
+            t!(fs::write(rustc_stamp, stamp_key));
         }
     }
 
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index baddc9da48db..171e1ccf0468 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1133,7 +1133,7 @@ impl Step for Tidy {
         if builder.config.channel == "dev" || builder.config.channel == "nightly" {
             builder.info("fmt check");
             if builder.initial_rustfmt().is_none() {
-                let inferred_rustfmt_dir = builder.config.initial_rustc.parent().unwrap();
+                let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap();
                 eprintln!(
                     "\
 error: no `rustfmt` binary found in {PATH}

From 7e9e91c3d395941b21dd1c791ff936ae44b4d45b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rn=20Bethune?= 
Date: Fri, 7 Apr 2023 23:49:20 +0200
Subject: [PATCH 214/267] Fix wrong type in docs: i16 -> u16

@rustbot label +A-docs

r? docs
---
 library/core/src/num/shells/u16.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/num/shells/u16.rs b/library/core/src/num/shells/u16.rs
index b203806f4600..7394977e5078 100644
--- a/library/core/src/num/shells/u16.rs
+++ b/library/core/src/num/shells/u16.rs
@@ -1,4 +1,4 @@
-//! Redundant constants module for the [`i16` primitive type][i16].
+//! Redundant constants module for the [`u16` primitive type][u16].
 //!
 //! New code should use the associated constants directly on the primitive type.
 

From 081e222d99be8a5dd795244abafd64cc05e3d00e Mon Sep 17 00:00:00 2001
From: Sergei Belokon 
Date: Sat, 8 Apr 2023 08:19:47 +1000
Subject: [PATCH 215/267] fix(tcp): remove redundant `format!` macro call

---
 library/std/src/net/tcp.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 6a5f2923210d..4b42ad65ee6b 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -869,7 +869,7 @@ impl TcpListener {
     /// use std::net::{TcpListener, TcpStream};
     ///
     /// fn listen_on(port: u16) -> impl Iterator {
-    ///     let listener = TcpListener::bind(format!("127.0.0.1:{port}")).unwrap();
+    ///     let listener = TcpListener::bind(("127.0.0.1", port)).unwrap();
     ///     listener.into_incoming()
     ///         .filter_map(Result::ok) /* Ignore failed connections */
     /// }

From f8b62ff535ec1957e3a3b36bf7b0debc22ef447c Mon Sep 17 00:00:00 2001
From: Eric Holk 
Date: Fri, 7 Apr 2023 15:24:08 -0700
Subject: [PATCH 216/267] Remove myself from reviewers list

I'm going to be unable to review for the next few weeks, so I'm
removing myself from the review queue. Once I'm back and able to review
again, I'll add myself back to the list.
---
 triagebot.toml | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/triagebot.toml b/triagebot.toml
index 2d7be7d12734..5f4de0562f89 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -470,8 +470,8 @@ cc = ["@rust-lang/style"]
 
 [mentions."Cargo.lock"]
 message = """
-These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs. 
-This was probably unintentional and should be reverted before this PR is merged. 
+These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs.
+This was probably unintentional and should be reverted before this PR is merged.
 
 If this was intentional then you can ignore this comment.
 """
@@ -499,7 +499,6 @@ compiler-team = [
 ]
 compiler-team-contributors = [
     "@compiler-errors",
-    "@eholk",
     "@jackh726",
     "@TaKO8Ki",
     "@WaffleLapkin",

From 066638b94ae1f19a059e813e54e6c3fb95efdcd2 Mon Sep 17 00:00:00 2001
From: Obei Sideg 
Date: Fri, 7 Apr 2023 02:04:42 +0300
Subject: [PATCH 217/267] Migrate `rustc_hir_analysis` to session diagnostic

Part 3: Finishing `collect.rs` file
---
 compiler/rustc_hir_analysis/messages.ftl   |  36 +++++
 compiler/rustc_hir_analysis/src/collect.rs | 165 +++++++--------------
 compiler/rustc_hir_analysis/src/errors.rs  | 124 ++++++++++++++++
 3 files changed, 215 insertions(+), 110 deletions(-)

diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index a57f39878491..1d7965ff5f66 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -189,3 +189,39 @@ hir_analysis_return_type_notation_equality_bound =
 
 hir_analysis_return_type_notation_missing_method =
     cannot find associated function `{$assoc_name}` in trait `{$trait_name}`
+
+hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
+    .label = not allowed in type signatures
+
+hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
+    .suggestion = use a fully qualified path with inferred lifetimes
+
+hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
+
+hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
+    .label = overflowed on value after {$discr}
+    .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
+
+hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
+    .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
+
+hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
+
+hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
+
+hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
+    .note = required by this annotation
+
+hir_analysis_must_implement_not_function = not a function
+
+hir_analysis_must_implement_not_function_span_note = required by this annotation
+
+hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
+
+hir_analysis_function_not_found_in_trait = function not found in this trait
+
+hir_analysis_functions_names_duplicated = functions names are duplicated
+    .note = all `#[rustc_must_implement_one_of]` arguments must be unique
+
+hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code
+    .help = add `#![feature(simd_ffi)]` to the crate attributes to enable
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index c41e96290df1..50862e342623 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -20,7 +20,7 @@ use crate::errors;
 use hir::def::DefKind;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
@@ -333,17 +333,7 @@ fn bad_placeholder<'tcx>(
     let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) };
 
     spans.sort();
-    let mut err = struct_span_err!(
-        tcx.sess,
-        spans.clone(),
-        E0121,
-        "the placeholder `_` is not allowed within types on item signatures for {}",
-        kind
-    );
-    for span in spans {
-        err.span_label(span, "not allowed in type signatures");
-    }
-    err
+    tcx.sess.create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
 }
 
 impl<'tcx> ItemCtxt<'tcx> {
@@ -419,13 +409,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
             self.tcx().mk_projection(item_def_id, item_substs)
         } else {
             // There are no late-bound regions; we can just ignore the binder.
-            let mut err = struct_span_err!(
-                self.tcx().sess,
-                span,
-                E0212,
-                "cannot use the associated type of a trait \
-                 with uninferred generic parameters"
-            );
+            let (mut mpart_sugg, mut inferred_sugg) = (None, None);
+            let mut bound = String::new();
 
             match self.node() {
                 hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
@@ -444,31 +429,25 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
                                     (bound.span.shrink_to_lo(), format!("{}, ", lt_name))
                                 }
                             };
-                            let suggestions = vec![
-                                (lt_sp, sugg),
-                                (
-                                    span.with_hi(item_segment.ident.span.lo()),
-                                    format!(
-                                        "{}::",
-                                        // Replace the existing lifetimes with a new named lifetime.
-                                        self.tcx.replace_late_bound_regions_uncached(
-                                            poly_trait_ref,
-                                            |_| {
-                                                self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
-                                                    def_id: item_def_id,
-                                                    index: 0,
-                                                    name: Symbol::intern(<_name),
-                                                })
-                                            }
-                                        ),
+                            mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+                                fspan: lt_sp,
+                                first: sugg,
+                                sspan: span.with_hi(item_segment.ident.span.lo()),
+                                second: format!(
+                                    "{}::",
+                                    // Replace the existing lifetimes with a new named lifetime.
+                                    self.tcx.replace_late_bound_regions_uncached(
+                                        poly_trait_ref,
+                                        |_| {
+                                            self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                                                def_id: item_def_id,
+                                                index: 0,
+                                                name: Symbol::intern(<_name),
+                                            })
+                                        }
                                     ),
                                 ),
-                            ];
-                            err.multipart_suggestion(
-                                "use a fully qualified path with explicit lifetimes",
-                                suggestions,
-                                Applicability::MaybeIncorrect,
-                            );
+                            });
                         }
                         _ => {}
                     }
@@ -482,20 +461,23 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
                 | hir::Node::ForeignItem(_)
                 | hir::Node::TraitItem(_)
                 | hir::Node::ImplItem(_) => {
-                    err.span_suggestion_verbose(
-                        span.with_hi(item_segment.ident.span.lo()),
-                        "use a fully qualified path with inferred lifetimes",
-                        format!(
-                            "{}::",
-                            // Erase named lt, we want `::C`, not `::C`.
-                            self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
-                        ),
-                        Applicability::MaybeIncorrect,
+                    inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
+                    bound = format!(
+                        "{}::",
+                        // Erase named lt, we want `::C`, not `::C`.
+                        self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
                     );
                 }
                 _ => {}
             }
-            self.tcx().ty_error(err.emit())
+            self.tcx().ty_error(self.tcx().sess.emit_err(
+                errors::AssociatedTypeTraitUninferredGenericParams {
+                    span,
+                    inferred_sugg,
+                    bound,
+                    mpart_sugg,
+                },
+            ))
         }
     }
 
@@ -763,14 +745,12 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
                 Some(discr)
             } else {
                 let span = tcx.def_span(variant.def_id);
-                struct_span_err!(tcx.sess, span, E0370, "enum discriminant overflowed")
-                    .span_label(span, format!("overflowed on value after {}", prev_discr.unwrap()))
-                    .note(&format!(
-                        "explicitly set `{} = {}` if that is desired outcome",
-                        tcx.item_name(variant.def_id),
-                        wrapped_discr
-                    ))
-                    .emit();
+                tcx.sess.emit_err(errors::EnumDiscriminantOverflowed {
+                    span,
+                    discr: prev_discr.unwrap().to_string(),
+                    item_name: tcx.item_name(variant.def_id),
+                    wrapped_discr: wrapped_discr.to_string(),
+                });
                 None
             }
             .unwrap_or(wrapped_discr),
@@ -915,14 +895,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
 
     let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
     if paren_sugar && !tcx.features().unboxed_closures {
-        tcx.sess
-            .struct_span_err(
-                item.span,
-                "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
-                 which traits can use parenthetical notation",
-            )
-            .help("add `#![feature(unboxed_closures)]` to the crate attributes to use it")
-            .emit();
+        tcx.sess.emit_err(errors::ParenSugarAttribute { span: item.span });
     }
 
     let is_marker = tcx.has_attr(def_id, sym::marker);
@@ -942,13 +915,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
         // and that they are all identifiers
         .and_then(|attr| match attr.meta_item_list() {
             Some(items) if items.len() < 2 => {
-                tcx.sess
-                    .struct_span_err(
-                        attr.span,
-                        "the `#[rustc_must_implement_one_of]` attribute must be \
-                         used with at least 2 args",
-                    )
-                    .emit();
+                tcx.sess.emit_err(errors::MustImplementOneOfAttribute { span: attr.span });
 
                 None
             }
@@ -957,9 +924,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
                 .map(|item| item.ident().ok_or(item.span()))
                 .collect::, _>>()
                 .map_err(|span| {
-                    tcx.sess
-                        .struct_span_err(span, "must be a name of an associated function")
-                        .emit();
+                    tcx.sess.emit_err(errors::MustBeNameOfAssociatedFunction { span });
                 })
                 .ok()
                 .zip(Some(attr.span)),
@@ -975,13 +940,10 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
                 match item {
                     Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
                         if !tcx.impl_defaultness(item.id.owner_id).has_value() {
-                            tcx.sess
-                                .struct_span_err(
-                                    item.span,
-                                    "function doesn't have a default implementation",
-                                )
-                                .span_note(attr_span, "required by this annotation")
-                                .emit();
+                            tcx.sess.emit_err(errors::FunctionNotHaveDefaultImplementation {
+                                span: item.span,
+                                note_span: attr_span,
+                            });
 
                             return Some(());
                         }
@@ -989,19 +951,14 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
                         return None;
                     }
                     Some(item) => {
-                        tcx.sess
-                            .struct_span_err(item.span, "not a function")
-                            .span_note(attr_span, "required by this annotation")
-                            .note(
-                                "all `#[rustc_must_implement_one_of]` arguments must be associated \
-                                 function names",
-                            )
-                            .emit();
+                        tcx.sess.emit_err(errors::MustImplementNotFunction {
+                            span: item.span,
+                            span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
+                            note: errors::MustImplementNotFunctionNote {},
+                        });
                     }
                     None => {
-                        tcx.sess
-                            .struct_span_err(ident.span, "function not found in this trait")
-                            .emit();
+                        tcx.sess.emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
                     }
                 }
 
@@ -1018,9 +975,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
             for ident in &*list {
                 if let Some(dup) = set.insert(ident.name, ident.span) {
                     tcx.sess
-                        .struct_span_err(vec![dup, ident.span], "functions names are duplicated")
-                        .note("all `#[rustc_must_implement_one_of]` arguments must be unique")
-                        .emit();
+                        .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
 
                     no_dups = false;
                 }
@@ -1485,17 +1440,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
                     .source_map()
                     .span_to_snippet(ast_ty.span)
                     .map_or_else(|_| String::new(), |s| format!(" `{}`", s));
-                tcx.sess
-                    .struct_span_err(
-                        ast_ty.span,
-                        &format!(
-                            "use of SIMD type{} in FFI is highly experimental and \
-                             may result in invalid code",
-                            snip
-                        ),
-                    )
-                    .help("add `#![feature(simd_ffi)]` to the crate attributes to enable")
-                    .emit();
+                tcx.sess.emit_err(errors::SIMDFFIHighlyExperimental { span: ast_ty.span, snip });
             }
         };
         for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index c71ce9a0bc7c..2a3a683489dd 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -507,3 +507,127 @@ pub(crate) struct ReturnTypeNotationMissingMethod {
     pub trait_name: Symbol,
     pub assoc_name: Symbol,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")]
+pub(crate) struct PlaceholderNotAllowedItemSignatures {
+    #[primary_span]
+    #[label]
+    pub spans: Vec,
+    pub kind: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = "E0212")]
+pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")]
+    pub inferred_sugg: Option,
+    pub bound: String,
+    #[subdiagnostic]
+    pub mpart_sugg: Option,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion,
+    applicability = "maybe-incorrect"
+)]
+pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+    #[suggestion_part(code = "{first}")]
+    pub fspan: Span,
+    pub first: String,
+    #[suggestion_part(code = "{second}")]
+    pub sspan: Span,
+    pub second: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_enum_discriminant_overflowed, code = "E0370")]
+#[note]
+pub(crate) struct EnumDiscriminantOverflowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub discr: String,
+    pub item_name: Symbol,
+    pub wrapped_discr: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_paren_sugar_attribute)]
+#[help]
+pub(crate) struct ParenSugarAttribute {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_must_implement_one_of_attribute)]
+pub(crate) struct MustImplementOneOfAttribute {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_must_be_name_of_associated_function)]
+pub(crate) struct MustBeNameOfAssociatedFunction {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_function_not_have_default_implementation)]
+pub(crate) struct FunctionNotHaveDefaultImplementation {
+    #[primary_span]
+    pub span: Span,
+    #[note]
+    pub note_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_must_implement_not_function)]
+pub(crate) struct MustImplementNotFunction {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub span_note: MustImplementNotFunctionSpanNote,
+    #[subdiagnostic]
+    pub note: MustImplementNotFunctionNote,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_analysis_must_implement_not_function_span_note)]
+pub(crate) struct MustImplementNotFunctionSpanNote {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_analysis_must_implement_not_function_note)]
+pub(crate) struct MustImplementNotFunctionNote {}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_function_not_found_in_trait)]
+pub(crate) struct FunctionNotFoundInTrait {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_functions_names_duplicated)]
+#[note]
+pub(crate) struct FunctionNamesDuplicated {
+    #[primary_span]
+    pub spans: Vec,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_simd_ffi_highly_experimental)]
+#[help]
+pub(crate) struct SIMDFFIHighlyExperimental {
+    #[primary_span]
+    pub span: Span,
+    pub snip: String,
+}

From 9920baba5f459668b70131df64bb85bd82c3b149 Mon Sep 17 00:00:00 2001
From: Andrew Xie 
Date: Fri, 7 Apr 2023 19:41:08 -0400
Subject: [PATCH 218/267] Switched provisional evaluation cache map to
 FxIndexMap, and replaced map.drain_filter with map.retain

---
 .../src/traits/select/mod.rs                  | 24 +++++++------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index d2d75d2aa4cc..6bb53418beab 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2,12 +2,6 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
 
-// FIXME: The `map` field in ProvisionalEvaluationCache should be changed to
-// a `FxIndexMap` to avoid query instability, but right now it causes a perf regression. This would be
-// fixed or at least lightened by the addition of the `drain_filter` method to `FxIndexMap`
-// Relevant: https://github.com/rust-lang/rust/pull/103723 and https://github.com/bluss/indexmap/issues/242
-#![allow(rustc::potential_query_instability)]
-
 use self::EvaluationResult::*;
 use self::SelectionCandidate::*;
 
@@ -32,8 +26,7 @@ use crate::traits::project::ProjectAndUnifyResult;
 use crate::traits::project::ProjectionCacheKeyExt;
 use crate::traits::ProjectionCacheKey;
 use crate::traits::Unimplemented;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::Diagnostic;
 use rustc_hir as hir;
@@ -2782,7 +2775,7 @@ struct ProvisionalEvaluationCache<'tcx> {
     /// - then we determine that `E` is in error -- we will then clear
     ///   all cache values whose DFN is >= 4 -- in this case, that
     ///   means the cached value for `F`.
-    map: RefCell, ProvisionalEvaluation>>,
+    map: RefCell, ProvisionalEvaluation>>,
 
     /// The stack of args that we assume to be true because a `WF(arg)` predicate
     /// is on the stack above (and because of wellformedness is coinductive).
@@ -2930,12 +2923,13 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
     /// have a performance impact in practice.
     fn on_completion(&self, dfn: usize) {
         debug!(?dfn, "on_completion");
-
-        for (fresh_trait_pred, eval) in
-            self.map.borrow_mut().drain_filter(|_k, eval| eval.from_dfn >= dfn)
-        {
-            debug!(?fresh_trait_pred, ?eval, "on_completion");
-        }
+        self.map.borrow_mut().retain(|fresh_trait_pred, eval| {
+            if eval.from_dfn >= dfn {
+                debug!(?fresh_trait_pred, ?eval, "on_completion");
+                return false;
+            }
+            true
+        });
     }
 }
 

From c4f686401dab0a532a6acd09aaaa2ba8ea99346c Mon Sep 17 00:00:00 2001
From: Matt Harding 
Date: Sat, 8 Apr 2023 06:36:59 +0100
Subject: [PATCH 219/267] Correct missed rename of config.example.toml

This commit:
fcb2a3665f6 (Rename `config.toml.example` to `config.example.toml`, 2023-03-11)
missed an instance in `config.example.toml` itself.
---
 config.example.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config.example.toml b/config.example.toml
index 5ef83760aed2..15c6bc0f1237 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -16,7 +16,7 @@
 # Use different pre-set defaults than the global defaults.
 #
 # See `src/bootstrap/defaults` for more information.
-# Note that this has no default value (x.py uses the defaults in `config.toml.example`).
+# Note that this has no default value (x.py uses the defaults in `config.example.toml`).
 #profile = 
 
 # Keeps track of the last version of `x.py` used.

From c80a69440c39aca92e73577cbeb0699415ecfcea Mon Sep 17 00:00:00 2001
From: Gimbles <93856041+gimbles@users.noreply.github.com>
Date: Fri, 7 Apr 2023 23:15:25 +0530
Subject: [PATCH 220/267] s/ignore_git/omit_git_hash

---
 config.example.toml                              |  2 +-
 src/bootstrap/channel.rs                         |  6 +++---
 src/bootstrap/config.rs                          | 12 ++++++------
 src/bootstrap/lib.rs                             | 16 ++++++++--------
 src/bootstrap/tool.rs                            |  2 +-
 .../host-x86_64/x86_64-gnu-distcheck/Dockerfile  |  2 +-
 6 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/config.example.toml b/config.example.toml
index 5ef83760aed2..edc72d3ec1cb 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -585,7 +585,7 @@ changelog-seen = 2
 # Having the git information can cause a lot of rebuilds during development.
 #
 # FIXME(#76720): this can causes bugs if different compilers reuse the same metadata cache.
-#ignore-git = if rust.channel == "dev" { true } else { false }
+#omit-git-hash = if rust.channel == "dev" { true } else { false }
 
 # Whether to create a source tarball by default when running `x dist`.
 #
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index eae81b9fc69c..390047f6fdce 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -19,7 +19,7 @@ pub enum GitInfo {
     #[default]
     Absent,
     /// This is a git repository.
-    /// If the info should be used (`ignore_git` is false), this will be
+    /// If the info should be used (`omit_git_hash` is false), this will be
     /// `Some`, otherwise it will be `None`.
     Present(Option),
     /// This is not a git repostory, but the info can be fetched from the
@@ -35,7 +35,7 @@ pub struct Info {
 }
 
 impl GitInfo {
-    pub fn new(ignore_git: bool, dir: &Path) -> GitInfo {
+    pub fn new(omit_git_hash: bool, dir: &Path) -> GitInfo {
         // See if this even begins to look like a git dir
         if !dir.join(".git").exists() {
             match read_commit_info_file(dir) {
@@ -52,7 +52,7 @@ impl GitInfo {
 
         // If we're ignoring the git info, we don't actually need to collect it, just make sure this
         // was a git repo in the first place.
-        if ignore_git {
+        if omit_git_hash {
             return GitInfo::Present(None);
         }
 
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index b8b6b7b2d4e9..7a934e16f5a3 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -77,7 +77,7 @@ pub struct Config {
     pub tools: Option>,
     pub sanitizers: bool,
     pub profiler: bool,
-    pub ignore_git: bool,
+    pub omit_git_hash: bool,
     pub exclude: Vec,
     pub include_default_paths: bool,
     pub rustc_error_format: Option,
@@ -755,7 +755,7 @@ define_config! {
         verbose_tests: Option = "verbose-tests",
         optimize_tests: Option = "optimize-tests",
         codegen_tests: Option = "codegen-tests",
-        ignore_git: Option = "ignore-git",
+        omit_git_hash: Option = "omit-git-hash",
         dist_src: Option = "dist-src",
         save_toolstates: Option = "save-toolstates",
         codegen_backends: Option> = "codegen-backends",
@@ -1088,7 +1088,7 @@ impl Config {
         let mut debuginfo_level_tools = None;
         let mut debuginfo_level_tests = None;
         let mut optimize = None;
-        let mut ignore_git = None;
+        let mut omit_git_hash = None;
 
         if let Some(rust) = toml.rust {
             debug = rust.debug;
@@ -1109,7 +1109,7 @@ impl Config {
                 .map(|v| v.expect("invalid value for rust.split_debuginfo"))
                 .unwrap_or(SplitDebuginfo::default_for_platform(&config.build.triple));
             optimize = rust.optimize;
-            ignore_git = rust.ignore_git;
+            omit_git_hash = rust.omit_git_hash;
             config.rust_new_symbol_mangling = rust.new_symbol_mangling;
             set(&mut config.rust_optimize_tests, rust.optimize_tests);
             set(&mut config.codegen_tests, rust.codegen_tests);
@@ -1166,8 +1166,8 @@ impl Config {
 
         // rust_info must be set before is_ci_llvm_available() is called.
         let default = config.channel == "dev";
-        config.ignore_git = ignore_git.unwrap_or(default);
-        config.rust_info = GitInfo::new(config.ignore_git, &config.src);
+        config.omit_git_hash = omit_git_hash.unwrap_or(default);
+        config.rust_info = GitInfo::new(config.omit_git_hash, &config.src);
 
         if let Some(llvm) = toml.llvm {
             match llvm.ccache {
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index e3f3ab5243e2..5ee18cf64110 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -358,14 +358,14 @@ impl Build {
         #[cfg(not(unix))]
         let is_sudo = false;
 
-        let ignore_git = config.ignore_git;
-        let rust_info = channel::GitInfo::new(ignore_git, &src);
-        let cargo_info = channel::GitInfo::new(ignore_git, &src.join("src/tools/cargo"));
+        let omit_git_hash = config.omit_git_hash;
+        let rust_info = channel::GitInfo::new(omit_git_hash, &src);
+        let cargo_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/cargo"));
         let rust_analyzer_info =
-            channel::GitInfo::new(ignore_git, &src.join("src/tools/rust-analyzer"));
-        let clippy_info = channel::GitInfo::new(ignore_git, &src.join("src/tools/clippy"));
-        let miri_info = channel::GitInfo::new(ignore_git, &src.join("src/tools/miri"));
-        let rustfmt_info = channel::GitInfo::new(ignore_git, &src.join("src/tools/rustfmt"));
+            channel::GitInfo::new(omit_git_hash, &src.join("src/tools/rust-analyzer"));
+        let clippy_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/clippy"));
+        let miri_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/miri"));
+        let rustfmt_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt"));
 
         // we always try to use git for LLVM builds
         let in_tree_llvm_info = channel::GitInfo::new(false, &src.join("src/llvm-project"));
@@ -1233,7 +1233,7 @@ impl Build {
         match &self.config.channel[..] {
             "stable" => num.to_string(),
             "beta" => {
-                if self.rust_info().is_managed_git_subrepository() && !self.config.ignore_git {
+                if self.rust_info().is_managed_git_subrepository() && !self.config.omit_git_hash {
                     format!("{}-beta.{}", num, self.beta_prerelease_version())
                 } else {
                     format!("{}-beta", num)
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 3c9a154da9ab..6a687a7903e0 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -320,7 +320,7 @@ pub fn prepare_tool_cargo(
     cargo.env("CFG_RELEASE_NUM", &builder.version);
     cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
 
-    let info = GitInfo::new(builder.config.ignore_git, &dir);
+    let info = GitInfo::new(builder.config.omit_git_hash, &dir);
     if let Some(sha) = info.sha() {
         cargo.env("CFG_COMMIT_HASH", sha);
     }
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
index 7e640c49f015..2217e6ee7043 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
@@ -24,6 +24,6 @@ RUN sh /scripts/sccache.sh
 # We are disabling CI LLVM since distcheck is an offline build.
 ENV NO_DOWNLOAD_CI_LLVM 1
 
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.ignore-git=false
+ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.omit-git-hash=false
 ENV SCRIPT python3 ../x.py --stage 2 test distcheck
 ENV DIST_SRC 1

From f1ded91a48034c3649f72202894811c3e669a65a Mon Sep 17 00:00:00 2001
From: Gimbles <93856041+gimbles@users.noreply.github.com>
Date: Fri, 7 Apr 2023 22:50:03 +0530
Subject: [PATCH 221/267] rm box_items

fix in plugin.md

fmt
---
 .../src/language-features/lang-items.md          | 16 ++++++++++++----
 .../src/language-features/plugin.md              |  4 ++--
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
index 39238dffa103..6adb3506e646 100644
--- a/src/doc/unstable-book/src/language-features/lang-items.md
+++ b/src/doc/unstable-book/src/language-features/lang-items.md
@@ -16,18 +16,26 @@ and one for deallocation. A freestanding program that uses the `Box`
 sugar for dynamic allocations via `malloc` and `free`:
 
 ```rust,ignore (libc-is-finicky)
-#![feature(lang_items, box_syntax, start, libc, core_intrinsics, rustc_private)]
+#![feature(lang_items, start, libc, core_intrinsics, rustc_private, rustc_attrs)]
 #![no_std]
 use core::intrinsics;
 use core::panic::PanicInfo;
+use core::ptr::NonNull;
 
 extern crate libc;
 
-struct Unique(*mut T);
+struct Unique(NonNull);
 
 #[lang = "owned_box"]
 pub struct Box(Unique);
 
+impl Box {
+    pub fn new(x: T) -> Self {
+        #[rustc_box]
+        Box::new(x)
+    }
+}
+
 #[lang = "exchange_malloc"]
 unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
     let p = libc::malloc(size as libc::size_t) as *mut u8;
@@ -47,13 +55,13 @@ unsafe fn box_free(ptr: *mut T) {
 
 #[start]
 fn main(_argc: isize, _argv: *const *const u8) -> isize {
-    let _x = box 1;
+    let _x = Box::new(1);
 
     0
 }
 
 #[lang = "eh_personality"] extern fn rust_eh_personality() {}
-#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } }
+#[lang = "panic_impl"] extern fn rust_begin_panic(_info: &PanicInfo) -> ! { intrinsics::abort() }
 #[no_mangle] pub extern fn rust_eh_register_frames () {}
 #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
 ```
diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
index dfbb468d4df9..1fade6ce95b8 100644
--- a/src/doc/unstable-book/src/language-features/plugin.md
+++ b/src/doc/unstable-book/src/language-features/plugin.md
@@ -37,7 +37,7 @@ additional checks for code style, safety, etc. Now let's write a plugin
 that warns about any item named `lintme`.
 
 ```rust,ignore (requires-stage-2)
-#![feature(box_syntax, rustc_private)]
+#![feature(rustc_private)]
 
 extern crate rustc_ast;
 
@@ -68,7 +68,7 @@ impl EarlyLintPass for Pass {
 #[no_mangle]
 fn __rustc_plugin_registrar(reg: &mut Registry) {
     reg.lint_store.register_lints(&[&TEST_LINT]);
-    reg.lint_store.register_early_pass(|| box Pass);
+    reg.lint_store.register_early_pass(|| Box::new(Pass));
 }
 ```
 

From ee554e24445effe121393f06d1f4f6dae9332ad4 Mon Sep 17 00:00:00 2001
From: Matt Harding 
Date: Sat, 8 Apr 2023 07:16:24 +0100
Subject: [PATCH 222/267] Make "codegen" config.toml profile build llvm

---
 src/bootstrap/defaults/config.codegen.toml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/bootstrap/defaults/config.codegen.toml b/src/bootstrap/defaults/config.codegen.toml
index 20b2699c761b..113df88d7c34 100644
--- a/src/bootstrap/defaults/config.codegen.toml
+++ b/src/bootstrap/defaults/config.codegen.toml
@@ -9,6 +9,8 @@ compiler-docs = true
 assertions = true
 # enable warnings during the llvm compilation
 enable-warnings = true
+# build llvm from source
+download-ci-llvm = false
 
 [rust]
 # This enables `RUSTC_LOG=debug`, avoiding confusing situations

From 04a5d611615a47b877c83cc72a5e6db3112adbc4 Mon Sep 17 00:00:00 2001
From: Deadbeef 
Date: Tue, 28 Mar 2023 00:00:58 +0000
Subject: [PATCH 223/267] Revert "Mark DoubleEndedIterator as #[const_trait]
 using rustc_do_not_const_check, implement const Iterator and
 DoubleEndedIterator for Range."

This reverts commit 8a9d6bf4fd540b2a2882193cbd6232b86e5dcd7e.
---
 library/core/src/iter/range.rs                | 12 +++----
 library/core/src/iter/traits/double_ended.rs  | 11 +-----
 library/core/src/iter/traits/iterator.rs      | 13 +++----
 library/core/src/lib.rs                       |  1 -
 library/core/tests/iter/consts.rs             | 36 -------------------
 library/core/tests/iter/mod.rs                |  2 --
 library/core/tests/lib.rs                     |  3 --
 .../ui/typeck/typeck_type_placeholder_item.rs |  1 +
 .../typeck_type_placeholder_item.stderr       | 15 +++++++-
 9 files changed, 24 insertions(+), 70 deletions(-)
 delete mode 100644 library/core/tests/iter/consts.rs

diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 1cd71193bd77..2273bead416b 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1,5 +1,4 @@
 use crate::convert::TryFrom;
-use crate::marker::Destruct;
 use crate::mem;
 use crate::num::NonZeroUsize;
 use crate::ops::{self, Try};
@@ -524,7 +523,6 @@ macro_rules! range_incl_exact_iter_impl {
 }
 
 /// Specialization implementations for `Range`.
-#[const_trait]
 trait RangeIteratorImpl {
     type Item;
 
@@ -539,7 +537,7 @@ trait RangeIteratorImpl {
     fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>;
 }
 
-impl const RangeIteratorImpl for ops::Range {
+impl RangeIteratorImpl for ops::Range {
     type Item = A;
 
     #[inline]
@@ -625,7 +623,7 @@ impl const RangeIteratorImpl for ops::Range
     }
 }
 
-impl const RangeIteratorImpl for ops::Range {
+impl RangeIteratorImpl for ops::Range {
     #[inline]
     fn spec_next(&mut self) -> Option {
         if self.start < self.end {
@@ -713,8 +711,7 @@ impl const RangeIteratorImpl for ops::R
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
-impl const Iterator for ops::Range {
+impl Iterator for ops::Range {
     type Item = A;
 
     #[inline]
@@ -824,8 +821,7 @@ range_incl_exact_iter_impl! {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
-impl const DoubleEndedIterator for ops::Range {
+impl DoubleEndedIterator for ops::Range {
     #[inline]
     fn next_back(&mut self) -> Option {
         self.spec_next_back()
diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs
index d82ecb698dd0..182d9f758adc 100644
--- a/library/core/src/iter/traits/double_ended.rs
+++ b/library/core/src/iter/traits/double_ended.rs
@@ -1,4 +1,3 @@
-use crate::marker::Destruct;
 use crate::num::NonZeroUsize;
 use crate::ops::{ControlFlow, Try};
 
@@ -39,7 +38,6 @@ use crate::ops::{ControlFlow, Try};
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")]
-#[const_trait]
 pub trait DoubleEndedIterator: Iterator {
     /// Removes and returns an element from the end of the iterator.
     ///
@@ -136,10 +134,7 @@ pub trait DoubleEndedIterator: Iterator {
     /// [`Err(k)`]: Err
     #[inline]
     #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
-    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>
-    where
-        Self::Item: ~const Destruct,
-    {
+    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
         for i in 0..n {
             if self.next_back().is_none() {
                 // SAFETY: `i` is always less than `n`.
@@ -192,7 +187,6 @@ pub trait DoubleEndedIterator: Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_nth_back", since = "1.37.0")]
-    #[rustc_do_not_const_check]
     fn nth_back(&mut self, n: usize) -> Option {
         if self.advance_back_by(n).is_err() {
             return None;
@@ -232,7 +226,6 @@ pub trait DoubleEndedIterator: Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iterator_try_fold", since = "1.27.0")]
-    #[rustc_do_not_const_check]
     fn try_rfold(&mut self, init: B, mut f: F) -> R
     where
         Self: Sized,
@@ -304,7 +297,6 @@ pub trait DoubleEndedIterator: Iterator {
     #[doc(alias = "foldr")]
     #[inline]
     #[stable(feature = "iter_rfold", since = "1.27.0")]
-    #[rustc_do_not_const_check]
     fn rfold(mut self, init: B, mut f: F) -> B
     where
         Self: Sized,
@@ -360,7 +352,6 @@ pub trait DoubleEndedIterator: Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_rfind", since = "1.27.0")]
-    #[rustc_do_not_const_check]
     fn rfind

(&mut self, predicate: P) -> Option where Self: Sized, diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 36cf7defd6de..f3d1e45f4fb6 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1,6 +1,5 @@ use crate::array; use crate::cmp::{self, Ordering}; -use crate::marker::Destruct; use crate::num::NonZeroUsize; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; @@ -340,10 +339,8 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] - fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> - where - Self::Item: ~const Destruct, - { + #[rustc_do_not_const_check] + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { for i in 0..n { if self.next().is_none() { // SAFETY: `i` is always less than `n`. @@ -394,10 +391,8 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn nth(&mut self, n: usize) -> Option - where - Self::Item: ~const Destruct, - { + #[rustc_do_not_const_check] + fn nth(&mut self, n: usize) -> Option { self.advance_by(n).ok()?; self.next() } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a6b9acb576eb..d195e24ef46d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -123,7 +123,6 @@ #![feature(const_index_range_slice_index)] #![feature(const_inherent_unchecked_arith)] #![feature(const_int_unchecked_arith)] -#![feature(const_intoiterator_identity)] #![feature(const_intrinsic_forget)] #![feature(const_ipv4)] #![feature(const_ipv6)] diff --git a/library/core/tests/iter/consts.rs b/library/core/tests/iter/consts.rs deleted file mode 100644 index d56687e48c96..000000000000 --- a/library/core/tests/iter/consts.rs +++ /dev/null @@ -1,36 +0,0 @@ -#[test] -fn const_manual_iter() { - struct S(bool); - - impl const Iterator for S { - type Item = (); - - fn next(&mut self) -> Option { - if self.0 == false { - self.0 = true; - Some(()) - } else { - None - } - } - } - const { - let mut val = S(false); - assert!(val.next().is_some()); - assert!(val.next().is_none()); - assert!(val.next().is_none()); - } -} - -#[test] -fn const_range() { - const { - let mut arr = [0; 3]; - for i in 0..arr.len() { - arr[i] = i; - } - assert!(arr[0] == 0); - assert!(arr[1] == 1); - assert!(arr[2] == 2); - } -} diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index cbb18e79e2d4..770b6f7601fa 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -20,8 +20,6 @@ mod range; mod sources; mod traits; -mod consts; - use core::cell::Cell; use core::convert::TryFrom; use core::iter::*; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 344f0b61754e..6cdafa411d00 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -12,11 +12,8 @@ #![feature(const_caller_location)] #![feature(const_cell_into_inner)] #![feature(const_convert)] -#![feature(const_for)] #![feature(const_hash)] #![feature(const_heap)] -#![feature(const_intoiterator_identity)] -#![feature(const_iter)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init_read)] #![feature(const_nonnull_new)] diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index e6f7dc410b61..a450dbb82d1b 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -228,4 +228,5 @@ fn evens_squared(n: usize) -> _ { const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); //~^ ERROR the trait bound +//~| ERROR the trait bound //~| ERROR the placeholder diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 9144ab9e3a6b..bc6c9fd07799 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -437,6 +437,19 @@ LL | fn evens_squared(n: usize) -> _ { | not allowed in type signatures | help: replace with an appropriate return type: `impl Iterator` +error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied + --> $DIR/typeck_type_placeholder_item.rs:229:22 + | +LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); + | ^^^^^^ `std::ops::Range<{integer}>` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` +note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` + --> $DIR/typeck_type_placeholder_item.rs:229:14 + | +LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); + | ^^^^^^^ + error[E0277]: the trait bound `Filter, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>: Iterator` is not satisfied --> $DIR/typeck_type_placeholder_item.rs:229:45 | @@ -664,7 +677,7 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error: aborting due to 72 previous errors +error: aborting due to 73 previous errors Some errors have detailed explanations: E0121, E0277, E0282, E0403. For more information about an error, try `rustc --explain E0121`. From 0cd49018d1e2d0e7b229aa9283b9254c58cd930b Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 28 Mar 2023 00:01:16 +0000 Subject: [PATCH 224/267] Revert "Make the `Step` implementations const." This reverts commit 7bc67ef6e02d69023c6fb04c2258beab54ac22b8. --- library/core/src/iter/range.rs | 20 ++++++-------------- library/core/src/iter/traits/marker.rs | 3 +-- library/core/src/lib.rs | 1 - 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 2273bead416b..37db074293d8 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -21,8 +21,7 @@ unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usi /// The *successor* operation moves towards values that compare greater. /// The *predecessor* operation moves towards values that compare lesser. #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] -#[const_trait] -pub trait Step: ~const Clone + ~const PartialOrd + Sized { +pub trait Step: Clone + PartialOrd + Sized { /// Returns the number of *successor* steps required to get from `start` to `end`. /// /// Returns `None` if the number of steps would overflow `usize` @@ -236,8 +235,7 @@ macro_rules! step_integer_impls { $( #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - #[rustc_const_unstable(feature = "const_iter", issue = "92476")] - impl const Step for $u_narrower { + impl Step for $u_narrower { step_identical_methods!(); #[inline] @@ -269,8 +267,7 @@ macro_rules! step_integer_impls { #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - #[rustc_const_unstable(feature = "const_iter", issue = "92476")] - impl const Step for $i_narrower { + impl Step for $i_narrower { step_identical_methods!(); #[inline] @@ -334,8 +331,7 @@ macro_rules! step_integer_impls { $( #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - #[rustc_const_unstable(feature = "const_iter", issue = "92476")] - impl const Step for $u_wider { + impl Step for $u_wider { step_identical_methods!(); #[inline] @@ -360,8 +356,7 @@ macro_rules! step_integer_impls { #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - #[rustc_const_unstable(feature = "const_iter", issue = "92476")] - impl const Step for $i_wider { + impl Step for $i_wider { step_identical_methods!(); #[inline] @@ -411,8 +406,7 @@ step_integer_impls! { } #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] -#[rustc_const_unstable(feature = "const_iter", issue = "92476")] -impl const Step for char { +impl Step for char { #[inline] fn steps_between(&start: &char, &end: &char) -> Option { let start = start as u32; @@ -430,7 +424,6 @@ impl const Step for char { } #[inline] - #[rustc_allow_const_fn_unstable(const_try)] fn forward_checked(start: char, count: usize) -> Option { let start = start as u32; let mut res = Step::forward_checked(start, count)?; @@ -447,7 +440,6 @@ impl const Step for char { } #[inline] - #[rustc_allow_const_fn_unstable(const_try)] fn backward_checked(start: char, count: usize) -> Option { let start = start as u32; let mut res = Step::backward_checked(start, count)?; diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs index c8f60defff77..af02848233d9 100644 --- a/library/core/src/iter/traits/marker.rs +++ b/library/core/src/iter/traits/marker.rs @@ -86,5 +86,4 @@ pub unsafe trait InPlaceIterable: Iterator {} /// for details. Consumers are free to rely on the invariants in unsafe code. #[unstable(feature = "trusted_step", issue = "85731")] #[rustc_specialization_trait] -#[const_trait] -pub unsafe trait TrustedStep: ~const Step {} +pub unsafe trait TrustedStep: Step {} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index d195e24ef46d..4fd5a4bfc65f 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -126,7 +126,6 @@ #![feature(const_intrinsic_forget)] #![feature(const_ipv4)] #![feature(const_ipv6)] -#![feature(const_iter)] #![feature(const_likely)] #![feature(const_maybe_uninit_uninit_array)] #![feature(const_maybe_uninit_as_mut_ptr)] From 2b36f5a40f523b563e04986126dedb86eb4a9470 Mon Sep 17 00:00:00 2001 From: Krishna Ramasimha <82328083+KittyBorgX@users.noreply.github.com> Date: Sat, 8 Apr 2023 13:49:00 +0530 Subject: [PATCH 225/267] Fix a typo in `config.example.toml` --- config.example.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.example.toml b/config.example.toml index 5ef83760aed2..15c6bc0f1237 100644 --- a/config.example.toml +++ b/config.example.toml @@ -16,7 +16,7 @@ # Use different pre-set defaults than the global defaults. # # See `src/bootstrap/defaults` for more information. -# Note that this has no default value (x.py uses the defaults in `config.toml.example`). +# Note that this has no default value (x.py uses the defaults in `config.example.toml`). #profile = # Keeps track of the last version of `x.py` used. From 2412f1b64576c29635275c31506f912ff32ec606 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 8 Apr 2023 08:50:46 +0000 Subject: [PATCH 226/267] bless ui tests --- tests/ui/consts/const-fn-error.rs | 1 + tests/ui/consts/const-fn-error.stderr | 19 ++++++++++++++++--- tests/ui/consts/const-for.rs | 1 + tests/ui/consts/const-for.stderr | 18 ++++++++++++++++-- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/tests/ui/consts/const-fn-error.rs b/tests/ui/consts/const-fn-error.rs index 50b7ce1f8c01..dabbd58dbe0a 100644 --- a/tests/ui/consts/const-fn-error.rs +++ b/tests/ui/consts/const-fn-error.rs @@ -7,6 +7,7 @@ const fn f(x: usize) -> usize { //~| ERROR `for` is not allowed in a `const fn` //~| ERROR mutable references are not allowed in constant functions //~| ERROR cannot call non-const fn + //~| ERROR the trait bound sum += i; } sum diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr index f735b3d53ce4..73d235d6aec5 100644 --- a/tests/ui/consts/const-fn-error.stderr +++ b/tests/ui/consts/const-fn-error.stderr @@ -5,7 +5,7 @@ LL | / for i in 0..x { LL | | LL | | LL | | -LL | | +... | LL | | sum += i; LL | | } | |_____^ @@ -33,6 +33,19 @@ LL | for i in 0..x { = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable +error[E0277]: the trait bound `std::ops::Range: Iterator` is not satisfied + --> $DIR/const-fn-error.rs:5:14 + | +LL | for i in 0..x { + | ^^^^ `std::ops::Range` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range` +note: the trait `Iterator` is implemented for `std::ops::Range`, but that implementation is not `const` + --> $DIR/const-fn-error.rs:5:14 + | +LL | for i in 0..x { + | ^^^^ + error[E0015]: cannot call non-const fn ` as Iterator>::next` in constant functions --> $DIR/const-fn-error.rs:5:14 | @@ -42,7 +55,7 @@ LL | for i in 0..x { = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0015, E0658. +Some errors have detailed explanations: E0015, E0277, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-for.rs b/tests/ui/consts/const-for.rs index 8db248535583..ff9c977f7948 100644 --- a/tests/ui/consts/const-for.rs +++ b/tests/ui/consts/const-for.rs @@ -5,6 +5,7 @@ const _: () = { for _ in 0..5 {} //~^ error: cannot call //~| error: cannot convert + //~| error: the trait bound }; fn main() {} diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr index 3fb9787c0d86..64f2f603b943 100644 --- a/tests/ui/consts/const-for.stderr +++ b/tests/ui/consts/const-for.stderr @@ -9,6 +9,19 @@ note: impl defined here, but it is not `const` = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable +error[E0277]: the trait bound `std::ops::Range: Iterator` is not satisfied + --> $DIR/const-for.rs:5:14 + | +LL | for _ in 0..5 {} + | ^^^^ `std::ops::Range` is not an iterator + | + = help: the trait `~const Iterator` is not implemented for `std::ops::Range` +note: the trait `Iterator` is implemented for `std::ops::Range`, but that implementation is not `const` + --> $DIR/const-for.rs:5:14 + | +LL | for _ in 0..5 {} + | ^^^^ + error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants --> $DIR/const-for.rs:5:14 | @@ -18,6 +31,7 @@ LL | for _ in 0..5 {} = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0015, E0277. +For more information about an error, try `rustc --explain E0015`. From fdfca765a71770d743981e71aab01625188328fc Mon Sep 17 00:00:00 2001 From: klensy Date: Sat, 8 Apr 2023 12:15:26 +0300 Subject: [PATCH 227/267] fixup: use Bool instead of bool --- compiler/rustc_codegen_llvm/src/builder.rs | 12 ++++++++++-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 74f3a662d602..6819a2af09da 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2,7 +2,7 @@ use crate::abi::FnAbiLlvmExt; use crate::attributes; use crate::common::Funclet; use crate::context::CodegenCx; -use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock}; +use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True}; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -841,7 +841,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { - unsafe { llvm::LLVMBuildIntCast2(self.llbuilder, val, dest_ty, is_signed, UNNAMED) } + unsafe { + llvm::LLVMBuildIntCast2( + self.llbuilder, + val, + dest_ty, + if is_signed { True } else { False }, + UNNAMED, + ) + } } fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index dc498f784b31..5b53b4c7c568 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1626,7 +1626,7 @@ extern "C" { B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, - IsSigned: bool, + IsSigned: Bool, Name: *const c_char, ) -> &'a Value; From d11b9165ee594fc6dd30b40e96bd7b32c04d2d3c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 Mar 2023 17:57:39 +0400 Subject: [PATCH 228/267] resolve: Preserve reexport chains in `ModChild`ren This may be potentially useful for - avoiding uses of `hir::ItemKind::Use` - preserving documentation comments on all reexports - preserving and checking stability/deprecation info on reexports - all kinds of diagnostics --- compiler/rustc_metadata/src/rmeta/decoder.rs | 2 +- compiler/rustc_middle/src/arena.rs | 1 + compiler/rustc_middle/src/metadata.rs | 26 ++++++++++++++++++- compiler/rustc_middle/src/query/erase.rs | 1 - .../rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/imports.rs | 21 +++++++++++++++ src/librustdoc/clean/inline.rs | 2 +- 7 files changed, 50 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 852c6d964694..f9d32ffceef6 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -991,7 +991,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { _ => false, }; - ModChild { ident, res, vis, span, macro_rules } + ModChild { ident, res, vis, span, macro_rules, reexport_chain: Default::default() } } /// Iterates over all named children of the given module, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 9f16ecbdaa93..dd1e254f405b 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -119,6 +119,7 @@ macro_rules! arena_types { [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>, [decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap, [] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>), + [] mod_child: rustc_middle::metadata::ModChild, ]); ) } diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs index 5ff014c7815a..fabc6bce7317 100644 --- a/compiler/rustc_middle/src/metadata.rs +++ b/compiler/rustc_middle/src/metadata.rs @@ -5,13 +5,34 @@ use rustc_macros::HashStable; use rustc_span::def_id::DefId; use rustc_span::symbol::Ident; use rustc_span::Span; +use smallvec::SmallVec; + +/// A simplified version of `ImportKind` from resolve. +/// `DefId`s here correspond to `use` and `extern crate` items themselves, not their targets. +#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, HashStable)] +pub enum Reexport { + Single(DefId), + Glob(DefId), + ExternCrate(DefId), + MacroUse, + MacroExport, +} + +impl Reexport { + pub fn id(self) -> Option { + match self { + Reexport::Single(id) | Reexport::Glob(id) | Reexport::ExternCrate(id) => Some(id), + Reexport::MacroUse | Reexport::MacroExport => None, + } + } +} /// This structure is supposed to keep enough data to re-create `NameBinding`s for other crates /// during name resolution. Right now the bindings are not recreated entirely precisely so we may /// need to add more data in the future to correctly support macros 2.0, for example. /// Module child can be either a proper item or a reexport (including private imports). /// In case of reexport all the fields describe the reexport item itself, not what it refers to. -#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(Debug, TyEncodable, TyDecodable, HashStable)] pub struct ModChild { /// Name of the item. pub ident: Ident, @@ -24,4 +45,7 @@ pub struct ModChild { pub span: Span, /// A proper `macro_rules` item (not a reexport). pub macro_rules: bool, + /// Reexport chain linking this module child to its original reexported item. + /// Empty if the module child is a proper item. + pub reexport_chain: SmallVec<[Reexport; 2]>, } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 5462ced16d6b..24d98665a7b4 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -235,7 +235,6 @@ trivial! { rustc_hir::OwnerId, rustc_hir::Upvar, rustc_index::bit_set::FiniteBitSet, - rustc_middle::metadata::ModChild, rustc_middle::middle::dependency_format::Linkage, rustc_middle::middle::exported_symbols::SymbolExportInfo, rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 49c41470a151..1f2a90829ec7 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -931,7 +931,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { /// Builds the reduced graph for a single item in an external crate. fn build_reduced_graph_for_external_crate_res(&mut self, child: ModChild) { let parent = self.parent_scope.module; - let ModChild { ident, res, vis, span, macro_rules } = child; + let ModChild { ident, res, vis, span, macro_rules, .. } = child; let res = res.expect_non_local(); let expansion = self.parent_scope.expansion; // Record primary definitions. diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index bc17ce571a7c..77bfcb659de1 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -17,6 +17,7 @@ use rustc_data_structures::intern::Interned; use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; use rustc_hir::def::{self, DefKind, PartialRes}; use rustc_middle::metadata::ModChild; +use rustc_middle::metadata::Reexport; use rustc_middle::span_bug; use rustc_middle::ty; use rustc_session::lint::builtin::{ @@ -27,6 +28,7 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; +use smallvec::SmallVec; use std::cell::Cell; use std::{mem, ptr}; @@ -190,6 +192,17 @@ impl<'a> Import<'a> { ImportKind::MacroUse | ImportKind::MacroExport => None, } } + + fn simplify(&self, r: &Resolver<'_, '_>) -> Reexport { + let to_def_id = |id| r.local_def_id(id).to_def_id(); + match self.kind { + ImportKind::Single { id, .. } => Reexport::Single(to_def_id(id)), + ImportKind::Glob { id, .. } => Reexport::Glob(to_def_id(id)), + ImportKind::ExternCrate { id, .. } => Reexport::ExternCrate(to_def_id(id)), + ImportKind::MacroUse => Reexport::MacroUse, + ImportKind::MacroExport => Reexport::MacroExport, + } + } } /// Records information about the resolution of a name in a namespace of a module. @@ -1252,12 +1265,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module.for_each_child(self, |this, ident, _, binding| { if let Some(res) = this.is_reexport(binding) { + let mut reexport_chain = SmallVec::new(); + let mut next_binding = binding; + while let NameBindingKind::Import { binding, import, .. } = next_binding.kind { + reexport_chain.push(import.simplify(this)); + next_binding = binding; + } + reexports.push(ModChild { ident, res, vis: binding.vis, span: binding.span, macro_rules: false, + reexport_chain, }); } }); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 768f8bb7bc89..87f9483388f7 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -558,7 +558,7 @@ fn build_module_items( // If we're re-exporting a re-export it may actually re-export something in // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. - for &item in cx.tcx.module_children(did).iter() { + for item in cx.tcx.module_children(did).iter() { if item.vis.is_public() { let res = item.res.expect_non_local(); if let Some(def_id) = res.opt_def_id() From b20ecc7c35e1c976c8c448086db7955e8bf61607 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 7 Apr 2023 19:15:05 +0300 Subject: [PATCH 229/267] rustdoc: Migrate some logic to `module_reexports` --- src/librustdoc/clean/mod.rs | 169 +++++++----------------------------- src/librustdoc/visit_ast.rs | 12 ++- 2 files changed, 34 insertions(+), 147 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1c57cd7a9461..cfff4e206897 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -21,6 +21,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::PredicateOrigin; use rustc_hir_analysis::hir_ty_to_ty; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; +use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::InternalSubsts; @@ -2056,141 +2057,44 @@ fn clean_bare_fn_ty<'tcx>( BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params } } -/// Get DefId of of an item's user-visible parent. -/// -/// "User-visible" should account for re-exporting and inlining, which is why this function isn't -/// just `tcx.parent(def_id)`. If the provided `path` has more than one path element, the `DefId` -/// of the second-to-last will be given. -/// -/// ```text -/// use crate::foo::Bar; -/// ^^^ DefId of this item will be returned -/// ``` -/// -/// If the provided path has only one item, `tcx.parent(def_id)` will be returned instead. -fn get_path_parent_def_id( - tcx: TyCtxt<'_>, - def_id: DefId, - path: &hir::UsePath<'_>, -) -> Option { - if let [.., parent_segment, _] = &path.segments { - match parent_segment.res { - hir::def::Res::Def(_, parent_def_id) => Some(parent_def_id), - _ if parent_segment.ident.name == kw::Crate => { - // In case the "parent" is the crate, it'll give `Res::Err` so we need to - // circumvent it this way. - Some(tcx.parent(def_id)) - } - _ => None, - } - } else { - // If the path doesn't have a parent, then the parent is the current module. - Some(tcx.parent(def_id)) - } -} - -/// This visitor is used to find an HIR Item based on its `use` path. This doesn't use the ordinary -/// name resolver because it does not walk all the way through a chain of re-exports. -pub(crate) struct OneLevelVisitor<'hir> { - map: rustc_middle::hir::map::Map<'hir>, - pub(crate) item: Option<&'hir hir::Item<'hir>>, - looking_for: Ident, +pub(crate) fn reexport_chain<'tcx>( + tcx: TyCtxt<'tcx>, + import_def_id: LocalDefId, target_def_id: LocalDefId, -} - -impl<'hir> OneLevelVisitor<'hir> { - pub(crate) fn new(map: rustc_middle::hir::map::Map<'hir>, target_def_id: LocalDefId) -> Self { - Self { map, item: None, looking_for: Ident::empty(), target_def_id } - } - - pub(crate) fn find_target( - &mut self, - tcx: TyCtxt<'_>, - def_id: DefId, - path: &hir::UsePath<'_>, - ) -> Option<&'hir hir::Item<'hir>> { - let parent_def_id = get_path_parent_def_id(tcx, def_id, path)?; - let parent = self.map.get_if_local(parent_def_id)?; - - // We get the `Ident` we will be looking for into `item`. - self.looking_for = path.segments[path.segments.len() - 1].ident; - // We reset the `item`. - self.item = None; - - match parent { - hir::Node::Item(parent_item) => { - hir::intravisit::walk_item(self, parent_item); - } - hir::Node::Crate(m) => { - hir::intravisit::walk_mod( - self, - m, - tcx.local_def_id_to_hir_id(parent_def_id.as_local().unwrap()), - ); - } - _ => return None, - } - self.item - } -} - -impl<'hir> hir::intravisit::Visitor<'hir> for OneLevelVisitor<'hir> { - type NestedFilter = rustc_middle::hir::nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.map - } - - fn visit_item(&mut self, item: &'hir hir::Item<'hir>) { - if self.item.is_none() - && item.ident == self.looking_for - && (matches!(item.kind, hir::ItemKind::Use(_, _)) - || item.owner_id.def_id == self.target_def_id) +) -> &'tcx [Reexport] { + for child in tcx.module_reexports(tcx.local_parent(import_def_id)).unwrap_or_default() { + if child.res.opt_def_id() == Some(target_def_id.to_def_id()) + && child.reexport_chain[0].id() == Some(import_def_id.to_def_id()) { - self.item = Some(item); + return &child.reexport_chain; } } + &[] } -/// Because a `Use` item directly links to the imported item, we need to manually go through each -/// import one by one. To do so, we go to the parent item and look for the `Ident` into it. Then, -/// if we found the "end item" (the imported one), we stop there because we don't need its -/// documentation. Otherwise, we repeat the same operation until we find the "end item". +/// Collect attributes from the whole import chain. fn get_all_import_attributes<'hir>( - mut item: &hir::Item<'hir>, cx: &mut DocContext<'hir>, + import_def_id: LocalDefId, target_def_id: LocalDefId, is_inline: bool, - mut prev_import: LocalDefId, ) -> Vec<(Cow<'hir, ast::Attribute>, Option)> { - let mut attributes: Vec<(Cow<'hir, ast::Attribute>, Option)> = Vec::new(); + let mut attrs = Vec::new(); let mut first = true; - let hir_map = cx.tcx.hir(); - let mut visitor = OneLevelVisitor::new(hir_map, target_def_id); - let mut visited = FxHashSet::default(); - - // If the item is an import and has at least a path with two parts, we go into it. - while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) { - let import_parent = cx.tcx.opt_local_parent(prev_import).map(|def_id| def_id.to_def_id()); + for def_id in reexport_chain(cx.tcx, import_def_id, target_def_id) + .iter() + .flat_map(|reexport| reexport.id()) + { + let import_attrs = inline::load_attrs(cx, def_id); if first { // This is the "original" reexport so we get all its attributes without filtering them. - attributes = hir_map.attrs(item.hir_id()) - .iter() - .map(|attr| (Cow::Borrowed(attr), import_parent)) - .collect::>(); + attrs = import_attrs.iter().map(|attr| (Cow::Borrowed(attr), Some(def_id))).collect(); first = false; } else { - add_without_unwanted_attributes(&mut attributes, hir_map.attrs(item.hir_id()), is_inline, import_parent); + add_without_unwanted_attributes(&mut attrs, import_attrs, is_inline, Some(def_id)); } - - if let Some(i) = visitor.find_target(cx.tcx, item.owner_id.def_id.to_def_id(), path) { - item = i; - } else { - break; - } - prev_import = item.owner_id.def_id; } - attributes + attrs } fn filter_tokens_from_list( @@ -2375,39 +2279,24 @@ fn clean_maybe_renamed_item<'tcx>( _ => unreachable!("not yet converted"), }; - let attrs = if let Some(import_id) = import_id && - let Some(hir::Node::Item(use_node)) = cx.tcx.hir().find_by_def_id(import_id) - { + let target_attrs = inline::load_attrs(cx, def_id); + let attrs = if let Some(import_id) = import_id { let is_inline = inline::load_attrs(cx, import_id.to_def_id()) .lists(sym::doc) .get_word_attr(sym::inline) .is_some(); - // Then we get all the various imports' attributes. - let mut attrs = get_all_import_attributes( - use_node, - cx, - item.owner_id.def_id, - is_inline, - import_id, - ); - - add_without_unwanted_attributes( - &mut attrs, - inline::load_attrs(cx, def_id), - is_inline, - None - ); + let mut attrs = + get_all_import_attributes(cx, import_id, item.owner_id.def_id, is_inline); + add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None); attrs } else { // We only keep the item's attributes. - inline::load_attrs(cx, def_id).iter().map(|attr| (Cow::Borrowed(attr), None)).collect::>() + target_attrs.iter().map(|attr| (Cow::Borrowed(attr), None)).collect() }; let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg); - let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| match attr { - Cow::Borrowed(attr) => (*attr, *did), - Cow::Owned(attr) => (attr, *did) - }), false); + let attrs = + Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false); let mut item = Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c959bb3701ab..383e8f669433 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -13,9 +13,9 @@ use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; -use std::mem; +use std::{iter, mem}; -use crate::clean::{cfg::Cfg, AttributesExt, NestedAttributesExt, OneLevelVisitor}; +use crate::clean::{cfg::Cfg, reexport_chain, AttributesExt, NestedAttributesExt}; use crate::core; /// This module is used to store stuff from Rust's AST in a more convenient @@ -220,7 +220,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { renamed: Option, glob: bool, please_inline: bool, - path: &hir::UsePath<'_>, ) -> bool { debug!("maybe_inline_local res: {:?}", res); @@ -266,9 +265,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } if !please_inline && - let mut visitor = OneLevelVisitor::new(self.cx.tcx.hir(), res_did) && - let Some(item) = visitor.find_target(self.cx.tcx, def_id.to_def_id(), path) && - let item_def_id = item.owner_id.def_id && + let Some(item_def_id) = reexport_chain(self.cx.tcx, def_id, res_did).iter() + .flat_map(|reexport| reexport.id()).map(|id| id.expect_local()) + .chain(iter::once(res_did)).nth(1) && item_def_id != def_id && self .cx @@ -383,7 +382,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { ident, is_glob, please_inline, - path, ) { continue; } From 612ddd2196fc2573baf8b1be85eb326f882fd2d3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 7 Apr 2023 19:15:20 +0300 Subject: [PATCH 230/267] std: Mark two reexports that should be inlined as `doc(inline)` --- library/std/src/collections/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index ae2baba09e68..575f56ff4df2 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -416,8 +416,10 @@ pub use alloc_crate::collections::{BTreeMap, BTreeSet, BinaryHeap}; pub use alloc_crate::collections::{LinkedList, VecDeque}; #[stable(feature = "rust1", since = "1.0.0")] +#[doc(inline)] pub use self::hash_map::HashMap; #[stable(feature = "rust1", since = "1.0.0")] +#[doc(inline)] pub use self::hash_set::HashSet; #[stable(feature = "try_reserve", since = "1.57.0")] From 9da9373bf0ebaf5fb2e4911d263a1950e2306157 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 7 Apr 2023 19:23:12 +0300 Subject: [PATCH 231/267] rustc_middle: Remove `Option` from `module_reexports` query --- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++-- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 16 ++++++---------- src/librustdoc/clean/inline.rs | 1 - src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/visit_ast.rs | 2 +- 7 files changed, 12 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index faf0592138bc..4291b9aa1426 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1327,8 +1327,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } })); - if let Some(reexports) = tcx.module_reexports(local_def_id) { - assert!(!reexports.is_empty()); + let reexports = tcx.module_reexports(local_def_id); + if !reexports.is_empty() { record_array!(self.tables.module_reexports[def_id] <- reexports); } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 964168967564..a0fce4b47ca3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1510,7 +1510,7 @@ rustc_queries! { desc { "getting traits in scope at a block" } } - query module_reexports(def_id: LocalDefId) -> Option<&'tcx [ModChild]> { + query module_reexports(def_id: LocalDefId) -> &'tcx [ModChild] { desc { |tcx| "looking up reexports of module `{}`", tcx.def_path_str(def_id.to_def_id()) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 299b1bf1d96e..2ef6180c4cbd 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2502,7 +2502,7 @@ pub struct DeducedParamAttrs { pub fn provide(providers: &mut ty::query::Providers) { providers.module_reexports = - |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); + |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map_or(&[], |v| &v[..]); providers.maybe_unused_trait_imports = |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports; providers.names_imported_by_glob_use = |tcx, id| { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d27505d1ac84..089e043d61c3 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -515,16 +515,12 @@ impl<'tcx> EmbargoVisitor<'tcx> { let vis = self.tcx.local_visibility(item_id.owner_id.def_id); self.update_macro_reachable_def(item_id.owner_id.def_id, def_kind, vis, defining_mod); } - if let Some(exports) = self.tcx.module_reexports(module_def_id) { - for export in exports { - if export.vis.is_accessible_from(defining_mod, self.tcx) { - if let Res::Def(def_kind, def_id) = export.res { - if let Some(def_id) = def_id.as_local() { - let vis = self.tcx.local_visibility(def_id); - self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod); - } - } - } + for export in self.tcx.module_reexports(module_def_id) { + if export.vis.is_accessible_from(defining_mod, self.tcx) + && let Res::Def(def_kind, def_id) = export.res + && let Some(def_id) = def_id.as_local() { + let vis = self.tcx.local_visibility(def_id); + self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod); } } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 87f9483388f7..9270d1c02e21 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -153,7 +153,6 @@ pub(crate) fn try_inline_glob( let reexports = cx .tcx .module_reexports(current_mod) - .unwrap_or_default() .iter() .filter_map(|child| child.res.opt_def_id()) .collect(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cfff4e206897..7f150f380253 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2062,7 +2062,7 @@ pub(crate) fn reexport_chain<'tcx>( import_def_id: LocalDefId, target_def_id: LocalDefId, ) -> &'tcx [Reexport] { - for child in tcx.module_reexports(tcx.local_parent(import_def_id)).unwrap_or_default() { + for child in tcx.module_reexports(tcx.local_parent(import_def_id)) { if child.res.opt_def_id() == Some(target_def_id.to_def_id()) && child.reexport_chain[0].id() == Some(import_def_id.to_def_id()) { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 383e8f669433..393d51fe0906 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // is declared but also a reexport of itself producing two exports of the same // macro in the same module. let mut inserted = FxHashSet::default(); - for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) { + for export in self.cx.tcx.module_reexports(CRATE_DEF_ID) { if let Res::Def(DefKind::Macro(_), def_id) = export.res && let Some(local_def_id) = def_id.as_local() && self.cx.tcx.has_attr(def_id, sym::macro_export) && From e6dc69ab4bef90e0f99e32f72b6dbeabaf7ab29e Mon Sep 17 00:00:00 2001 From: beetrees Date: Sat, 8 Apr 2023 00:22:03 +0100 Subject: [PATCH 232/267] Add `max_line_length` to `.editorconfig`, matching rustfmt --- .editorconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/.editorconfig b/.editorconfig index ec6e107d547f..03aab32bfc6e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,6 +11,7 @@ trim_trailing_whitespace = true insert_final_newline = true indent_style = space indent_size = 4 +max_line_length = 100 [*.md] # double whitespace at end of line From 804e93871dfc879380fdd3bcde6c6958466814af Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 8 Apr 2023 20:01:14 +0100 Subject: [PATCH 233/267] Move SIMD layout errors to `SessionDiagnostic` --- compiler/rustc_ty_utils/messages.ftl | 8 ++++++ compiler/rustc_ty_utils/src/errors.rs | 26 ++++++++++++++++++ compiler/rustc_ty_utils/src/layout.rs | 39 +++++++++++++-------------- compiler/rustc_ty_utils/src/lib.rs | 2 ++ 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl index e0aa27b73f62..a1e97bb95bc6 100644 --- a/compiler/rustc_ty_utils/messages.ftl +++ b/compiler/rustc_ty_utils/messages.ftl @@ -47,3 +47,11 @@ ty_utils_inline_asm_not_supported = assembly is not supported in generic constan ty_utils_operation_not_supported = unsupported operation in generic constants ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item + +ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length + +ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field + +ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes} + +ty_utils_non_primative_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}` diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index c05815d510ae..3db3c98e9e28 100644 --- a/compiler/rustc_ty_utils/src/errors.rs +++ b/compiler/rustc_ty_utils/src/errors.rs @@ -74,3 +74,29 @@ pub struct UnexpectedFnPtrAssociatedItem { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(ty_utils_zero_length_simd_type)] +pub struct ZeroLengthSimdType<'tcx> { + pub ty: Ty<'tcx>, +} + +#[derive(Diagnostic)] +#[diag(ty_utils_multiple_array_fields_simd_type)] +pub struct MultipleArrayFieldsSimdType<'tcx> { + pub ty: Ty<'tcx>, +} + +#[derive(Diagnostic)] +#[diag(ty_utils_oversized_simd_type)] +pub struct OversizedSimdType<'tcx> { + pub ty: Ty<'tcx>, + pub max_lanes: u64, +} + +#[derive(Diagnostic)] +#[diag(ty_utils_non_primative_simd_type)] +pub struct NonPrimitiveSimdType<'tcx> { + pub ty: Ty<'tcx>, + pub e_ty: Ty<'tcx>, +} diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index d4420ec88db9..d08877233b3f 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -17,6 +17,9 @@ use rustc_target::abi::*; use std::fmt::Debug; use std::iter; +use crate::errors::{ + MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType, +}; use crate::layout_sanity_check::sanity_check_layout; pub fn provide(providers: &mut ty::query::Providers) { @@ -294,6 +297,8 @@ fn layout_of_uncached<'tcx>( return Err(LayoutError::Unknown(ty)); } + let fields = &def.non_enum_variant().fields; + // Supported SIMD vectors are homogeneous ADTs with at least one field: // // * #[repr(simd)] struct S(T, T, T, T); @@ -304,18 +309,22 @@ fn layout_of_uncached<'tcx>( // SIMD vectors with zero fields are not supported. // (should be caught by typeck) - if def.non_enum_variant().fields.is_empty() { - tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty)); + if fields.is_empty() { + tcx.sess.emit_fatal(ZeroLengthSimdType { ty }) } // Type of the first ADT field: - let f0_ty = def.non_enum_variant().fields[FieldIdx::from_u32(0)].ty(tcx, substs); + let f0_ty = fields[FieldIdx::from_u32(0)].ty(tcx, substs); // Heterogeneous SIMD vectors are not supported: // (should be caught by typeck) - for fi in &def.non_enum_variant().fields { + for fi in fields { if fi.ty(tcx, substs) != f0_ty { - tcx.sess.fatal(&format!("monomorphising heterogeneous SIMD type `{}`", ty)); + tcx.sess.delay_span_bug( + DUMMY_SP, + "#[repr(simd)] was applied to an ADT with hetrogeneous field type", + ); + return Err(LayoutError::Unknown(ty)); } } @@ -330,12 +339,9 @@ fn layout_of_uncached<'tcx>( // First ADT field is an array: // SIMD vectors with multiple array fields are not supported: - // (should be caught by typeck) + // Can't be caught by typeck with a generic simd type. if def.non_enum_variant().fields.len() != 1 { - tcx.sess.fatal(&format!( - "monomorphising SIMD type `{}` with more than one array field", - ty - )); + tcx.sess.emit_fatal(MultipleArrayFieldsSimdType { ty }); } // Extract the number of elements from the layout of the array field: @@ -355,12 +361,9 @@ fn layout_of_uncached<'tcx>( // // Can't be caught in typeck if the array length is generic. if e_len == 0 { - tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty)); + tcx.sess.emit_fatal(ZeroLengthSimdType { ty }); } else if e_len > MAX_SIMD_LANES { - tcx.sess.fatal(&format!( - "monomorphising SIMD type `{}` of length greater than {}", - ty, MAX_SIMD_LANES, - )); + tcx.sess.emit_fatal(OversizedSimdType { ty, max_lanes: MAX_SIMD_LANES }); } // Compute the ABI of the element type: @@ -368,11 +371,7 @@ fn layout_of_uncached<'tcx>( let Abi::Scalar(e_abi) = e_ly.abi else { // This error isn't caught in typeck, e.g., if // the element type of the vector is generic. - tcx.sess.fatal(&format!( - "monomorphising SIMD type `{}` with a non-primitive-scalar \ - (integer/float/pointer) element type `{}`", - ty, e_ty - )) + tcx.sess.emit_fatal(NonPrimitiveSimdType {ty, e_ty }); }; // Compute the size and alignment of the vector: diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 9195964a2f36..2613445f39be 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -10,6 +10,8 @@ #![feature(never_type)] #![feature(box_patterns)] #![recursion_limit = "256"] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; From 8e76c7614917d687d49bdb0484473cb7b88d7fe2 Mon Sep 17 00:00:00 2001 From: matthewjasper <20113453+matthewjasper@users.noreply.github.com> Date: Sat, 8 Apr 2023 21:40:33 +0100 Subject: [PATCH 234/267] Update compiler/rustc_ty_utils/src/layout.rs Fix formatting that rustfmt can't handle currently. Co-authored-by: Michael Goulet --- compiler/rustc_ty_utils/src/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index d08877233b3f..63eb34f7d552 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -371,7 +371,7 @@ fn layout_of_uncached<'tcx>( let Abi::Scalar(e_abi) = e_ly.abi else { // This error isn't caught in typeck, e.g., if // the element type of the vector is generic. - tcx.sess.emit_fatal(NonPrimitiveSimdType {ty, e_ty }); + tcx.sess.emit_fatal(NonPrimitiveSimdType { ty, e_ty }); }; // Compute the size and alignment of the vector: From 920c51c5265833b1a587ad9206e271f49564e2cc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 20 Mar 2023 20:53:43 +0000 Subject: [PATCH 235/267] Enforce that PointerLike requires a pointer-like ABI --- compiler/rustc_abi/src/lib.rs | 10 ++++++++++ .../src/solve/trait_goals.rs | 3 +-- .../src/traits/select/candidate_assembly.rs | 15 +++++++-------- library/core/src/marker.rs | 2 +- tests/ui/dyn-star/align.normal.stderr | 13 +++++++++++-- tests/ui/dyn-star/align.over_aligned.stderr | 6 +++--- tests/ui/dyn-star/align.rs | 3 +-- .../check-size-at-cast-polymorphic-bad.rs | 2 +- .../check-size-at-cast-polymorphic-bad.stderr | 2 +- tests/ui/dyn-star/check-size-at-cast.rs | 2 +- tests/ui/dyn-star/check-size-at-cast.stderr | 2 +- tests/ui/dyn-star/upcast.stderr | 2 +- tests/ui/traits/new-solver/pointer-like.rs | 2 +- tests/ui/traits/new-solver/pointer-like.stderr | 2 +- 14 files changed, 41 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index da91776ef672..76765c8a0aa3 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1522,6 +1522,16 @@ impl<'a> Layout<'a> { pub fn size(self) -> Size { self.0.0.size } + + /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. + /// + /// Currently, that means that the type is pointer-sized, pointer-aligned, + /// and has a scalar ABI. + pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool { + self.size() == data_layout.pointer_size + && self.align().abi == data_layout.pointer_align.abi + && matches!(self.abi(), Abi::Scalar(..)) + } } #[derive(Copy, Clone, PartialEq, Eq, Debug)] diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index ce3db83d33dd..a2203473ca97 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -221,8 +221,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let self_ty = tcx.erase_regions(goal.predicate.self_ty()); if let Ok(layout) = tcx.layout_of(goal.param_env.and(self_ty)) - && layout.layout.size() == tcx.data_layout.pointer_size - && layout.layout.align().abi == tcx.data_layout.pointer_align.abi + && layout.layout.is_pointer_like(&tcx.data_layout) { // FIXME: We could make this faster by making a no-constraints response ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 090312338e00..a794d20d683f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -97,7 +97,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if lang_items.tuple_trait() == Some(def_id) { self.assemble_candidate_for_tuple(obligation, &mut candidates); } else if lang_items.pointer_like() == Some(def_id) { - self.assemble_candidate_for_ptr_sized(obligation, &mut candidates); + self.assemble_candidate_for_pointer_like(obligation, &mut candidates); } else if lang_items.fn_ptr_trait() == Some(def_id) { self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates); } else { @@ -942,15 +942,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn assemble_candidate_for_ptr_sized( + fn assemble_candidate_for_pointer_like( &mut self, obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // The regions of a type don't affect the size of the type - let self_ty = self - .tcx() - .erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate.self_ty())); + let tcx = self.tcx(); + let self_ty = + tcx.erase_regions(tcx.erase_late_bound_regions(obligation.predicate.self_ty())); // But if there are inference variables, we have to wait until it's resolved. if self_ty.has_non_region_infer() { @@ -958,9 +958,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - if let Ok(layout) = self.tcx().layout_of(obligation.param_env.and(self_ty)) - && layout.layout.size() == self.tcx().data_layout.pointer_size - && layout.layout.align().abi == self.tcx().data_layout.pointer_align.abi + if let Ok(layout) = tcx.layout_of(obligation.param_env.and(self_ty)) + && layout.layout.is_pointer_like(&tcx.data_layout) { candidates.vec.push(BuiltinCandidate { has_nested: false }); } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 74e9c55396d1..62064f1aa6cb 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -879,7 +879,7 @@ pub trait Tuple {} #[unstable(feature = "pointer_like_trait", issue = "none")] #[lang = "pointer_like"] #[rustc_on_unimplemented( - message = "`{Self}` needs to have the same alignment and size as a pointer", + message = "`{Self}` needs to have the same ABI as a pointer", label = "`{Self}` needs to be a pointer-like type" )] pub trait PointerLike {} diff --git a/tests/ui/dyn-star/align.normal.stderr b/tests/ui/dyn-star/align.normal.stderr index 53c2cbeac326..42fa4fd6f00c 100644 --- a/tests/ui/dyn-star/align.normal.stderr +++ b/tests/ui/dyn-star/align.normal.stderr @@ -1,5 +1,5 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/align.rs:4:12 + --> $DIR/align.rs:3:12 | LL | #![feature(dyn_star)] | ^^^^^^^^ @@ -7,5 +7,14 @@ LL | #![feature(dyn_star)] = note: see issue #102425 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +error[E0277]: `AlignedUsize` needs to have the same ABI as a pointer + --> $DIR/align.rs:14:13 + | +LL | let x = AlignedUsize(12) as dyn* Debug; + | ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-like type + | + = help: the trait `PointerLike` is not implemented for `AlignedUsize` +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/align.over_aligned.stderr b/tests/ui/dyn-star/align.over_aligned.stderr index 0365d87a6f82..42fa4fd6f00c 100644 --- a/tests/ui/dyn-star/align.over_aligned.stderr +++ b/tests/ui/dyn-star/align.over_aligned.stderr @@ -1,5 +1,5 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/align.rs:4:12 + --> $DIR/align.rs:3:12 | LL | #![feature(dyn_star)] | ^^^^^^^^ @@ -7,8 +7,8 @@ LL | #![feature(dyn_star)] = note: see issue #102425 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: `AlignedUsize` needs to have the same alignment and size as a pointer - --> $DIR/align.rs:15:13 +error[E0277]: `AlignedUsize` needs to have the same ABI as a pointer + --> $DIR/align.rs:14:13 | LL | let x = AlignedUsize(12) as dyn* Debug; | ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-like type diff --git a/tests/ui/dyn-star/align.rs b/tests/ui/dyn-star/align.rs index 6679997a9402..79cbaba0c78a 100644 --- a/tests/ui/dyn-star/align.rs +++ b/tests/ui/dyn-star/align.rs @@ -1,5 +1,4 @@ // revisions: normal over_aligned -//[normal] check-pass #![feature(dyn_star)] //~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes @@ -13,5 +12,5 @@ struct AlignedUsize(usize); fn main() { let x = AlignedUsize(12) as dyn* Debug; - //[over_aligned]~^ ERROR `AlignedUsize` needs to have the same alignment and size as a pointer + //~^ ERROR `AlignedUsize` needs to have the same ABI as a pointer } diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs index 85749aa7b00e..913c2faacbd6 100644 --- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs +++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs @@ -9,7 +9,7 @@ fn dyn_debug(_: (dyn* Debug + '_)) { fn polymorphic(t: &T) { dyn_debug(t); - //~^ ERROR `&T` needs to have the same alignment and size as a pointer + //~^ ERROR `&T` needs to have the same ABI as a pointer } fn main() {} diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr index 350630f79413..8726fae79a00 100644 --- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr +++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr @@ -1,4 +1,4 @@ -error[E0277]: `&T` needs to have the same alignment and size as a pointer +error[E0277]: `&T` needs to have the same ABI as a pointer --> $DIR/check-size-at-cast-polymorphic-bad.rs:11:15 | LL | dyn_debug(t); diff --git a/tests/ui/dyn-star/check-size-at-cast.rs b/tests/ui/dyn-star/check-size-at-cast.rs index 17bc4f303bff..e15e090b529a 100644 --- a/tests/ui/dyn-star/check-size-at-cast.rs +++ b/tests/ui/dyn-star/check-size-at-cast.rs @@ -5,6 +5,6 @@ use std::fmt::Debug; fn main() { let i = [1, 2, 3, 4] as dyn* Debug; - //~^ ERROR `[i32; 4]` needs to have the same alignment and size as a pointer + //~^ ERROR `[i32; 4]` needs to have the same ABI as a pointer dbg!(i); } diff --git a/tests/ui/dyn-star/check-size-at-cast.stderr b/tests/ui/dyn-star/check-size-at-cast.stderr index 19700b406440..e60b5c56ff04 100644 --- a/tests/ui/dyn-star/check-size-at-cast.stderr +++ b/tests/ui/dyn-star/check-size-at-cast.stderr @@ -1,4 +1,4 @@ -error[E0277]: `[i32; 4]` needs to have the same alignment and size as a pointer +error[E0277]: `[i32; 4]` needs to have the same ABI as a pointer --> $DIR/check-size-at-cast.rs:7:13 | LL | let i = [1, 2, 3, 4] as dyn* Debug; diff --git a/tests/ui/dyn-star/upcast.stderr b/tests/ui/dyn-star/upcast.stderr index e60144fea74c..8b34c7f8b710 100644 --- a/tests/ui/dyn-star/upcast.stderr +++ b/tests/ui/dyn-star/upcast.stderr @@ -7,7 +7,7 @@ LL | #![feature(dyn_star, trait_upcasting)] = note: see issue #102425 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: `dyn* Foo` needs to have the same alignment and size as a pointer +error[E0277]: `dyn* Foo` needs to have the same ABI as a pointer --> $DIR/upcast.rs:30:23 | LL | let w: dyn* Bar = w; diff --git a/tests/ui/traits/new-solver/pointer-like.rs b/tests/ui/traits/new-solver/pointer-like.rs index 3745a075e6a4..98630176976f 100644 --- a/tests/ui/traits/new-solver/pointer-like.rs +++ b/tests/ui/traits/new-solver/pointer-like.rs @@ -9,6 +9,6 @@ fn require_(_: impl PointerLike) {} fn main() { require_(1usize); require_(1u16); - //~^ ERROR `u16` needs to have the same alignment and size as a pointer + //~^ ERROR `u16` needs to have the same ABI as a pointer require_(&1i16); } diff --git a/tests/ui/traits/new-solver/pointer-like.stderr b/tests/ui/traits/new-solver/pointer-like.stderr index f695e64187d4..215a81cc2657 100644 --- a/tests/ui/traits/new-solver/pointer-like.stderr +++ b/tests/ui/traits/new-solver/pointer-like.stderr @@ -1,4 +1,4 @@ -error[E0277]: `u16` needs to have the same alignment and size as a pointer +error[E0277]: `u16` needs to have the same ABI as a pointer --> $DIR/pointer-like.rs:11:14 | LL | require_(1u16); From c17a7057580fcd76caec41939f1c4d5534ff790e Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 8 Apr 2023 22:14:57 +0100 Subject: [PATCH 236/267] Add test for new delayed bug code path --- tests/ui/simd/monomorphize-heterogeneous.rs | 9 +++++++++ tests/ui/simd/monomorphize-heterogeneous.stderr | 9 +++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/ui/simd/monomorphize-heterogeneous.rs create mode 100644 tests/ui/simd/monomorphize-heterogeneous.stderr diff --git a/tests/ui/simd/monomorphize-heterogeneous.rs b/tests/ui/simd/monomorphize-heterogeneous.rs new file mode 100644 index 000000000000..42e380dbb779 --- /dev/null +++ b/tests/ui/simd/monomorphize-heterogeneous.rs @@ -0,0 +1,9 @@ +#![feature(repr_simd)] + +#[repr(simd)] +struct I64F64(i64, f64); +//~^ ERROR SIMD vector should be homogeneous + +static X: I64F64 = I64F64(1, 2.0); + +fn main() {} diff --git a/tests/ui/simd/monomorphize-heterogeneous.stderr b/tests/ui/simd/monomorphize-heterogeneous.stderr new file mode 100644 index 000000000000..e7b41cd787cd --- /dev/null +++ b/tests/ui/simd/monomorphize-heterogeneous.stderr @@ -0,0 +1,9 @@ +error[E0076]: SIMD vector should be homogeneous + --> $DIR/monomorphize-heterogeneous.rs:4:1 + | +LL | struct I64F64(i64, f64); + | ^^^^^^^^^^^^^ SIMD elements must have the same type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0076`. From fbc3457d3582c44882ed20c5b11c6ba589163ab1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 8 Apr 2023 21:32:36 +0000 Subject: [PATCH 237/267] Tweak tuple indexing suggestion --- compiler/rustc_hir_typeck/src/expr.rs | 29 +++++++++++++++------------ tests/ui/index_message.rs | 4 ++-- tests/ui/index_message.stderr | 2 +- tests/ui/issues/issue-27842.rs | 5 +++++ tests/ui/issues/issue-27842.stderr | 12 ++++++++++- 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index c17aae22ba54..68e096e3bd02 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2810,23 +2810,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "cannot index into a value of type `{base_t}`", ); // Try to give some advice about indexing tuples. - if let ty::Tuple(..) = base_t.kind() { + if let ty::Tuple(types) = base_t.kind() { let mut needs_note = true; // If the index is an integer, we can show the actual // fixed expression: - if let ExprKind::Lit(ref lit) = idx.kind { - if let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node { - let snip = self.tcx.sess.source_map().span_to_snippet(base.span); - if let Ok(snip) = snip { - err.span_suggestion( - expr.span, - "to access tuple elements, use", - format!("{snip}.{i}"), - Applicability::MachineApplicable, - ); - needs_note = false; - } + if let ExprKind::Lit(ref lit) = idx.kind + && let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node + && i < types.len().try_into().expect("expected tuple index to be < usize length") + { + let snip = self.tcx.sess.source_map().span_to_snippet(base.span); + if let Ok(snip) = snip { + err.span_suggestion( + expr.span, + "to access tuple elements, use", + format!("{snip}.{i}"), + Applicability::MachineApplicable, + ); + needs_note = false; } + } else if let ExprKind::Path(..) = idx.peel_borrows().kind { + err.span_label(idx.span, "cannot access tuple elements at a variable index"); } if needs_note { err.help( diff --git a/tests/ui/index_message.rs b/tests/ui/index_message.rs index 87e0cde59195..88b848d6f857 100644 --- a/tests/ui/index_message.rs +++ b/tests/ui/index_message.rs @@ -1,4 +1,4 @@ fn main() { - let z = (); - let _ = z[0]; //~ ERROR cannot index into a value of type `()` + let z = (10,); + let _ = z[0]; //~ ERROR cannot index into a value of type `({integer},)` } diff --git a/tests/ui/index_message.stderr b/tests/ui/index_message.stderr index 6c2b126734b0..56d1d70809db 100644 --- a/tests/ui/index_message.stderr +++ b/tests/ui/index_message.stderr @@ -1,4 +1,4 @@ -error[E0608]: cannot index into a value of type `()` +error[E0608]: cannot index into a value of type `({integer},)` --> $DIR/index_message.rs:3:13 | LL | let _ = z[0]; diff --git a/tests/ui/issues/issue-27842.rs b/tests/ui/issues/issue-27842.rs index 3bcfa1330701..060d3b34e09d 100644 --- a/tests/ui/issues/issue-27842.rs +++ b/tests/ui/issues/issue-27842.rs @@ -8,4 +8,9 @@ fn main() { let i = 0_usize; let _ = tup[i]; //~^ ERROR cannot index into a value of type + + // the case where the index is out of bounds + let tup = (10,); + let _ = tup[3]; + //~^ ERROR cannot index into a value of type } diff --git a/tests/ui/issues/issue-27842.stderr b/tests/ui/issues/issue-27842.stderr index 784666a639e1..83333aa0c47b 100644 --- a/tests/ui/issues/issue-27842.stderr +++ b/tests/ui/issues/issue-27842.stderr @@ -8,10 +8,20 @@ error[E0608]: cannot index into a value of type `({integer}, {integer}, {integer --> $DIR/issue-27842.rs:9:13 | LL | let _ = tup[i]; + | ^^^^-^ + | | + | cannot access tuple elements at a variable index + | + = help: to access tuple elements, use tuple indexing syntax (e.g., `tuple.0`) + +error[E0608]: cannot index into a value of type `({integer},)` + --> $DIR/issue-27842.rs:14:13 + | +LL | let _ = tup[3]; | ^^^^^^ | = help: to access tuple elements, use tuple indexing syntax (e.g., `tuple.0`) -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0608`. From 5c75dcdefa8b6e239560bad3cfe5af9f036308a5 Mon Sep 17 00:00:00 2001 From: Erik Hofmayer Date: Sun, 9 Apr 2023 12:31:13 +0200 Subject: [PATCH 238/267] Add renaming of ignore-git to changelog --- src/bootstrap/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index 654e03d0c3c7..fe6d450e3eb3 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - `remote-test-server`'s `remote` argument has been removed in favor of the `--bind` flag. Use `--bind 0.0.0.0:12345` to replicate the behavior of the `remote` argument. - `x.py fmt` now formats only files modified between the merge-base of HEAD and the last commit in the master branch of the rust-lang repository and the current working directory. To restore old behaviour, use `x.py fmt .`. The check mode is not affected by this change. [#105702](https://github.com/rust-lang/rust/pull/105702) - The `llvm.version-check` config option has been removed. Older versions were never supported. If you still need to support older versions (e.g. you are applying custom patches), patch `check_llvm_version` in bootstrap to change the minimum version. [#108619](https://github.com/rust-lang/rust/pull/108619) +- The `rust.ignore-git` option has been renamed to `rust.omit-git-hash`. ### Non-breaking changes From 3fcc007f96c625c3a6d326030fca5d5fb7f8abf2 Mon Sep 17 00:00:00 2001 From: Erik Hofmayer Date: Sun, 9 Apr 2023 12:36:15 +0200 Subject: [PATCH 239/267] Add PR link to changelog entry for renaming of ignore-git --- src/bootstrap/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index fe6d450e3eb3..74dd22df9e06 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -17,7 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - `remote-test-server`'s `remote` argument has been removed in favor of the `--bind` flag. Use `--bind 0.0.0.0:12345` to replicate the behavior of the `remote` argument. - `x.py fmt` now formats only files modified between the merge-base of HEAD and the last commit in the master branch of the rust-lang repository and the current working directory. To restore old behaviour, use `x.py fmt .`. The check mode is not affected by this change. [#105702](https://github.com/rust-lang/rust/pull/105702) - The `llvm.version-check` config option has been removed. Older versions were never supported. If you still need to support older versions (e.g. you are applying custom patches), patch `check_llvm_version` in bootstrap to change the minimum version. [#108619](https://github.com/rust-lang/rust/pull/108619) -- The `rust.ignore-git` option has been renamed to `rust.omit-git-hash`. +- The `rust.ignore-git` option has been renamed to `rust.omit-git-hash`. [#110059](https://github.com/rust-lang/rust/pull/110059) ### Non-breaking changes From 28e19f19aaa9388814fb0cc358e18258127397f3 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Wed, 5 Apr 2023 23:36:40 +0200 Subject: [PATCH 240/267] Add little `is_test_crate` function --- compiler/rustc_session/src/session.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 5730df9d5c6b..340bb158e179 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -294,6 +294,11 @@ impl Session { self.crate_types.get().unwrap().as_slice() } + /// Returns true if the crate is a testing one. + pub fn is_test_crate(&self) -> bool { + self.opts.test + } + pub fn needs_crate_hash(&self) -> bool { // Why is the crate hash needed for these configurations? // - debug_assertions: for the "fingerprint the result" check in From 7ca7c8fbf322171af8247509256c833b862f4618 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 9 Apr 2023 12:36:30 -0500 Subject: [PATCH 241/267] compiletest: Give a better error message if `node` isn't installed --- src/tools/compiletest/src/runtest.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a35284f05b54..1a4b2bdb4e18 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2135,7 +2135,7 @@ impl<'test> TestCx<'test> { if let Some(ref p) = self.config.nodejs { args.push(p.clone()); } else { - self.fatal("no NodeJS binary found (--nodejs)"); + self.fatal("emscripten target requested and no NodeJS binary found (--nodejs)"); } // If this is otherwise wasm, then run tests under nodejs with our // shim @@ -2143,7 +2143,7 @@ impl<'test> TestCx<'test> { if let Some(ref p) = self.config.nodejs { args.push(p.clone()); } else { - self.fatal("no NodeJS binary found (--nodejs)"); + self.fatal("wasm32 target requested and no NodeJS binary found (--nodejs)"); } let src = self From 464a24e68d62acfb7b1084cbf6a331b8b3cde6cb Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 9 Apr 2023 12:38:03 -0500 Subject: [PATCH 242/267] compiletest: Use remap-path-prefix only in CI This makes jump-to-definition work in most IDEs, as well as being easier to understand for contributors. --- src/tools/compiletest/src/header.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 735351fbf605..a7efe16150ea 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -6,6 +6,7 @@ use std::io::BufReader; use std::path::{Path, PathBuf}; use std::process::Command; +use build_helper::ci::CiEnv; use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; @@ -276,8 +277,12 @@ impl TestProps { /// `//[foo]`), then the property is ignored unless `cfg` is /// `Some("foo")`. fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) { - // Mode-dependent defaults. - self.remap_src_base = config.mode == Mode::Ui && !config.suite.contains("rustdoc"); + // In CI, we've sometimes encountered non-determinism related to truncating very long paths. + // Set a consistent (short) prefix to avoid issues, but only in CI to avoid regressing the + // contributor experience. + if CiEnv::is_ci() { + self.remap_src_base = config.mode == Mode::Ui && !config.suite.contains("rustdoc"); + } let mut has_edition = false; if !testfile.is_dir() { From d757c4b904869967f1e665dc2bb9a2ca5122bc96 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 6 Apr 2023 16:24:32 -0700 Subject: [PATCH 243/267] Handle not all immediates having `abi::Scalar`s --- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 54 ++++++++++++++---- tests/codegen/intrinsics/transmute-x64.rs | 35 ++++++++++++ tests/codegen/intrinsics/transmute.rs | 58 +++++++++++++++++++- 3 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 tests/codegen/intrinsics/transmute-x64.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 6e4c0be12f08..d88226f5db05 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -223,13 +223,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let OperandValueKind::Immediate(in_scalar) = operand_kind else { bug!("Found {operand_kind:?} for operand {operand:?}"); }; - if let OperandValueKind::Immediate(out_scalar) = cast_kind - && in_scalar.size(self.cx) == out_scalar.size(self.cx) - { - let cast_bty = bx.backend_type(cast); - Some(OperandValue::Immediate( - self.transmute_immediate(bx, imm, in_scalar, out_scalar, cast_bty), - )) + if let OperandValueKind::Immediate(out_scalar) = cast_kind { + match (in_scalar, out_scalar) { + (ScalarOrZst::Zst, ScalarOrZst::Zst) => { + Some(OperandRef::new_zst(bx, cast).val) + } + (ScalarOrZst::Scalar(in_scalar), ScalarOrZst::Scalar(out_scalar)) + if in_scalar.size(self.cx) == out_scalar.size(self.cx) => + { + let cast_bty = bx.backend_type(cast); + Some(OperandValue::Immediate( + self.transmute_immediate(bx, imm, in_scalar, out_scalar, cast_bty), + )) + } + _ => None, + } } else { None } @@ -892,13 +900,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if self.cx.is_backend_immediate(layout) { debug_assert!(!self.cx.is_backend_scalar_pair(layout)); OperandValueKind::Immediate(match layout.abi { - abi::Abi::Scalar(s) => s, - abi::Abi::Vector { element, .. } => element, - x => bug!("Couldn't translate {x:?} as backend immediate"), + abi::Abi::Scalar(s) => ScalarOrZst::Scalar(s), + abi::Abi::Vector { element, .. } => ScalarOrZst::Scalar(element), + _ if layout.is_zst() => ScalarOrZst::Zst, + x => span_bug!(self.mir.span, "Couldn't translate {x:?} as backend immediate"), }) } else if self.cx.is_backend_scalar_pair(layout) { let abi::Abi::ScalarPair(s1, s2) = layout.abi else { - bug!("Couldn't translate {:?} as backend scalar pair", layout.abi) + span_bug!( + self.mir.span, + "Couldn't translate {:?} as backend scalar pair", + layout.abi, + ); }; OperandValueKind::Pair(s1, s2) } else { @@ -907,9 +920,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } +/// The variants of this match [`OperandValue`], giving details about the +/// backend values that will be held in that other type. #[derive(Debug, Copy, Clone)] enum OperandValueKind { Ref, - Immediate(abi::Scalar), + Immediate(ScalarOrZst), Pair(abi::Scalar, abi::Scalar), } + +#[derive(Debug, Copy, Clone)] +enum ScalarOrZst { + Zst, + Scalar(abi::Scalar), +} + +impl ScalarOrZst { + pub fn size(self, cx: &impl abi::HasDataLayout) -> abi::Size { + match self { + ScalarOrZst::Zst => abi::Size::ZERO, + ScalarOrZst::Scalar(s) => s.size(cx), + } + } +} diff --git a/tests/codegen/intrinsics/transmute-x64.rs b/tests/codegen/intrinsics/transmute-x64.rs new file mode 100644 index 000000000000..99d258c62040 --- /dev/null +++ b/tests/codegen/intrinsics/transmute-x64.rs @@ -0,0 +1,35 @@ +// compile-flags: -O -C no-prepopulate-passes +// only-x86_64 (it's using arch-specific types) +// min-llvm-version: 15.0 # this test assumes `ptr`s + +#![crate_type = "lib"] + +use std::arch::x86_64::{__m128, __m128i, __m256i}; +use std::mem::transmute; + +// CHECK-LABEL: @check_sse_float_to_int( +#[no_mangle] +pub unsafe fn check_sse_float_to_int(x: __m128) -> __m128i { + // CHECK-NOT: alloca + // CHECK: %1 = load <4 x float>, ptr %x, align 16 + // CHECK: store <4 x float> %1, ptr %0, align 16 + transmute(x) +} + +// CHECK-LABEL: @check_sse_pair_to_avx( +#[no_mangle] +pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i { + // CHECK-NOT: alloca + // CHECK: %1 = load <4 x i64>, ptr %x, align 16 + // CHECK: store <4 x i64> %1, ptr %0, align 32 + transmute(x) +} + +// CHECK-LABEL: @check_sse_pair_from_avx( +#[no_mangle] +pub unsafe fn check_sse_pair_from_avx(x: __m256i) -> (__m128i, __m128i) { + // CHECK-NOT: alloca + // CHECK: %1 = load <4 x i64>, ptr %x, align 32 + // CHECK: store <4 x i64> %1, ptr %0, align 16 + transmute(x) +} diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index c2295ca9a0c3..57f901c67199 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -8,7 +8,7 @@ #![feature(inline_const)] #![allow(unreachable_code)] -use std::mem::transmute; +use std::mem::{transmute, MaybeUninit}; // Some of the cases here are statically rejected by `mem::transmute`, so // we need to generate custom MIR for those cases to get to codegen. @@ -373,3 +373,59 @@ pub unsafe fn check_pair_to_dst_ref<'a>(x: (usize, usize)) -> &'a [u8] { // CHECK: ret { ptr, i64 } %2 transmute(x) } + +// CHECK-LABEL: @check_issue_109992( +#[no_mangle] +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub unsafe fn check_issue_109992(x: ()) -> [(); 1] { + // This uses custom MIR to avoid MIR optimizations having removed ZST ops. + + // CHECK: start + // CHECK-NEXT: ret void + mir!{ + { + RET = CastTransmute(x); + Return() + } + } +} + +// CHECK-LABEL: @check_maybe_uninit_pair(i16 %x.0, i64 %x.1) +#[no_mangle] +pub unsafe fn check_maybe_uninit_pair( + x: (MaybeUninit, MaybeUninit), +) -> (MaybeUninit, MaybeUninit) { + // Thanks to `MaybeUninit` this is actually defined behaviour, + // unlike the examples above with pairs of primitives. + + // CHECK: store i16 %x.0 + // CHECK: store i64 %x.1 + // CHECK: load i64 + // CHECK-NOT: noundef + // CHECK: load i16 + // CHECK-NOT: noundef + // CHECK: ret { i64, i16 } + transmute(x) +} + +#[repr(align(8))] +pub struct HighAlignScalar(u8); + +// CHECK-LABEL: @check_to_overalign( +#[no_mangle] +pub unsafe fn check_to_overalign(x: u64) -> HighAlignScalar { + // CHECK: %0 = alloca %HighAlignScalar, align 8 + // CHECK: store i64 %x, ptr %0, align 8 + // CHECK: %1 = load i64, ptr %0, align 8 + // CHECK: ret i64 %1 + transmute(x) +} + +// CHECK-LABEL: @check_from_overalign( +#[no_mangle] +pub unsafe fn check_from_overalign(x: HighAlignScalar) -> u64 { + // CHECK: %x = alloca %HighAlignScalar, align 8 + // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 8 + // CHECK: ret i64 %[[VAL]] + transmute(x) +} From 2b43f25e428ca1065206f424d7b953e2cc606c2e Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 9 Apr 2023 14:27:45 -0500 Subject: [PATCH 244/267] Fix `x check --stage 1` when download-rustc is enabled --- src/bootstrap/check.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index cd19667139ab..f9387a0fc80b 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -271,9 +271,17 @@ impl Step for Rustc { false, ); - let libdir = builder.sysroot_libdir(compiler, target); - let hostdir = builder.sysroot_libdir(compiler, compiler.host); - add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target)); + // HACK: This avoids putting the newly built artifacts in the sysroot if we're using + // `download-rustc`, to avoid "multiple candidates for `rmeta`" errors. Technically, that's + // not quite right: people can set `download-rustc = true` to download even if there are + // changes to the compiler, and in that case ideally we would put the *new* artifacts in the + // sysroot, in case there are API changes that should be used by tools. In practice, + // though, that should be very uncommon, and people can still disable download-rustc. + if !builder.download_rustc() { + let libdir = builder.sysroot_libdir(compiler, target); + let hostdir = builder.sysroot_libdir(compiler, compiler.host); + add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target)); + } } } From 2c976765b8e426506285b334e0a1506c78b135e2 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Sun, 9 Apr 2023 21:37:31 +0200 Subject: [PATCH 245/267] Migrate `sess.opts.tests` uses to `sess.is_test_crate()` --- compiler/rustc_builtin_macros/src/test_harness.rs | 2 +- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- compiler/rustc_interface/src/passes.rs | 4 ++-- compiler/rustc_passes/src/stability.rs | 2 +- compiler/rustc_resolve/src/check_unused.rs | 2 +- compiler/rustc_session/src/config.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 43ab6c044283..80f497333a63 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -53,7 +53,7 @@ pub fn inject(krate: &mut ast::Crate, sess: &Session, resolver: &mut dyn Resolve // even in non-test builds let test_runner = get_test_runner(span_diagnostic, &krate); - if sess.opts.test { + if sess.is_test_crate() { let panic_strategy = match (panic_strategy, sess.opts.unstable_opts.panic_abort_tests) { (PanicStrategy::Abort, true) => PanicStrategy::Abort, (PanicStrategy::Abort, false) => { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 6a0d0ca55c25..7a5fa5a370cb 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2301,7 +2301,7 @@ fn add_native_libs_from_crate( || (whole_archive == None && bundle && cnum == LOCAL_CRATE - && sess.opts.test); + && sess.is_test_crate()); if bundle && cnum != LOCAL_CRATE { if let Some(filename) = lib.filename { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 8d4892470ac7..0e4e20c7cd1d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -230,7 +230,7 @@ fn configure_and_expand( features: Some(features), recursion_limit, trace_mac: sess.opts.unstable_opts.trace_macros, - should_test: sess.opts.test, + should_test: sess.is_test_crate(), span_debug: sess.opts.unstable_opts.span_debug, proc_macro_backtrace: sess.opts.unstable_opts.proc_macro_backtrace, ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) @@ -292,7 +292,7 @@ fn configure_and_expand( } sess.time("maybe_create_a_macro_crate", || { - let is_test_crate = sess.opts.test; + let is_test_crate = sess.is_test_crate(); rustc_builtin_macros::proc_macro_harness::inject( &mut krate, sess, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 4a1ba19c9206..4a35c6794663 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -530,7 +530,7 @@ struct MissingStabilityAnnotations<'tcx> { impl<'tcx> MissingStabilityAnnotations<'tcx> { fn check_missing_stability(&self, def_id: LocalDefId, span: Span) { let stab = self.tcx.stability().local_stability(def_id); - if !self.tcx.sess.opts.test + if !self.tcx.sess.is_test_crate() && stab.is_none() && self.effective_visibilities.is_reachable(def_id) { diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index dbf6cec788b5..ae3fd0ede6cf 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -393,7 +393,7 @@ impl Resolver<'_, '_> { // If we are in the `--test` mode, suppress a help that adds the `#[cfg(test)]` // attribute; however, if not, suggest adding the attribute. There is no way to // retrieve attributes here because we do not have a `TyCtxt` yet. - let test_module_span = if tcx.sess.opts.test { + let test_module_span = if tcx.sess.is_test_crate() { None } else { let parent_module = visitor.r.get_nearest_non_block_module( diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index de0ddb53fa40..613abaa8e3cd 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1258,7 +1258,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo // some default and generated configuration items. let default_cfg = default_configuration(sess); // If the user wants a test runner, then add the test cfg. - if sess.opts.test { + if sess.is_test_crate() { user_cfg.insert((sym::test, None)); } user_cfg.extend(default_cfg.iter().cloned()); From f058d05fc20a19c46a8253eec15faa2636ea1135 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 21:52:46 +0200 Subject: [PATCH 246/267] Some simple `clippy::perf` fixes --- compiler/rustc_data_structures/src/profiling.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs | 3 +-- compiler/rustc_macros/src/diagnostics/fluent.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_transmute/src/lib.rs | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 58a0609e2965..92924111a000 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -778,7 +778,7 @@ pub fn print_time_passes_entry( "rss_start": start_rss, "rss_end": end_rss, }); - eprintln!("time: {}", json.to_string()); + eprintln!("time: {}", json); return; } TimePassesFormat::Text => (), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 7534e432f119..3e0c2bf2a553 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -242,8 +242,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(arg) = segment .args() .args - .iter() - .nth(index) else { return false; }; + .get(index) else { return false; }; error.obligation.cause.span = arg .span() .find_ancestor_in_same_ctxt(error.obligation.cause.span) diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs index 9f96a0414879..493ec5a99447 100644 --- a/compiler/rustc_macros/src/diagnostics/fluent.rs +++ b/compiler/rustc_macros/src/diagnostics/fluent.rs @@ -100,7 +100,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok Diagnostic::spanned( resource_span, Level::Error, - format!("could not open Fluent resource: {}", e.to_string()), + format!("could not open Fluent resource: {}", e), ) .emit(); return failed(&crate_name); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index b3f66c4ba335..e1cae6caf2fb 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1224,7 +1224,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lifetime_ribs: Vec::new(), lifetime_elision_candidates: None, current_trait_ref: None, - diagnostic_metadata: Box::new(DiagnosticMetadata::default()), + diagnostic_metadata: Box::>::default(), // errors at module scope should always be reported in_func_body: false, lifetime_uses: Default::default(), diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 4b4a8ebd079f..a93a42987ed5 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -149,7 +149,7 @@ mod rustc { .iter() .enumerate() .find(|(_, field_def)| name == field_def.name) - .expect(&format!("There were no fields named `{name}`.")); + .unwrap_or_else(|| panic!("There were no fields named `{name}`.")); fields[field_idx].unwrap_leaf() == ScalarInt::TRUE }; From 54e1309c65ec10bb40adf832d2dee3e043dddb9c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 21:53:03 +0200 Subject: [PATCH 247/267] Use HashMap entry APIs more --- .../src/generator_interior/drop_ranges/cfg_build.rs | 5 +++-- compiler/rustc_lint/src/levels.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs index 1eeb7d984ee0..3e9a9ce1b311 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs @@ -526,8 +526,9 @@ impl DropRangesBuilder { let mut next = <_>::from(0u32); for value in tracked_values { for_each_consumable(hir, value, |value| { - if !tracked_value_map.contains_key(&value) { - tracked_value_map.insert(value, next); + if let std::collections::hash_map::Entry::Vacant(e) = tracked_value_map.entry(value) + { + e.insert(next); next = next + 1; } }); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index a76229dd3524..a2a7c93a7ca9 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -266,12 +266,12 @@ impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> { let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id else { bug!("unstable expectation id should already be mapped") }; let key = LintExpectationId::Unstable { attr_id, lint_index: None }; - if !self.unstable_to_stable_ids.contains_key(&key) { - self.unstable_to_stable_ids.insert( - key, - LintExpectationId::Stable { hir_id, attr_index, lint_index: None, attr_id: None }, - ); - } + self.unstable_to_stable_ids.entry(key).or_insert(LintExpectationId::Stable { + hir_id, + attr_index, + lint_index: None, + attr_id: None, + }); self.expectations.push((id.normalize(), expectation)); } From f00366d191cabfbc5a61df07c724cca25a8ec10d Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 21:53:40 +0200 Subject: [PATCH 248/267] Box large enum variants --- compiler/rustc_metadata/src/locator.rs | 6 +++--- compiler/rustc_span/src/lib.rs | 4 ++-- compiler/rustc_span/src/source_map.rs | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 2515269ea2ff..c6af8d632898 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -762,14 +762,14 @@ impl<'a> CrateLocator<'a> { } pub(crate) fn into_error(self, root: Option) -> CrateError { - CrateError::LocatorCombined(CombinedLocatorError { + CrateError::LocatorCombined(Box::new(CombinedLocatorError { crate_name: self.crate_name, root, triple: self.triple, dll_prefix: self.target.dll_prefix.to_string(), dll_suffix: self.target.dll_suffix.to_string(), crate_rejections: self.crate_rejections, - }) + })) } } @@ -958,7 +958,7 @@ pub(crate) enum CrateError { StableCrateIdCollision(Symbol, Symbol), DlOpen(String), DlSym(String), - LocatorCombined(CombinedLocatorError), + LocatorCombined(Box), NonDylibPlugin(Symbol), } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 11cd5811be8b..b0cd999e627e 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2051,13 +2051,13 @@ pub type FileLinesResult = Result; #[derive(Clone, PartialEq, Eq, Debug)] pub enum SpanLinesError { - DistinctSources(DistinctSources), + DistinctSources(Box), } #[derive(Clone, PartialEq, Eq, Debug)] pub enum SpanSnippetError { IllFormedSpan(Span), - DistinctSources(DistinctSources), + DistinctSources(Box), MalformedForSourcemap(MalformedSourceMapPositions), SourceNotAvailable { filename: FileName }, } diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index ee895f53eba9..88e3674f8994 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -542,10 +542,10 @@ impl SourceMap { let hi = self.lookup_char_pos(sp.hi()); trace!(?hi); if lo.file.start_pos != hi.file.start_pos { - return Err(SpanLinesError::DistinctSources(DistinctSources { + return Err(SpanLinesError::DistinctSources(Box::new(DistinctSources { begin: (lo.file.name.clone(), lo.file.start_pos), end: (hi.file.name.clone(), hi.file.start_pos), - })); + }))); } Ok((lo, hi)) } @@ -603,10 +603,10 @@ impl SourceMap { let local_end = self.lookup_byte_offset(sp.hi()); if local_begin.sf.start_pos != local_end.sf.start_pos { - Err(SpanSnippetError::DistinctSources(DistinctSources { + Err(SpanSnippetError::DistinctSources(Box::new(DistinctSources { begin: (local_begin.sf.name.clone(), local_begin.sf.start_pos), end: (local_end.sf.name.clone(), local_end.sf.start_pos), - })) + }))) } else { self.ensure_source_file_source_present(local_begin.sf.clone()); From 968be9875664ba794f27e4a5bfa3b97f09f0582d Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 22:29:56 +0200 Subject: [PATCH 249/267] Allow `clippy::from_mut_ref` This pattern is fine for arena allocators. --- compiler/rustc_arena/src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 4fae5ef845f7..345e058e1134 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -22,6 +22,7 @@ #![feature(strict_provenance)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] +#![allow(clippy::mut_from_ref)] // Arena allocators are one of the places where this pattern is fine. use smallvec::SmallVec; @@ -568,7 +569,9 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { } pub trait ArenaAllocatable<'tcx, C = rustc_arena::IsNotCopy>: Sized { + #[allow(clippy::mut_from_ref)] fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self; + #[allow(clippy::mut_from_ref)] fn allocate_from_iter<'a>( arena: &'a Arena<'tcx>, iter: impl ::std::iter::IntoIterator, @@ -578,10 +581,12 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { // Any type that impls `Copy` can be arena-allocated in the `DroplessArena`. impl<'tcx, T: Copy> ArenaAllocatable<'tcx, rustc_arena::IsCopy> for T { #[inline] + #[allow(clippy::mut_from_ref)] fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self { arena.dropless.alloc(self) } #[inline] + #[allow(clippy::mut_from_ref)] fn allocate_from_iter<'a>( arena: &'a Arena<'tcx>, iter: impl ::std::iter::IntoIterator, @@ -601,6 +606,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { } #[inline] + #[allow(clippy::mut_from_ref)] fn allocate_from_iter<'a>( arena: &'a Arena<'tcx>, iter: impl ::std::iter::IntoIterator, @@ -616,12 +622,14 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { impl<'tcx> Arena<'tcx> { #[inline] + #[allow(clippy::mut_from_ref)] pub fn alloc, C>(&self, value: T) -> &mut T { value.allocate_on(self) } // Any type that impls `Copy` can have slices be arena-allocated in the `DroplessArena`. #[inline] + #[allow(clippy::mut_from_ref)] pub fn alloc_slice(&self, value: &[T]) -> &mut [T] { if value.is_empty() { return &mut []; @@ -629,6 +637,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { self.dropless.alloc_slice(value) } + #[allow(clippy::mut_from_ref)] pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, C>, C>( &'a self, iter: impl ::std::iter::IntoIterator, From 0a0968b207776f5f29d42aaece7872c7d1aec892 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 22:30:24 +0200 Subject: [PATCH 250/267] Allow `modulo_one` on function using cfg consts --- compiler/rustc_data_structures/src/sharded.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index f88c055a9b56..bd7a86f67800 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -140,6 +140,7 @@ pub fn make_hash(val: &K) -> u64 { /// `hash` can be computed with any hasher, so long as that hasher is used /// consistently for each `Sharded` instance. #[inline] +#[allow(clippy::modulo_one)] pub fn get_shard_index_by_hash(hash: u64) -> usize { let hash_len = mem::size_of::(); // Ignore the top 7 bits as hashbrown uses these and get the next SHARD_BITS highest bits. From 07cd3826e08953cd4be2ba7be5c223294f6f3586 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 22:31:48 +0200 Subject: [PATCH 251/267] Small clippy::correctness fixes Nothing was really incorrect before, but it did get nicer. --- .../src/coherence/inherent_impls_overlap.rs | 2 +- compiler/rustc_hir_typeck/src/generator_interior/mod.rs | 3 +-- compiler/rustc_hir_typeck/src/method/probe.rs | 5 ++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 7bca4edcc8c9..ad76e2bed202 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -302,7 +302,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { .iter() .flatten() .map(|r| r.impl_blocks.len() as isize - avg as isize) - .map(|v| v.abs() as usize) + .map(|v| v.unsigned_abs()) .sum::(); s / connected_regions.len() }, diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 84ed8f3780e1..5faa6ab13dd7 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -313,8 +313,7 @@ pub fn resolve_interior<'a, 'tcx>( // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list_from_iter(type_causes.iter().map(|cause| cause.ty)); let bound_vars = fcx.tcx.mk_bound_variable_kinds(&bound_vars); - let witness = - fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone())); + let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars)); drop(typeck_results); // Store the generator types and spans into the typeck results for this generator. diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 0092bd2c6e64..8388d0f94c8a 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1755,7 +1755,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn probe_for_similar_candidate(&mut self) -> Result, MethodError<'tcx>> { debug!("probing for method names similar to {:?}", self.method_name); - let steps = self.steps.clone(); self.probe(|_| { let mut pcx = ProbeContext::new( self.fcx, @@ -1763,8 +1762,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.mode, self.method_name, self.return_type, - &self.orig_steps_var_values, - steps, + self.orig_steps_var_values, + self.steps, self.scope_expr_id, ); pcx.allow_similar_names = true; From 1c75724752077e53ddcb7fd19a55a929a5a8feae Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 22:35:00 +0200 Subject: [PATCH 252/267] Properly compare previously shadowed values The shadowing lead to an incorrect comparison. Rename it and compare it properly. compiler-errors told me that I should just include the fix here without a test. --- compiler/rustc_hir_typeck/src/_match.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 035ccf30b246..6c2ce62722a5 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -538,8 +538,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(rpitit): This will need to be fixed when we move to associated types assert!(matches!( *trait_pred.trait_ref.self_ty().kind(), - ty::Alias(_, ty::AliasTy { def_id, substs, .. }) - if def_id == rpit_def_id && substs == substs + ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. }) + if def_id == rpit_def_id && substs == alias_substs )); ty::PredicateKind::Clause(ty::Clause::Trait( trait_pred.with_self_ty(self.tcx, ty), @@ -548,8 +548,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => { assert!(matches!( *proj_pred.projection_ty.self_ty().kind(), - ty::Alias(_, ty::AliasTy { def_id, substs, .. }) - if def_id == rpit_def_id && substs == substs + ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. }) + if def_id == rpit_def_id && substs == alias_substs )); proj_pred = proj_pred.with_self_ty(self.tcx, ty); ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred)) From 5a90de8f5e08e736c24348eab1caa62cd57790b0 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 22:35:49 +0200 Subject: [PATCH 253/267] Delete useless loop --- compiler/rustc_middle/src/hir/map/mod.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 89a485b47ca8..9d97a75a2fa6 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -74,18 +74,17 @@ impl<'hir> Iterator for ParentHirIterator<'hir> { if self.current_id == CRATE_HIR_ID { return None; } - loop { - // There are nodes that do not have entries, so we need to skip them. - let parent_id = self.map.parent_id(self.current_id); - if parent_id == self.current_id { - self.current_id = CRATE_HIR_ID; - return None; - } + // There are nodes that do not have entries, so we need to skip them. + let parent_id = self.map.parent_id(self.current_id); - self.current_id = parent_id; - return Some(parent_id); + if parent_id == self.current_id { + self.current_id = CRATE_HIR_ID; + return None; } + + self.current_id = parent_id; + return Some(parent_id); } } From 6fceb0f6456d4bf526634ef8a3759c0c98ffaa79 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 22:38:48 +0200 Subject: [PATCH 254/267] Improve `Allocation::hash Exhaustively destructure and ignore `()` --- .../src/mir/interpret/allocation.rs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 2f2c7b154165..7b18255f57a8 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -109,26 +109,34 @@ const MAX_HASHED_BUFFER_LEN: usize = 2 * MAX_BYTES_TO_HASH; // large. impl hash::Hash for Allocation { fn hash(&self, state: &mut H) { + let Self { + bytes, + provenance, + init_mask, + align, + mutability, + extra: _, // don't bother hashing () + } = self; + // Partially hash the `bytes` buffer when it is large. To limit collisions with common // prefixes and suffixes, we hash the length and some slices of the buffer. - let byte_count = self.bytes.len(); + let byte_count = bytes.len(); if byte_count > MAX_HASHED_BUFFER_LEN { // Hash the buffer's length. byte_count.hash(state); // And its head and tail. - self.bytes[..MAX_BYTES_TO_HASH].hash(state); - self.bytes[byte_count - MAX_BYTES_TO_HASH..].hash(state); + bytes[..MAX_BYTES_TO_HASH].hash(state); + bytes[byte_count - MAX_BYTES_TO_HASH..].hash(state); } else { - self.bytes.hash(state); + bytes.hash(state); } // Hash the other fields as usual. - self.provenance.hash(state); - self.init_mask.hash(state); - self.align.hash(state); - self.mutability.hash(state); - self.extra.hash(state); + provenance.hash(state); + init_mask.hash(state); + align.hash(state); + mutability.hash(state); } } From 81c320ea7786a2b5a07a165aedacb438ae14fd74 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 23:07:18 +0200 Subject: [PATCH 255/267] Fix some clippy::complexity --- compiler/rustc_abi/src/lib.rs | 2 +- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_ast_passes/src/feature_gate.rs | 7 +++++-- compiler/rustc_ast_pretty/src/pprust/state.rs | 4 +++- .../src/graph/implementation/mod.rs | 10 ++-------- compiler/rustc_data_structures/src/memmap.rs | 2 +- .../src/stable_hasher.rs | 4 ++-- compiler/rustc_data_structures/src/stack.rs | 2 +- .../rustc_data_structures/src/sync/vec.rs | 2 +- compiler/rustc_data_structures/src/unord.rs | 4 ++-- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_errors/src/emitter.rs | 10 +++++----- compiler/rustc_expand/src/config.rs | 2 +- compiler/rustc_expand/src/mbe/metavar_expr.rs | 2 +- compiler/rustc_hir/src/lang_items.rs | 2 +- compiler/rustc_index/src/bit_set.rs | 2 +- compiler/rustc_index/src/vec.rs | 11 ++++------- .../src/diagnostics/diagnostic_builder.rs | 4 ++-- compiler/rustc_middle/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 2 +- compiler/rustc_middle/src/traits/solve.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 4 ++-- .../rustc_parse/src/lexer/unicode_chars.rs | 4 ++-- compiler/rustc_parse/src/parser/generics.rs | 2 +- .../rustc_query_system/src/query/caches.rs | 4 +++- compiler/rustc_session/src/config.rs | 2 +- compiler/rustc_session/src/parse.rs | 19 ++++++++++--------- compiler/rustc_span/src/lib.rs | 10 +++++----- 28 files changed, 62 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 76765c8a0aa3..b0c0ee942ea8 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1176,7 +1176,7 @@ impl FieldsShape { /// Gets source indices of the fields by increasing offsets. #[inline] - pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator + 'a { + pub fn index_by_increasing_offset(&self) -> impl Iterator + '_ { let mut inverse_small = [0u8; 64]; let mut inverse_big = IndexVec::new(); let use_small = self.count() <= inverse_small.len(); diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 236ebd04ae88..1389acabfcbd 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -691,7 +691,7 @@ fn validate_generic_param_order( GenericParamKind::Lifetime => (), GenericParamKind::Const { ty: _, kw_span: _, default: Some(default) } => { ordered_params += " = "; - ordered_params += &pprust::expr_to_string(&*default.value); + ordered_params += &pprust::expr_to_string(&default.value); } GenericParamKind::Const { ty: _, kw_span: _, default: None } => (), } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index b3923b651eb3..007d64f681f7 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -404,11 +404,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } else { // And if it isn't, cancel the early-pass warning. - self.sess + if let Some(err) = self + .sess .parse_sess .span_diagnostic .steal_diagnostic(e.span, StashKey::EarlySyntaxWarning) - .map(|err| err.cancel()); + { + err.cancel() + } } } ast::ExprKind::TryBlock(_) => { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 80c451d67535..9b3b1d7a8e30 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -988,7 +988,9 @@ impl<'a> State<'a> { pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocConstraint) { self.print_ident(constraint.ident); - constraint.gen_args.as_ref().map(|args| self.print_generic_args(args, false)); + if let Some(args) = constraint.gen_args.as_ref() { + self.print_generic_args(args, false) + } self.space(); match &constraint.kind { ast::AssocConstraintKind::Equality { term } => { diff --git a/compiler/rustc_data_structures/src/graph/implementation/mod.rs b/compiler/rustc_data_structures/src/graph/implementation/mod.rs index 1aa7ac024d94..9ff401c3c7aa 100644 --- a/compiler/rustc_data_structures/src/graph/implementation/mod.rs +++ b/compiler/rustc_data_structures/src/graph/implementation/mod.rs @@ -206,17 +206,11 @@ impl Graph { AdjacentEdges { graph: self, direction, next: first_edge } } - pub fn successor_nodes<'a>( - &'a self, - source: NodeIndex, - ) -> impl Iterator + 'a { + pub fn successor_nodes(&self, source: NodeIndex) -> impl Iterator + '_ { self.outgoing_edges(source).targets() } - pub fn predecessor_nodes<'a>( - &'a self, - target: NodeIndex, - ) -> impl Iterator + 'a { + pub fn predecessor_nodes(&self, target: NodeIndex) -> impl Iterator + '_ { self.incoming_edges(target).sources() } diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs index 1556873f5976..ef37a606f313 100644 --- a/compiler/rustc_data_structures/src/memmap.rs +++ b/compiler/rustc_data_structures/src/memmap.rs @@ -40,7 +40,7 @@ impl Deref for Mmap { impl AsRef<[u8]> for Mmap { fn as_ref(&self) -> &[u8] { - &*self.0 + &self.0 } } diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index de9842156d61..3ed1de1bc3ca 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -312,14 +312,14 @@ impl HashStable for ::std::num::NonZeroUsize { impl HashStable for f32 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let val: u32 = unsafe { ::std::mem::transmute(*self) }; + let val: u32 = self.to_bits(); val.hash_stable(ctx, hasher); } } impl HashStable for f64 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let val: u64 = unsafe { ::std::mem::transmute(*self) }; + let val: u64 = self.to_bits(); val.hash_stable(ctx, hasher); } } diff --git a/compiler/rustc_data_structures/src/stack.rs b/compiler/rustc_data_structures/src/stack.rs index 3bdd67512321..7ff1339c5ab3 100644 --- a/compiler/rustc_data_structures/src/stack.rs +++ b/compiler/rustc_data_structures/src/stack.rs @@ -5,7 +5,7 @@ const RED_ZONE: usize = 100 * 1024; // 100k // Only the first stack that is pushed, grows exponentially (2^n * STACK_PER_RECURSION) from then // on. This flag has performance relevant characteristics. Don't set it too high. -const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB +const STACK_PER_RECURSION: usize = 1024 * 1024; // 1MB /// Grows the stack on demand to prevent stack overflow. Call this in strategic locations /// to "break up" recursive calls. E.g. almost any call to `visit_expr` or equivalent can benefit diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs index aefaa8519d53..1783b4b35725 100644 --- a/compiler/rustc_data_structures/src/sync/vec.rs +++ b/compiler/rustc_data_structures/src/sync/vec.rs @@ -84,7 +84,7 @@ impl AppendOnlyVec { } pub fn iter(&self) -> impl Iterator + '_ { - (0..).map(|i| self.get(i)).take_while(|o| o.is_some()).filter_map(|o| o) + (0..).map(|i| self.get(i)).take_while(|o| o.is_some()).flatten() } } diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index 5c2435a0122e..6c8d54146315 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -224,7 +224,7 @@ impl UnordSet { } #[inline] - pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator> { + pub fn items(&self) -> UnordItems<&V, impl Iterator> { UnordItems(self.inner.iter()) } @@ -415,7 +415,7 @@ impl UnordMap { } #[inline] - pub fn items<'a>(&'a self) -> UnordItems<(&'a K, &'a V), impl Iterator> { + pub fn items(&self) -> UnordItems<(&K, &V), impl Iterator> { UnordItems(self.inner.iter()) } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 9ed8ab67431c..e09ef34b93db 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -956,7 +956,7 @@ impl Diagnostic { // Exact iteration order of diagnostic arguments shouldn't make a difference to output because // they're only used in interpolation. #[allow(rustc::potential_query_instability)] - pub fn args<'a>(&'a self) -> impl Iterator> { + pub fn args(&self) -> impl Iterator> { self.args.iter() } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 4b1ff0e1df94..81e8bcbf7cd5 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1407,7 +1407,7 @@ impl EmitterWriter { // Account for newlines to align output to its label. for (line, text) in normalize_whitespace(&text).lines().enumerate() { buffer.append( - 0 + line, + line, &format!( "{}{}", if line == 0 { String::new() } else { " ".repeat(label_width) }, @@ -1918,7 +1918,7 @@ impl EmitterWriter { let last_line = unhighlighted_lines.pop(); let first_line = unhighlighted_lines.drain(..).next(); - first_line.map(|(p, l)| { + if let Some((p, l)) = first_line { self.draw_code_line( &mut buffer, &mut row_num, @@ -1930,12 +1930,12 @@ impl EmitterWriter { &file_lines, is_multiline, ) - }); + } buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); row_num += 1; - last_line.map(|(p, l)| { + if let Some((p, l)) = last_line { self.draw_code_line( &mut buffer, &mut row_num, @@ -1947,7 +1947,7 @@ impl EmitterWriter { &file_lines, is_multiline, ) - }); + } } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index a78dc0678d5d..4ff8e409d88e 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -466,7 +466,7 @@ impl<'a> StripUnconfigured<'a> { // // N.B., this is intentionally not part of the visit_expr() function // in order for filter_map_expr() to be able to avoid this check - if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) { + if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) { self.sess.emit_err(RemoveExprNotSupported { span: attr.span }); } diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index de34df0114a7..fb3a00d86d4f 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -41,7 +41,7 @@ impl MetaVarExpr { }; check_trailing_token(&mut tts, sess)?; let mut iter = args.trees(); - let rslt = match &*ident.as_str() { + let rslt = match ident.as_str() { "count" => parse_count(&mut iter, sess, ident.span)?, "ignore" => MetaVarExpr::Ignore(parse_ident(&mut iter, sess, ident.span)?), "index" => MetaVarExpr::Index(parse_depth(&mut iter, sess, ident.span)?), diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index eac8fd294293..8f91a96f964a 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -49,7 +49,7 @@ impl LanguageItems { self.get(it).ok_or_else(|| LangItemError(it)) } - pub fn iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn iter(&self) -> impl Iterator + '_ { self.items .iter() .enumerate() diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index eba5b3ed882a..271ab830694b 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -1850,7 +1850,7 @@ impl SparseBitMatrix { /// Iterates through all the columns set to true in a given row of /// the matrix. - pub fn iter<'a>(&'a self, row: R) -> impl Iterator + 'a { + pub fn iter(&self, row: R) -> impl Iterator + '_ { self.row(row).into_iter().flat_map(|r| r.iter()) } diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 009602382dd0..ae2f52c513e9 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -201,18 +201,15 @@ impl IndexVec { } #[inline] - pub fn drain<'a, R: RangeBounds>( - &'a mut self, - range: R, - ) -> impl Iterator + 'a { + pub fn drain>(&mut self, range: R) -> impl Iterator + '_ { self.raw.drain(range) } #[inline] - pub fn drain_enumerated<'a, R: RangeBounds>( - &'a mut self, + pub fn drain_enumerated>( + &mut self, range: R, - ) -> impl Iterator + 'a { + ) -> impl Iterator + '_ { let begin = match range.start_bound() { std::ops::Bound::Included(i) => *i, std::ops::Bound::Excluded(i) => i.checked_add(1).unwrap(), diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 9b91627883a8..4540ded0f41a 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -119,7 +119,7 @@ impl DiagnosticDeriveBuilder { impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Generates calls to `code` and similar functions based on the attributes on the type or /// variant. - pub fn preamble<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream { + pub fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let ast = variant.ast(); let attrs = &ast.attrs; let preamble = attrs.iter().map(|attr| { @@ -133,7 +133,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Generates calls to `span_label` and similar functions based on the attributes on fields or /// calls to `set_arg` when no attributes are present. - pub fn body<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream { + pub fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let mut body = quote! {}; // Generate `set_arg` calls first.. for binding in variant.bindings().iter().filter(|bi| should_generate_set_arg(bi.ast())) { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 0fad30973db7..56755e588cb4 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -915,7 +915,7 @@ pub enum LocalInfo<'tcx> { impl<'tcx> LocalDecl<'tcx> { pub fn local_info(&self) -> &LocalInfo<'tcx> { - &**self.local_info.as_ref().assert_crate_local() + &self.local_info.as_ref().assert_crate_local() } /// Returns `true` only if local is a binding that can itself be diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 833402abfc47..6a8ae525069c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -923,7 +923,7 @@ impl ObjectSafetyViolation { } } ObjectSafetyViolation::SupertraitNonLifetimeBinder(_) => { - format!("where clause cannot reference non-lifetime `for<...>` variables").into() + "where clause cannot reference non-lifetime `for<...>` variables".into() } ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => { format!("associated function `{}` has no `self` parameter", name).into() diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 0d6f9813e767..9c350fb5a137 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -105,7 +105,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { type Target = ExternalConstraintsData<'tcx>; fn deref(&self) -> &Self::Target { - &*self.0 + &self.0 } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2ef6180c4cbd..c312aaf6819a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -924,7 +924,7 @@ impl<'tcx> TyCtxt<'tcx> { crate_name, // Don't print the whole stable crate id. That's just // annoying in debug output. - stable_crate_id.to_u64() >> 8 * 6, + stable_crate_id.to_u64() >> (8 * 6), self.def_path(def_id).to_string_no_crate_verbose() ) } @@ -2379,7 +2379,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> { let map = self.in_scope_traits_map(id.owner)?; let candidates = map.get(&id.local_id)?; - Some(&*candidates) + Some(candidates) } pub fn named_bound_var(self, id: HirId) -> Option { diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index d4f971d5bc84..1f027c08fc3b 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -336,8 +336,8 @@ const ASCII_ARRAY: &[(&str, &str, Option)] = &[ ("\"", "Quotation Mark", None), ]; -pub(super) fn check_for_substitution<'a>( - reader: &StringReader<'a>, +pub(super) fn check_for_substitution( + reader: &StringReader<'_>, pos: BytePos, ch: char, count: usize, diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 8d0f168e09d7..f8ef1307c988 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -53,7 +53,7 @@ impl<'a> Parser<'a> { let snapshot = self.create_snapshot_for_diagnostic(); match self.parse_ty() { Ok(p) => { - if let TyKind::ImplTrait(_, bounds) = &(*p).kind { + if let TyKind::ImplTrait(_, bounds) = &p.kind { let span = impl_span.to(self.token.span.shrink_to_lo()); let mut err = self.struct_span_err( span, diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 3ac8a852a4e7..29f6a07e81be 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -136,7 +136,9 @@ where } fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) { - self.cache.lock().as_ref().map(|value| f(&(), &value.0, value.1)); + if let Some(value) = self.cache.lock().as_ref() { + f(&(), &value.0, value.1) + } } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index de0ddb53fa40..d4eba495dcdc 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1426,7 +1426,7 @@ pub fn rustc_short_optgroups() -> Vec { opt::opt_s( "", "edition", - &*EDITION_STRING, + &EDITION_STRING, EDITION_NAME_LIST, ), opt::multi_s( diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 002ae1e3165a..15e27952cf50 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -84,12 +84,12 @@ impl SymbolGallery { /// Construct a diagnostic for a language feature error due to the given `span`. /// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`. -pub fn feature_err<'a>( - sess: &'a ParseSess, +pub fn feature_err( + sess: &ParseSess, feature: Symbol, span: impl Into, explain: impl Into, -) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +) -> DiagnosticBuilder<'_, ErrorGuaranteed> { feature_err_issue(sess, feature, span, GateIssue::Language, explain) } @@ -98,20 +98,21 @@ pub fn feature_err<'a>( /// This variant allows you to control whether it is a library or language feature. /// Almost always, you want to use this for a language feature. If so, prefer `feature_err`. #[track_caller] -pub fn feature_err_issue<'a>( - sess: &'a ParseSess, +pub fn feature_err_issue( + sess: &ParseSess, feature: Symbol, span: impl Into, issue: GateIssue, explain: impl Into, -) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let span = span.into(); // Cancel an earlier warning for this same error, if it exists. if let Some(span) = span.primary_span() { - sess.span_diagnostic - .steal_diagnostic(span, StashKey::EarlySyntaxWarning) - .map(|err| err.cancel()); + if let Some(err) = sess.span_diagnostic.steal_diagnostic(span, StashKey::EarlySyntaxWarning) + { + err.cancel() + } } let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() }); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index b0cd999e627e..aa8859ed1a35 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1353,16 +1353,16 @@ impl Clone for SourceFile { Self { name: self.name.clone(), src: self.src.clone(), - src_hash: self.src_hash.clone(), + src_hash: self.src_hash, external_src: Lock::new(self.external_src.borrow().clone()), - start_pos: self.start_pos.clone(), - end_pos: self.end_pos.clone(), + start_pos: self.start_pos, + end_pos: self.end_pos, lines: Lock::new(self.lines.borrow().clone()), multibyte_chars: self.multibyte_chars.clone(), non_narrow_chars: self.non_narrow_chars.clone(), normalized_pos: self.normalized_pos.clone(), - name_hash: self.name_hash.clone(), - cnum: self.cnum.clone(), + name_hash: self.name_hash, + cnum: self.cnum, } } } From 4b4948c2e34e6b320f0091b97bf3044db467f4d3 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 23:07:45 +0200 Subject: [PATCH 256/267] Remove identity casts --- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_llvm/src/lib.rs | 2 +- compiler/rustc_middle/src/mir/patch.rs | 6 +++--- compiler/rustc_middle/src/mir/tcx.rs | 2 +- compiler/rustc_middle/src/ty/consts/int.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_parse/src/lexer/mod.rs | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 9b3b1d7a8e30..1f6838a02784 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -686,7 +686,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere fn bclose_maybe_open(&mut self, span: rustc_span::Span, empty: bool, close_box: bool) { let has_comment = self.maybe_print_comment(span.hi()); if !empty || has_comment { - self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); + self.break_offset_if_not_bol(1, -INDENT_UNIT); } self.word("}"); if close_box { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 4f27c01fad2c..74f5b359021d 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -242,7 +242,7 @@ pub fn enum_def_to_string( impl<'a> State<'a> { pub fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) { self.maybe_print_comment(span.hi()); - self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); + self.break_offset_if_not_bol(1, -INDENT_UNIT); self.word("}"); if close_box { self.end(); // close the outer-box diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 8542dcf5bf0f..ec3cf34d7109 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -30,7 +30,7 @@ pub unsafe extern "C" fn LLVMRustStringWriteImpl( ptr: *const c_char, size: size_t, ) { - let slice = slice::from_raw_parts(ptr as *const u8, size as usize); + let slice = slice::from_raw_parts(ptr as *const u8, size); sr.bytes.borrow_mut().extend_from_slice(slice); } diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index b898e85fa71b..f62853c3e740 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -133,21 +133,21 @@ impl<'tcx> MirPatch<'tcx> { let mut new_decl = LocalDecl::new(ty, span).internal(); **new_decl.local_info.as_mut().assert_crate_local() = local_info; self.new_locals.push(new_decl); - Local::new(index as usize) + Local::new(index) } pub fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local { let index = self.next_local; self.next_local += 1; self.new_locals.push(LocalDecl::new(ty, span)); - Local::new(index as usize) + Local::new(index) } pub fn new_internal(&mut self, ty: Ty<'tcx>, span: Span) -> Local { let index = self.next_local; self.next_local += 1; self.new_locals.push(LocalDecl::new(ty, span).internal()); - Local::new(index as usize) + Local::new(index) } pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock { diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 0092401470f5..4f00abf7fabc 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -98,7 +98,7 @@ impl<'tcx> PlaceTy<'tcx> { ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64), ty::Array(inner, size) if from_end => { let size = size.eval_target_usize(tcx, param_env); - let len = size - (from as u64) - (to as u64); + let len = size - from - to; tcx.mk_array(*inner, len) } _ => bug!("cannot subslice non-array type: `{:?}`", self), diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index a7f38884ebcc..c0e557d480d3 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -337,7 +337,7 @@ impl ScalarInt { /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 16 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i128(self) -> Result { - self.try_to_int(Size::from_bits(128)).map(|v| i128::try_from(v).unwrap()) + self.try_to_int(Size::from_bits(128)) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 0e2e2a956ec7..5bbd396d6f3b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1891,7 +1891,7 @@ impl<'tcx> Ty<'tcx> { // The way we evaluate the `N` in `[T; N]` here only works since we use // `simd_size_and_type` post-monomorphization. It will probably start to ICE // if we use it in generic code. See the `simd-array-trait` ui test. - (f0_len.eval_target_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty) + (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty) } // Otherwise, the fields of this Adt are the SIMD components (and we assume they // all have the same type). diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 4a7da11a0978..e41d0f7047b3 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -558,8 +558,8 @@ impl<'a> StringReader<'a> { } if let Some(possible_offset) = possible_offset { - let lo = start + BytePos(possible_offset as u32); - let hi = lo + BytePos(found_terminators as u32); + let lo = start + BytePos(possible_offset); + let hi = lo + BytePos(found_terminators); let span = self.mk_sp(lo, hi); err.span_suggestion( span, From e5defd010262989a01573193b0456fd31e3cb63c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 23:08:01 +0200 Subject: [PATCH 257/267] Convert manual loop into `while let` --- compiler/rustc_middle/src/mir/traversal.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 62cdf794b1e9..7d247eeb656c 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -178,17 +178,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { // When we yield `B` and call `traverse_successor`, we push `C` to the stack, but // since we've already visited `E`, that child isn't added to the stack. The last // two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A] - loop { - let bb = if let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() { - if let Some(bb) = iter.next() { - bb - } else { - break; - } - } else { - break; - }; - + while let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() && let Some(bb) = iter.next() { if self.visited.insert(bb) { if let Some(term) = &self.basic_blocks[bb].terminator { self.visit_stack.push((bb, term.successors())); From 5853c28a7f5c497f25d679d32522a110ae6cac28 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 23:08:39 +0200 Subject: [PATCH 258/267] Simply Abi::fmt --- compiler/rustc_target/src/spec/abi.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index d4f7ed31b895..5582d909f6b1 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -324,8 +324,6 @@ impl Abi { impl fmt::Display for Abi { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - abi => write!(f, "\"{}\"", abi.name()), - } + write!(f, "\"{}\"", self.name()) } } From cab94d29ffc4929a181cbfdb744f87deab467cc1 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 23:23:33 +0200 Subject: [PATCH 259/267] fixup! Improve `Allocation::hash --- compiler/rustc_middle/src/mir/interpret/allocation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 7b18255f57a8..1a8e48264471 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -115,7 +115,7 @@ impl hash::Hash for Allocation { init_mask, align, mutability, - extra: _, // don't bother hashing () + extra: (), // don't bother hashing () } = self; // Partially hash the `bytes` buffer when it is large. To limit collisions with common From 73417b1e1503ad6a3eeae93cd12ecdc727f002c0 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 23:29:39 +0200 Subject: [PATCH 260/267] Inline format_args Co-authored-by: Michael Goulet --- compiler/rustc_data_structures/src/profiling.rs | 2 +- compiler/rustc_macros/src/diagnostics/fluent.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 92924111a000..1ed584eafad3 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -778,7 +778,7 @@ pub fn print_time_passes_entry( "rss_start": start_rss, "rss_end": end_rss, }); - eprintln!("time: {}", json); + eprintln!("time: {json}"); return; } TimePassesFormat::Text => (), diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs index 493ec5a99447..607d51f5608d 100644 --- a/compiler/rustc_macros/src/diagnostics/fluent.rs +++ b/compiler/rustc_macros/src/diagnostics/fluent.rs @@ -100,7 +100,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok Diagnostic::spanned( resource_span, Level::Error, - format!("could not open Fluent resource: {}", e), + format!("could not open Fluent resource: {e}"), ) .emit(); return failed(&crate_name); From 9fc1555f74f96fd1f77d5188fe438abd1c6f72d9 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 9 Apr 2023 23:31:25 +0200 Subject: [PATCH 261/267] Remove turbofish --- compiler/rustc_resolve/src/late.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e1cae6caf2fb..31ac3f1c151e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1224,7 +1224,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lifetime_ribs: Vec::new(), lifetime_elision_candidates: None, current_trait_ref: None, - diagnostic_metadata: Box::>::default(), + diagnostic_metadata: Default::default(), // errors at module scope should always be reported in_func_body: false, lifetime_uses: Default::default(), From 2b0f5721c190ebb9b738713d578f3780eac46ee6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 29 Mar 2023 15:36:17 +0200 Subject: [PATCH 262/267] prioritize param-env candidates --- compiler/rustc_middle/src/infer/canonical.rs | 12 +++ .../src/solve/assembly.rs | 72 ++++++-------- .../rustc_trait_selection/src/solve/mod.rs | 93 ++++++++++++------- ..._eq_dont_use_normalizes_to_if_substs_eq.rs | 2 +- .../prefer-candidate-no-constraints.rs | 22 +++++ .../prefer-param-env-on-ambiguity.rs | 10 ++ .../recursive-self-normalization-2.stderr | 13 ++- .../recursive-self-normalization.stderr | 13 ++- 8 files changed, 150 insertions(+), 87 deletions(-) create mode 100644 tests/ui/traits/new-solver/prefer-candidate-no-constraints.rs create mode 100644 tests/ui/traits/new-solver/prefer-param-env-on-ambiguity.rs diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index f668c4e77bea..b5b712c367d0 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -80,6 +80,18 @@ impl CanonicalVarValues<'_> { } }) } + + pub fn is_identity_modulo_regions(&self) -> bool { + self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() { + ty::GenericArgKind::Lifetime(_) => true, + ty::GenericArgKind::Type(ty) => { + matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv) + } + ty::GenericArgKind::Const(ct) => { + matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv) + } + }) + } } /// When we canonicalize a value to form a query, we wind up replacing diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 6476da7ba489..7c9a69f03987 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -4,8 +4,8 @@ use super::search_graph::OverflowHandler; #[cfg(doc)] use super::trait_goals::structural_traits::*; use super::{EvalCtxt, SolverMode}; +use crate::solve::CanonicalResponseExt; use crate::traits::coherence; -use itertools::Itertools; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; @@ -547,61 +547,41 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + /// If there are multiple ways to prove a trait or projection goal, we have + /// to somehow try to merge the candidates into one. If that fails, we return + /// ambiguity. #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_candidates( &mut self, mut candidates: Vec>, ) -> QueryResult<'tcx> { - match candidates.len() { - 0 => return Err(NoSolution), - 1 => return Ok(candidates.pop().unwrap().result), - _ => {} + // First try merging all candidates. This is complete and fully sound. + let responses = candidates.iter().map(|c| c.result).collect::>(); + if let Some(result) = self.try_merge_responses(&responses) { + return Ok(result); } - if candidates.len() > 1 { - let mut i = 0; - 'outer: while i < candidates.len() { - for j in (0..candidates.len()).filter(|&j| i != j) { - if self.candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j]) - { - debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len()); - candidates.swap_remove(i); - continue 'outer; + // We then check whether we should prioritize `ParamEnv` candidates. + // + // Doing so is incomplete and would therefore be unsound during coherence. + match self.solver_mode() { + SolverMode::Coherence => (), + // Prioritize `ParamEnv` candidates only if they do not guide inference. + // + // This is still incomplete as we may add incorrect region bounds. + SolverMode::Normal => { + let param_env_responses = candidates + .iter() + .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_))) + .map(|c| c.result) + .collect::>(); + if let Some(result) = self.try_merge_responses(¶m_env_responses) { + if result.has_only_region_constraints() { + return Ok(result); } } - - debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len()); - i += 1; - } - - // If there are *STILL* multiple candidates that have *different* response - // results, give up and report ambiguity. - if candidates.len() > 1 && !candidates.iter().map(|cand| cand.result).all_equal() { - let certainty = if candidates.iter().all(|x| { - matches!(x.result.value.certainty, Certainty::Maybe(MaybeCause::Overflow)) - }) { - Certainty::Maybe(MaybeCause::Overflow) - } else { - Certainty::AMBIGUOUS - }; - return self.evaluate_added_goals_and_make_canonical_response(certainty); } } - - Ok(candidates.pop().unwrap().result) - } - - fn candidate_should_be_dropped_in_favor_of( - &self, - candidate: &Candidate<'tcx>, - other: &Candidate<'tcx>, - ) -> bool { - // FIXME: implement this - match (candidate.source, other.source) { - (CandidateSource::Impl(_), _) - | (CandidateSource::ParamEnv(_), _) - | (CandidateSource::AliasBound, _) - | (CandidateSource::BuiltinImpl, _) => false, - } + self.flounder(&responses) } } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 9ddae8f8dcd4..2ee91a2da385 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -46,6 +46,8 @@ enum SolverMode { trait CanonicalResponseExt { fn has_no_inference_or_external_constraints(&self) -> bool; + + fn has_only_region_constraints(&self) -> bool; } impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> { @@ -54,6 +56,11 @@ impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> { && self.value.var_values.is_identity() && self.value.external_constraints.opaque_types.is_empty() } + + fn has_only_region_constraints(&self) -> bool { + self.value.var_values.is_identity_modulo_regions() + && self.value.external_constraints.opaque_types.is_empty() + } } impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { @@ -221,12 +228,17 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { (Some(alias_lhs), Some(alias_rhs)) => { debug!("both sides are aliases"); - let candidates = vec![ - // LHS normalizes-to RHS - evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No), - // RHS normalizes-to RHS - evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes), - // Relate via substs + let mut candidates = Vec::new(); + // LHS normalizes-to RHS + candidates.extend( + evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No).ok(), + ); + // RHS normalizes-to RHS + candidates.extend( + evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes).ok(), + ); + // Relate via substs + candidates.extend( self.probe(|ecx| { let span = tracing::span!( tracing::Level::DEBUG, @@ -247,11 +259,16 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }), - ]; + }) + .ok(), + ); debug!(?candidates); - self.try_merge_responses(candidates.into_iter()) + if let Some(merged) = self.try_merge_responses(&candidates) { + Ok(merged) + } else { + self.flounder(&candidates) + } } } } @@ -289,43 +306,51 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { debug!("added_goals={:?}", &self.nested_goals.goals[current_len..]); } - #[instrument(level = "debug", skip(self, responses))] + /// Try to merge multiple possible ways to prove a goal, if that is not possible returns `None`. + /// + /// In this case we tend to flounder and return ambiguity by calling `[EvalCtxt::flounder]`. + #[instrument(level = "debug", skip(self), ret)] fn try_merge_responses( &mut self, - responses: impl Iterator>, - ) -> QueryResult<'tcx> { - let candidates = responses.into_iter().flatten().collect::>(); - - if candidates.is_empty() { - return Err(NoSolution); + responses: &[CanonicalResponse<'tcx>], + ) -> Option> { + if responses.is_empty() { + return None; } // FIXME(-Ztrait-solver=next): We should instead try to find a `Certainty::Yes` response with // a subset of the constraints that all the other responses have. - let one = candidates[0]; - if candidates[1..].iter().all(|resp| resp == &one) { - return Ok(one); + let one = responses[0]; + if responses[1..].iter().all(|&resp| resp == one) { + return Some(one); } - if let Some(response) = candidates.iter().find(|response| { - response.value.certainty == Certainty::Yes - && response.has_no_inference_or_external_constraints() - }) { - return Ok(*response); - } + responses + .iter() + .find(|response| { + response.value.certainty == Certainty::Yes + && response.has_no_inference_or_external_constraints() + }) + .copied() + } - let certainty = candidates.iter().fold(Certainty::AMBIGUOUS, |certainty, response| { + /// If we fail to merge responses we flounder and return overflow or ambiguity. + #[instrument(level = "debug", skip(self), ret)] + fn flounder(&mut self, responses: &[CanonicalResponse<'tcx>]) -> QueryResult<'tcx> { + if responses.is_empty() { + return Err(NoSolution); + } + let certainty = responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| { certainty.unify_and(response.value.certainty) }); - // FIXME(-Ztrait-solver=next): We should take the intersection of the constraints on all the - // responses and use that for the constraints of this ambiguous response. - debug!(">1 response, bailing with {certainty:?}"); - let response = self.evaluate_added_goals_and_make_canonical_response(certainty); - if let Ok(response) = &response { - assert!(response.has_no_inference_or_external_constraints()); - } - response + let response = self.evaluate_added_goals_and_make_canonical_response(certainty); + if let Ok(response) = response { + assert!(response.has_no_inference_or_external_constraints()); + Ok(response) + } else { + bug!("failed to make floundered response: {responses:?}"); + } } } diff --git a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs index fd5d0e3b1946..531203d9c64f 100644 --- a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs +++ b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs @@ -1,7 +1,7 @@ // compile-flags: -Ztrait-solver=next // check that when computing `alias-eq(<() as Foo>::Assoc, <() as Foo>::Assoc)` -// we do not infer `?0 = u8` via the `for (): Foo` impl or `?0 = u16` by +// we do not infer `?0 = u8` via the `for (): Foo` impl or `?0 = u16` by // relating substs as either could be a valid solution. trait Foo { diff --git a/tests/ui/traits/new-solver/prefer-candidate-no-constraints.rs b/tests/ui/traits/new-solver/prefer-candidate-no-constraints.rs new file mode 100644 index 000000000000..6f8164f3a40f --- /dev/null +++ b/tests/ui/traits/new-solver/prefer-candidate-no-constraints.rs @@ -0,0 +1,22 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Foo {} + +impl Foo for T {} + +trait Bar {} + +struct Wrapper<'a, T>(&'a T); + +impl<'a, T> Bar for Wrapper<'a, T> where &'a T: Foo {} +// We need to satisfy `&'a T: Foo` when checking that this impl is WF +// that can either be satisfied via the param-env, or via an impl. +// +// When satisfied via the param-env, since each lifetime is canonicalized +// separately, we end up getting extra region constraints. +// +// However, when satisfied via the impl, there are no region constraints, +// and we can short-circuit a response with no external constraints. + +fn main() {} diff --git a/tests/ui/traits/new-solver/prefer-param-env-on-ambiguity.rs b/tests/ui/traits/new-solver/prefer-param-env-on-ambiguity.rs new file mode 100644 index 000000000000..909b33ec3d5a --- /dev/null +++ b/tests/ui/traits/new-solver/prefer-param-env-on-ambiguity.rs @@ -0,0 +1,10 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Foo<'a> {} +trait Bar<'a> {} + +impl<'a, T: Bar<'a>> Foo<'a> for T {} +impl Bar<'static> for T {} + +fn main() {} diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr index 29cfa47a1050..e3a92e85e17e 100644 --- a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr @@ -1,9 +1,16 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `::Assoc1: Bar` --> $DIR/recursive-self-normalization-2.rs:15:5 | LL | needs_bar::(); - | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar` + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `::Assoc1: Bar` +note: required by a bound in `needs_bar` + --> $DIR/recursive-self-normalization-2.rs:12:17 + | +LL | fn needs_bar() {} + | ^^^ required by this bound in `needs_bar` error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.stderr b/tests/ui/traits/new-solver/recursive-self-normalization.stderr index ba39981893d4..773007aebaa6 100644 --- a/tests/ui/traits/new-solver/recursive-self-normalization.stderr +++ b/tests/ui/traits/new-solver/recursive-self-normalization.stderr @@ -1,9 +1,16 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `::Assoc: Bar` --> $DIR/recursive-self-normalization.rs:11:5 | LL | needs_bar::(); - | ^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar` + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `::Assoc: Bar` +note: required by a bound in `needs_bar` + --> $DIR/recursive-self-normalization.rs:8:17 + | +LL | fn needs_bar() {} + | ^^^ required by this bound in `needs_bar` error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. From 2186847f28b240b6f06515402789e3d8fc9205bd Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 29 Mar 2023 15:44:23 +0200 Subject: [PATCH 263/267] move `structural_traits` into `assembly` --- .../src/solve/{assembly.rs => assembly/mod.rs} | 4 ++-- .../solve/{trait_goals => assembly}/structural_traits.rs | 8 ++++---- compiler/rustc_trait_selection/src/solve/project_goals.rs | 3 +-- compiler/rustc_trait_selection/src/solve/trait_goals.rs | 5 ++--- 4 files changed, 9 insertions(+), 11 deletions(-) rename compiler/rustc_trait_selection/src/solve/{assembly.rs => assembly/mod.rs} (99%) rename compiler/rustc_trait_selection/src/solve/{trait_goals => assembly}/structural_traits.rs (98%) diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs similarity index 99% rename from compiler/rustc_trait_selection/src/solve/assembly.rs rename to compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 7c9a69f03987..12ee80b6722b 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -1,8 +1,6 @@ //! Code shared by trait and projection goals for candidate assembly. use super::search_graph::OverflowHandler; -#[cfg(doc)] -use super::trait_goals::structural_traits::*; use super::{EvalCtxt, SolverMode}; use crate::solve::CanonicalResponseExt; use crate::traits::coherence; @@ -16,6 +14,8 @@ use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; use std::fmt::Debug; +pub(super) mod structural_traits; + /// A candidate is a possible way to prove a goal. /// /// It consists of both the `source`, which describes how that goal would be proven, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs similarity index 98% rename from compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs rename to compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 9e851b788a54..2de556185e31 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -11,7 +11,7 @@ use crate::solve::EvalCtxt; // // For types with an "existential" binder, i.e. generator witnesses, we also // instantiate the binder with placeholders eagerly. -pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>( +pub(crate) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, ) -> Result>, NoSolution> { @@ -87,7 +87,7 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>( } } -fn replace_erased_lifetimes_with_bound_vars<'tcx>( +pub(crate) fn replace_erased_lifetimes_with_bound_vars<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, ) -> ty::Binder<'tcx, Ty<'tcx>> { @@ -108,7 +108,7 @@ fn replace_erased_lifetimes_with_bound_vars<'tcx>( ty::Binder::bind_with_vars(ty, bound_vars) } -pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>( +pub(crate) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, ) -> Result>, NoSolution> { @@ -158,7 +158,7 @@ pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>( } } -pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( +pub(crate) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, ) -> Result>, NoSolution> { diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index e0a69438dec0..2a47da81ec76 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -1,7 +1,6 @@ use crate::traits::specialization_graph; -use super::assembly; -use super::trait_goals::structural_traits; +use super::assembly::{self, structural_traits}; use super::EvalCtxt; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index a2203473ca97..81f89fd950c8 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -1,6 +1,7 @@ //! Dealing with trait goals, i.e. `T: Trait<'a, U>`. -use super::{assembly, EvalCtxt, SolverMode}; +use super::assembly::{self, structural_traits}; +use super::{EvalCtxt, SolverMode}; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; use rustc_infer::traits::query::NoSolution; @@ -11,8 +12,6 @@ use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; use rustc_span::DUMMY_SP; -pub mod structural_traits; - impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn self_ty(self) -> Ty<'tcx> { self.self_ty() From 3fab7f7c13390217bf55d864b6e1efc3d0ec1528 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 30 Mar 2023 11:49:06 +0200 Subject: [PATCH 264/267] review + some small stuff --- compiler/rustc_middle/src/traits/solve.rs | 16 +++++++++++++--- .../src/solve/assembly/structural_traits.rs | 18 ++++++++++++------ .../src/solve/eval_ctxt.rs | 4 ++-- .../src/solve/eval_ctxt/canonical.rs | 2 +- .../rustc_trait_selection/src/solve/mod.rs | 2 +- .../issue-95230.new.stderr | 18 ++++++++++++++++++ .../ui/higher-rank-trait-bounds/issue-95230.rs | 6 +++++- 7 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 0d6f9813e767..7602bea5a248 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -56,9 +56,19 @@ pub enum Certainty { impl Certainty { pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity); - /// When proving multiple goals using **AND**, e.g. nested obligations for an impl, - /// use this function to unify the certainty of these goals - pub fn unify_and(self, other: Certainty) -> Certainty { + /// Use this function to merge the certainty of multiple nested subgoals. + /// + /// Given an impl like `impl Baz for T {}`, we have 2 nested + /// subgoals whenever we use the impl as a candidate: `T: Foo` and `T: Bar`. + /// If evaluating `T: Foo` results in ambiguity and `T: Bar` results in + /// success, we merge these two responses. This results in ambiguity. + /// + /// If we unify ambiguity with overflow, we return overflow. This doesn't matter + /// inside of the solver as we distinguish ambiguity from overflow. It does + /// however matter for diagnostics. If `T: Foo` resulted in overflow and `T: Bar` + /// in ambiguity without changing the inference state, we still want to tell the + /// user that `T: Baz` results in overflow. + pub fn unify_with(self, other: Certainty) -> Certainty { match (self, other) { (Certainty::Yes, Certainty::Yes) => Certainty::Yes, (Certainty::Yes, Certainty::Maybe(_)) => other, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 2de556185e31..cbec39d82856 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -11,7 +11,7 @@ use crate::solve::EvalCtxt; // // For types with an "existential" binder, i.e. generator witnesses, we also // instantiate the binder with placeholders eagerly. -pub(crate) fn instantiate_constituent_tys_for_auto_trait<'tcx>( +pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, ) -> Result>, NoSolution> { @@ -87,7 +87,7 @@ pub(crate) fn instantiate_constituent_tys_for_auto_trait<'tcx>( } } -pub(crate) fn replace_erased_lifetimes_with_bound_vars<'tcx>( +pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, ) -> ty::Binder<'tcx, Ty<'tcx>> { @@ -108,7 +108,7 @@ pub(crate) fn replace_erased_lifetimes_with_bound_vars<'tcx>( ty::Binder::bind_with_vars(ty, bound_vars) } -pub(crate) fn instantiate_constituent_tys_for_sized_trait<'tcx>( +pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, ) -> Result>, NoSolution> { @@ -158,7 +158,7 @@ pub(crate) fn instantiate_constituent_tys_for_sized_trait<'tcx>( } } -pub(crate) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( +pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, ) -> Result>, NoSolution> { @@ -224,7 +224,7 @@ pub(crate) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( } // Returns a binder of the tupled inputs types and output type from a builtin callable type. -pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>( +pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>, goal_kind: ty::ClosureKind, @@ -337,7 +337,13 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>( /// additional step of eagerly folding the associated types in the where /// clauses of the impl. In this example, that means replacing /// `::Bar` with `Ty` in the first impl. -pub(crate) fn predicates_for_object_candidate<'tcx>( +/// +// FIXME: This is only necessary as `::Assoc: ItemBound` +// bounds in impls are trivially proven using the item bound candidates. +// This is unsound in general and once that is fixed, we don't need to +// normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9 +// for more details. +pub(in crate::solve) fn predicates_for_object_candidate<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, trait_ref: ty::TraitRef<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index cdbab5bd8d27..28aca76cceb6 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -357,7 +357,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { // deal with `has_changed` in the next iteration. new_goals.normalizes_to_hack_goal = Some(this.resolve_vars_if_possible(goal)); - has_changed = has_changed.map_err(|c| c.unify_and(certainty)); + has_changed = has_changed.map_err(|c| c.unify_with(certainty)); } } } @@ -378,7 +378,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { Certainty::Yes => {} Certainty::Maybe(_) => { new_goals.goals.push(goal); - has_changed = has_changed.map_err(|c| c.unify_and(certainty)); + has_changed = has_changed.map_err(|c| c.unify_with(certainty)); } } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 714b6dfb7176..861fa0a305ac 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -50,7 +50,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { certainty: Certainty, ) -> QueryResult<'tcx> { let goals_certainty = self.try_evaluate_added_goals()?; - let certainty = certainty.unify_and(goals_certainty); + let certainty = certainty.unify_with(goals_certainty); let external_constraints = self.compute_external_query_constraints()?; diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 2ee91a2da385..19bcbd461447 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -341,7 +341,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { return Err(NoSolution); } let certainty = responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| { - certainty.unify_and(response.value.certainty) + certainty.unify_with(response.value.certainty) }); let response = self.evaluate_added_goals_and_make_canonical_response(certainty); diff --git a/tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr b/tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr new file mode 100644 index 000000000000..bcb201bf0c37 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr @@ -0,0 +1,18 @@ +error[E0282]: type annotations needed + --> $DIR/issue-95230.rs:9:13 + | +LL | for<'a> &'a mut Self:; + | ^^^^^^^^^^^^ cannot infer type for mutable reference `&'a mut Bar` + | +note: required by a bound in `Bar` + --> $DIR/issue-95230.rs:9:13 + | +LL | pub struct Bar + | --- required by a bound in this struct +LL | where +LL | for<'a> &'a mut Self:; + | ^^^^^^^^^^^^ required by this bound in `Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/higher-rank-trait-bounds/issue-95230.rs b/tests/ui/higher-rank-trait-bounds/issue-95230.rs index 92c506eabb7f..769b6a925376 100644 --- a/tests/ui/higher-rank-trait-bounds/issue-95230.rs +++ b/tests/ui/higher-rank-trait-bounds/issue-95230.rs @@ -1,4 +1,8 @@ -// check-pass +// revisions: old new +//[new] compile-flags: -Ztrait-solver=next +//[old] check-pass +//[new] known-bug: #109764 + pub struct Bar where From 0bb6d66251dae171bac858874be87d714004cc16 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 10 Apr 2023 07:55:53 -0400 Subject: [PATCH 265/267] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 1bf1217c83b9..f1ed3be2edd3 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -bd991d9953625e9d51fc4fcb5e19aa9c3ea598a8 +d4be8efc6296bace5b1e165f1b34d3c6da76aa8e From 73702d5e39e812d2e9ad22221462c266c963dd43 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 10 Apr 2023 07:52:36 -0400 Subject: [PATCH 266/267] Turn off the alignment check pass, remove the panic test for it The panic test is now counted as an error test; we encounter a Terminate terminator, and emit an interpreter error, as opposed to just terminating due to a panic. So this test should have broken with https://github.com/rust-lang/rust/pull/102906 but wasn't because the Miri test suite is currently broken in rust-lang/rust: https://github.com/rust-lang/rust/issues/110102 --- src/tools/miri/src/lib.rs | 3 +++ src/tools/miri/tests/panic/alignment-assertion.rs | 9 --------- src/tools/miri/tests/panic/alignment-assertion.stderr | 2 -- 3 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 src/tools/miri/tests/panic/alignment-assertion.rs delete mode 100644 src/tools/miri/tests/panic/alignment-assertion.stderr diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 94be8bb9d3d3..5c8aba6d441f 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -124,10 +124,13 @@ pub use crate::tag_gc::{EvalContextExt as _, VisitTags}; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. +/// Also disable the MIR pass that inserts an alignment check on every pointer dereference. Miri +/// does that too, and with a better error message. pub const MIRI_DEFAULT_ARGS: &[&str] = &[ "--cfg=miri", "-Zalways-encode-mir", "-Zextra-const-ub-checks", "-Zmir-emit-retag", "-Zmir-opt-level=0", + "-Zmir-enable-passes=-CheckAlignment", ]; diff --git a/src/tools/miri/tests/panic/alignment-assertion.rs b/src/tools/miri/tests/panic/alignment-assertion.rs deleted file mode 100644 index 68aa19a88db0..000000000000 --- a/src/tools/miri/tests/panic/alignment-assertion.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@compile-flags: -Zmiri-disable-alignment-check -Cdebug-assertions=yes - -fn main() { - let mut x = [0u32; 2]; - let ptr: *mut u8 = x.as_mut_ptr().cast::(); - unsafe { - *(ptr.add(1).cast::()) = 42; - } -} diff --git a/src/tools/miri/tests/panic/alignment-assertion.stderr b/src/tools/miri/tests/panic/alignment-assertion.stderr deleted file mode 100644 index 26cf51b0cd2e..000000000000 --- a/src/tools/miri/tests/panic/alignment-assertion.stderr +++ /dev/null @@ -1,2 +0,0 @@ -thread 'main' panicked at 'misaligned pointer dereference: address must be a multiple of 0x4 but is $HEX', $DIR/alignment-assertion.rs:LL:CC -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From d50fee9fb2e66b4162fbf5496e5abb7d3f29129a Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 10 Apr 2023 07:57:55 -0400 Subject: [PATCH 267/267] rustup --- src/tools/miri/src/shims/panic.rs | 20 +++++++------------ .../tests/fail/terminate-terminator.stderr | 4 +++- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index 2cca2f3f3914..18ae01a19f91 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -157,7 +157,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &[catch_unwind.data.into(), payload.into()], None, // Directly return to caller of `try`. - StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: mir::UnwindAction::Continue }, + StackPopCleanup::Goto { + ret: Some(catch_unwind.ret), + unwind: mir::UnwindAction::Continue, + }, )?; // We pushed a new stack frame, the engine should not do any jumping now! @@ -211,10 +214,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Abi::Rust, &[index.into(), len.into()], None, - StackPopCleanup::Goto { - ret: None, - unwind, - }, + StackPopCleanup::Goto { ret: None, unwind }, )?; } MisalignedPointerDereference { required, found } => { @@ -235,19 +235,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Abi::Rust, &[required.into(), found.into()], None, - StackPopCleanup::Goto { - ret: None, - unwind, - }, + StackPopCleanup::Goto { ret: None, unwind }, )?; } _ => { // Forward everything else to `panic` lang item. - this.start_panic( - msg.description(), - unwind, - )?; + this.start_panic(msg.description(), unwind)?; } } Ok(()) diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr index 3befd83007bf..c046678f73f5 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.stderr +++ b/src/tools/miri/tests/fail/terminate-terminator.stderr @@ -1,3 +1,5 @@ +warning: You have explicitly enabled MIR optimizations, overriding Miri's default which is to completely disable them. Any optimizations may hide UB that Miri would otherwise detect, and it is not necessarily possible to predict what kind of UB will be missed. If you are enabling optimizations to make Miri run faster, we advise using cfg(miri) to shrink your workload instead. The performance benefit of enabling MIR optimizations is usually marginal at best. + thread 'main' panicked at 'explicit panic', $DIR/terminate-terminator.rs:LL:CC note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: abnormal termination: panic in a function that cannot unwind @@ -23,5 +25,5 @@ LL | panic_abort(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted

\ {title}\ §\