From 821b32bd406e9c29b2e9ca2a647d30021cff653d Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sun, 29 May 2022 14:35:00 -0400 Subject: [PATCH 01/38] Add `let_underscore_drop` lint. This lint checks for statements similar to `let _ = foo`, where `foo` is a type that implements `Drop`. These types of let statements cause the expression in them to be dropped immediately, instead of at the end of the scope. Such behavior can be surprizing, especially if you are relying on the value to be dropped at the end of the scope. Instead, the binding should be an underscore prefixed name (like `_unused`) or the value should explicitly be passed to `std::mem::drop()` if the value really should be dropped immediately. --- compiler/rustc_lint/src/let_underscore.rs | 66 +++++++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 5 ++ src/test/ui/let_underscore_drop.rs | 13 +++++ src/test/ui/let_underscore_drop.stderr | 12 +++++ 4 files changed, 96 insertions(+) create mode 100644 compiler/rustc_lint/src/let_underscore.rs create mode 100644 src/test/ui/let_underscore_drop.rs create mode 100644 src/test/ui/let_underscore_drop.stderr diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs new file mode 100644 index 0000000000000..44242173c008b --- /dev/null +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -0,0 +1,66 @@ +use crate::{LateContext, LateLintPass, LintContext}; +use rustc_hir as hir; + +declare_lint! { + /// The `let_underscore_drop` lint checks for statements which don't bind + /// an expression which has a non-trivial Drop implementation to anything, + /// causing the expression to be dropped immediately instead of at end of + /// scope. + /// + /// ### Example + /// ```rust + /// struct SomeStruct; + /// impl Drop for SomeStruct { + /// fn drop(&mut self) { + /// println!("Dropping SomeStruct"); + /// } + /// } + /// + /// fn main() { + /// // SomeStuct is dropped immediately instead of at end of scope, + /// // so "Dropping SomeStruct" is printed before "end of main". + /// // The order of prints would be reversed if SomeStruct was bound to + /// // a name (such as "_foo"). + /// let _ = SomeStruct; + /// println!("end of main"); + /// } + /// ``` + /// ### Explanation + /// + /// Statements which assign an expression to an underscore causes the + /// expression to immediately drop instead of extending the expression's + /// lifetime to the end of the scope. This is usually unintended, + /// especially for types like `MutexGuard`, which are typically used to + /// lock a mutex for the duration of an entire scope. + /// + /// If you want to extend the expression's lifetime to the end of the scope, + /// assign an underscore-prefixed name (such as `_foo`) to the expression. + /// If you do actually want to drop the expression immediately, then + /// calling `std::mem::drop` on the expression is clearer and helps convey + /// intent. + pub LET_UNDERSCORE_DROP, + Warn, + "non-binding let on a type that implements `Drop`" +} + +declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP]); + +impl<'tcx> LateLintPass<'tcx> for LetUnderscore { + fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) { + if !matches!(local.pat.kind, hir::PatKind::Wild) { + return; + } + if let Some(init) = local.init { + let init_ty = cx.typeck_results().expr_ty(init); + let needs_drop = init_ty.needs_drop(cx.tcx, cx.param_env); + if needs_drop { + cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| { + lint.build("non-binding let on a type that implements `Drop`") + .help("consider binding to an unused variable") + .help("consider explicitly droping with `std::mem::drop`") + .emit(); + }) + } + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 0a0f292fe7a4d..55396b36dbc2e 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -54,6 +54,7 @@ mod expect; pub mod hidden_unicode_codepoints; mod internal; mod late; +mod let_underscore; mod levels; mod methods; mod non_ascii_idents; @@ -85,6 +86,7 @@ use builtin::*; use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums; use hidden_unicode_codepoints::*; use internal::*; +use let_underscore::*; use methods::*; use non_ascii_idents::*; use non_fmt_panic::NonPanicFmt; @@ -199,6 +201,7 @@ macro_rules! late_lint_mod_passes { VariantSizeDifferences: VariantSizeDifferences, BoxPointers: BoxPointers, PathStatements: PathStatements, + LetUnderscore: LetUnderscore, // Depends on referenced function signatures in expressions UnusedResults: UnusedResults, NonUpperCaseGlobals: NonUpperCaseGlobals, @@ -314,6 +317,8 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { REDUNDANT_SEMICOLONS ); + add_lint_group!("let_underscore", LET_UNDERSCORE_DROP); + add_lint_group!( "rust_2018_idioms", BARE_TRAIT_OBJECTS, diff --git a/src/test/ui/let_underscore_drop.rs b/src/test/ui/let_underscore_drop.rs new file mode 100644 index 0000000000000..c1c5207d0fe87 --- /dev/null +++ b/src/test/ui/let_underscore_drop.rs @@ -0,0 +1,13 @@ +// run-pass + +struct NontrivialDrop; + +impl Drop for NontrivialDrop { + fn drop(&mut self) { + println!("Dropping!"); + } +} + +fn main() { + let _ = NontrivialDrop; //~WARNING non-binding let on a type that implements `Drop` +} diff --git a/src/test/ui/let_underscore_drop.stderr b/src/test/ui/let_underscore_drop.stderr new file mode 100644 index 0000000000000..40ed1abd8dc6f --- /dev/null +++ b/src/test/ui/let_underscore_drop.stderr @@ -0,0 +1,12 @@ +warning: non-binding let on a type that implements `Drop` + --> $DIR/let_underscore_drop.rs:12:5 + | +LL | let _ = NontrivialDrop; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(let_underscore_drop)]` on by default + = help: consider binding to an unused variable + = help: consider explicitly droping with `std::mem::drop` + +warning: 1 warning emitted + From ad7587fedcf29a6629e0218f0e180ddf8960461d Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Tue, 31 May 2022 14:05:04 -0400 Subject: [PATCH 02/38] Add `let_underscore_lock` lint. Similar to `let_underscore_drop`, this lint checks for statements similar to `let _ = foo`, where `foo` is a lock guard. These types of let statements are especially problematic because the lock gets released immediately, instead of at the end of the scope. This behavior is almost always the wrong thing. --- compiler/rustc_lint/src/let_underscore.rs | 72 ++++++++++++++++++++++- compiler/rustc_lint/src/lib.rs | 2 +- src/test/ui/let_underscore_lock.rs | 8 +++ src/test/ui/let_underscore_lock.stderr | 12 ++++ 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/let_underscore_lock.rs create mode 100644 src/test/ui/let_underscore_lock.stderr diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 44242173c008b..81906a24d9029 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -1,5 +1,7 @@ use crate::{LateContext, LateLintPass, LintContext}; use rustc_hir as hir; +use rustc_middle::ty::{self, subst::GenericArgKind}; +use rustc_span::Symbol; declare_lint! { /// The `let_underscore_drop` lint checks for statements which don't bind @@ -43,7 +45,53 @@ declare_lint! { "non-binding let on a type that implements `Drop`" } -declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP]); +declare_lint! { + /// The `let_underscore_lock` lint checks for statements which don't bind + /// a mutex to anything, causing the lock to be released immediately instead + /// of at end of scope, which is typically incorrect. + /// + /// ### Example + /// ```rust + /// use std::sync::{Arc, Mutex}; + /// use std::thread; + /// let data = Arc::new(Mutex::new(0)); + /// + /// thread::spawn(move || { + /// // The lock is immediately released instead of at the end of the + /// // scope, which is probably not intended. + /// let _ = data.lock().unwrap(); + /// println!("doing some work"); + /// let mut lock = data.lock().unwrap(); + /// *lock += 1; + /// }); + /// ``` + /// ### Explanation + /// + /// Statements which assign an expression to an underscore causes the + /// expression to immediately drop instead of extending the expression's + /// lifetime to the end of the scope. This is usually unintended, + /// especially for types like `MutexGuard`, which are typically used to + /// lock a mutex for the duration of an entire scope. + /// + /// If you want to extend the expression's lifetime to the end of the scope, + /// assign an underscore-prefixed name (such as `_foo`) to the expression. + /// If you do actually want to drop the expression immediately, then + /// calling `std::mem::drop` on the expression is clearer and helps convey + /// intent. + pub LET_UNDERSCORE_LOCK, + Warn, + "non-binding let on a synchronization lock" +} + +declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK]); + +const SYNC_GUARD_PATHS: [&[&str]; 5] = [ + &["std", "sync", "mutex", "MutexGuard"], + &["std", "sync", "rwlock", "RwLockReadGuard"], + &["std", "sync", "rwlock", "RwLockWriteGuard"], + &["parking_lot", "raw_mutex", "RawMutex"], + &["parking_lot", "raw_rwlock", "RawRwLock"], +]; impl<'tcx> LateLintPass<'tcx> for LetUnderscore { fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) { @@ -53,7 +101,27 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { if let Some(init) = local.init { let init_ty = cx.typeck_results().expr_ty(init); let needs_drop = init_ty.needs_drop(cx.tcx, cx.param_env); - if needs_drop { + let is_sync_lock = init_ty.walk().any(|inner| match inner.unpack() { + GenericArgKind::Type(inner_ty) => { + SYNC_GUARD_PATHS.iter().any(|guard_path| match inner_ty.kind() { + ty::Adt(adt, _) => { + let ty_path = cx.get_def_path(adt.did()); + guard_path.iter().map(|x| Symbol::intern(x)).eq(ty_path.iter().copied()) + } + _ => false, + }) + } + + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, + }); + if is_sync_lock { + cx.struct_span_lint(LET_UNDERSCORE_LOCK, local.span, |lint| { + lint.build("non-binding let on a synchronization lock") + .help("consider binding to an unused variable") + .help("consider explicitly droping with `std::mem::drop`") + .emit(); + }) + } else if needs_drop { cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| { lint.build("non-binding let on a type that implements `Drop`") .help("consider binding to an unused variable") diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 55396b36dbc2e..79661c0fefe8d 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -317,7 +317,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { REDUNDANT_SEMICOLONS ); - add_lint_group!("let_underscore", LET_UNDERSCORE_DROP); + add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK); add_lint_group!( "rust_2018_idioms", diff --git a/src/test/ui/let_underscore_lock.rs b/src/test/ui/let_underscore_lock.rs new file mode 100644 index 0000000000000..774b610db2fb8 --- /dev/null +++ b/src/test/ui/let_underscore_lock.rs @@ -0,0 +1,8 @@ +// run-pass + +use std::sync::{Arc, Mutex}; + +fn main() { + let data = Arc::new(Mutex::new(0)); + let _ = data.lock().unwrap(); //~WARNING non-binding let on a synchronization lock +} diff --git a/src/test/ui/let_underscore_lock.stderr b/src/test/ui/let_underscore_lock.stderr new file mode 100644 index 0000000000000..77379d8c3db2c --- /dev/null +++ b/src/test/ui/let_underscore_lock.stderr @@ -0,0 +1,12 @@ +warning: non-binding let on a synchronization lock + --> $DIR/let_underscore_lock.rs:7:5 + | +LL | let _ = data.lock().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(let_underscore_lock)]` on by default + = help: consider binding to an unused variable + = help: consider explicitly droping with `std::mem::drop` + +warning: 1 warning emitted + From 758a9fd0f9ac191f0ea99215e07816631f402b7e Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Thu, 2 Jun 2022 14:58:44 -0400 Subject: [PATCH 03/38] Add `let_underscore_must_use` lint. Similar to `let_underscore_drop`, this lint checks for statements similar to `let _ = foo`, where `foo` is an expression marked `must_use`. --- compiler/rustc_lint/src/let_underscore.rs | 106 ++++++++++++++++++++- compiler/rustc_lint/src/lib.rs | 7 +- src/test/ui/let_underscore_must_use.rs | 12 +++ src/test/ui/let_underscore_must_use.stderr | 21 ++++ 4 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/let_underscore_must_use.rs create mode 100644 src/test/ui/let_underscore_must_use.stderr diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 81906a24d9029..40e6d12abf910 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -1,6 +1,6 @@ use crate::{LateContext, LateLintPass, LintContext}; use rustc_hir as hir; -use rustc_middle::ty::{self, subst::GenericArgKind}; +use rustc_middle::ty::{self, subst::GenericArgKind, Ty}; use rustc_span::Symbol; declare_lint! { @@ -83,7 +83,32 @@ declare_lint! { "non-binding let on a synchronization lock" } -declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK]); +declare_lint! { + /// The `let_underscore_must_use` lint checks for statements which don't bind + /// a `must_use` expression to anything, causing the lock to be released + /// immediately instead of at end of scope, which is typically incorrect. + /// + /// ### Example + /// ```rust + /// #[must_use] + /// struct SomeStruct; + /// + /// fn main() { + /// // SomeStuct is dropped immediately instead of at end of scope. + /// let _ = SomeStruct; + /// } + /// ``` + /// ### Explanation + /// + /// Statements which assign an expression to an underscore causes the + /// expression to immediately drop. Usually, it's better to explicitly handle + /// the `must_use` expression. + pub LET_UNDERSCORE_MUST_USE, + Warn, + "non-binding let on a expression marked `must_use`" +} + +declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_MUST_USE]); const SYNC_GUARD_PATHS: [&[&str]; 5] = [ &["std", "sync", "mutex", "MutexGuard"], @@ -114,6 +139,8 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, }); + let is_must_use_ty = is_must_use_ty(cx, cx.typeck_results().expr_ty(init)); + let is_must_use_func_call = is_must_use_func_call(cx, init); if is_sync_lock { cx.struct_span_lint(LET_UNDERSCORE_LOCK, local.span, |lint| { lint.build("non-binding let on a synchronization lock") @@ -121,6 +148,13 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { .help("consider explicitly droping with `std::mem::drop`") .emit(); }) + } else if is_must_use_ty || is_must_use_func_call { + cx.struct_span_lint(LET_UNDERSCORE_MUST_USE, local.span, |lint| { + lint.build("non-binding let on a expression marked `must_use`") + .help("consider binding to an unused variable") + .help("consider explicitly droping with `std::mem::drop`") + .emit(); + }) } else if needs_drop { cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| { lint.build("non-binding let on a type that implements `Drop`") @@ -130,5 +164,73 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { }) } } + + fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.kind() { + ty::Adt(adt, _) => has_must_use_attr(cx, adt.did()), + ty::Foreign(ref did) => has_must_use_attr(cx, *did), + ty::Slice(ty) + | ty::Array(ty, _) + | ty::RawPtr(ty::TypeAndMut { ty, .. }) + | ty::Ref(_, ty, _) => { + // for the Array case we don't need to care for the len == 0 case + // because we don't want to lint functions returning empty arrays + is_must_use_ty(cx, *ty) + } + ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), + ty::Opaque(ref def_id, _) => { + for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { + if let ty::PredicateKind::Trait(trait_predicate) = + predicate.kind().skip_binder() + { + if has_must_use_attr(cx, trait_predicate.trait_ref.def_id) { + return true; + } + } + } + false + } + ty::Dynamic(binder, _) => { + for predicate in binder.iter() { + if let ty::ExistentialPredicate::Trait(ref trait_ref) = + predicate.skip_binder() + { + if has_must_use_attr(cx, trait_ref.def_id) { + return true; + } + } + } + false + } + _ => false, + } + } + + // check if expr is calling method or function with #[must_use] attribute + fn is_must_use_func_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + let did = match expr.kind { + hir::ExprKind::Call(path, _) if let hir::ExprKind::Path(ref qpath) = path.kind => { + if let hir::def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id) { + Some(did) + } else { + None + } + }, + hir::ExprKind::MethodCall(..) => { + cx.typeck_results().type_dependent_def_id(expr.hir_id) + } + _ => None, + }; + + did.map_or(false, |did| has_must_use_attr(cx, did)) + } + + // returns true if DefId contains a `#[must_use]` attribute + fn has_must_use_attr(cx: &LateContext<'_>, did: hir::def_id::DefId) -> bool { + cx.tcx + .get_attrs(did, rustc_span::sym::must_use) + .find(|a| a.has_name(rustc_span::sym::must_use)) + .is_some() + } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 79661c0fefe8d..4359a54b698dc 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -317,7 +317,12 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { REDUNDANT_SEMICOLONS ); - add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK); + add_lint_group!( + "let_underscore", + LET_UNDERSCORE_DROP, + LET_UNDERSCORE_LOCK, + LET_UNDERSCORE_MUST_USE + ); add_lint_group!( "rust_2018_idioms", diff --git a/src/test/ui/let_underscore_must_use.rs b/src/test/ui/let_underscore_must_use.rs new file mode 100644 index 0000000000000..6a78e3fc4b402 --- /dev/null +++ b/src/test/ui/let_underscore_must_use.rs @@ -0,0 +1,12 @@ +// run-pass + +#[must_use] +struct MustUseType; + +#[must_use] +fn must_use_function() -> () {} + +fn main() { + let _ = MustUseType; //~WARNING non-binding let on a expression marked `must_use` + let _ = must_use_function(); //~WARNING non-binding let on a expression marked `must_use` +} diff --git a/src/test/ui/let_underscore_must_use.stderr b/src/test/ui/let_underscore_must_use.stderr new file mode 100644 index 0000000000000..0b840385e5dfa --- /dev/null +++ b/src/test/ui/let_underscore_must_use.stderr @@ -0,0 +1,21 @@ +warning: non-binding let on a expression marked `must_use` + --> $DIR/let_underscore_must_use.rs:10:5 + | +LL | let _ = MustUseType; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(let_underscore_must_use)]` on by default + = help: consider binding to an unused variable + = help: consider explicitly droping with `std::mem::drop` + +warning: non-binding let on a expression marked `must_use` + --> $DIR/let_underscore_must_use.rs:11:5 + | +LL | let _ = must_use_function(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider binding to an unused variable + = help: consider explicitly droping with `std::mem::drop` + +warning: 2 warnings emitted + From 36b6309c6556e5486138057e8c654b40e005327d Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Fri, 3 Jun 2022 14:37:14 -0400 Subject: [PATCH 04/38] Move let_underscore tests to their own subfolder. This was done to pass `tidy`. --- src/test/ui/{ => let_underscore}/let_underscore_drop.rs | 0 src/test/ui/{ => let_underscore}/let_underscore_drop.stderr | 0 src/test/ui/{ => let_underscore}/let_underscore_lock.rs | 0 src/test/ui/{ => let_underscore}/let_underscore_lock.stderr | 0 src/test/ui/{ => let_underscore}/let_underscore_must_use.rs | 0 src/test/ui/{ => let_underscore}/let_underscore_must_use.stderr | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => let_underscore}/let_underscore_drop.rs (100%) rename src/test/ui/{ => let_underscore}/let_underscore_drop.stderr (100%) rename src/test/ui/{ => let_underscore}/let_underscore_lock.rs (100%) rename src/test/ui/{ => let_underscore}/let_underscore_lock.stderr (100%) rename src/test/ui/{ => let_underscore}/let_underscore_must_use.rs (100%) rename src/test/ui/{ => let_underscore}/let_underscore_must_use.stderr (100%) diff --git a/src/test/ui/let_underscore_drop.rs b/src/test/ui/let_underscore/let_underscore_drop.rs similarity index 100% rename from src/test/ui/let_underscore_drop.rs rename to src/test/ui/let_underscore/let_underscore_drop.rs diff --git a/src/test/ui/let_underscore_drop.stderr b/src/test/ui/let_underscore/let_underscore_drop.stderr similarity index 100% rename from src/test/ui/let_underscore_drop.stderr rename to src/test/ui/let_underscore/let_underscore_drop.stderr diff --git a/src/test/ui/let_underscore_lock.rs b/src/test/ui/let_underscore/let_underscore_lock.rs similarity index 100% rename from src/test/ui/let_underscore_lock.rs rename to src/test/ui/let_underscore/let_underscore_lock.rs diff --git a/src/test/ui/let_underscore_lock.stderr b/src/test/ui/let_underscore/let_underscore_lock.stderr similarity index 100% rename from src/test/ui/let_underscore_lock.stderr rename to src/test/ui/let_underscore/let_underscore_lock.stderr diff --git a/src/test/ui/let_underscore_must_use.rs b/src/test/ui/let_underscore/let_underscore_must_use.rs similarity index 100% rename from src/test/ui/let_underscore_must_use.rs rename to src/test/ui/let_underscore/let_underscore_must_use.rs diff --git a/src/test/ui/let_underscore_must_use.stderr b/src/test/ui/let_underscore/let_underscore_must_use.stderr similarity index 100% rename from src/test/ui/let_underscore_must_use.stderr rename to src/test/ui/let_underscore/let_underscore_must_use.stderr From ae2ac3b4c568d2d20cb395a57a163e1e298d6d6c Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Fri, 3 Jun 2022 16:19:55 -0400 Subject: [PATCH 05/38] Allow `let_underscore_drop` and `let_underscore_must_use` by default. These lints are very noisy and are allow-by-default in clippy anyways. Hence, setting them to allow-by-default here makes more sense than warning constantly on these cases. --- compiler/rustc_lint/src/let_underscore.rs | 4 ++-- src/test/ui/let_underscore/let_underscore_drop.rs | 1 + src/test/ui/let_underscore/let_underscore_drop.stderr | 4 ++-- src/test/ui/let_underscore/let_underscore_must_use.rs | 1 + src/test/ui/let_underscore/let_underscore_must_use.stderr | 6 +++--- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 40e6d12abf910..985c7300efa95 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -41,7 +41,7 @@ declare_lint! { /// calling `std::mem::drop` on the expression is clearer and helps convey /// intent. pub LET_UNDERSCORE_DROP, - Warn, + Allow, "non-binding let on a type that implements `Drop`" } @@ -104,7 +104,7 @@ declare_lint! { /// expression to immediately drop. Usually, it's better to explicitly handle /// the `must_use` expression. pub LET_UNDERSCORE_MUST_USE, - Warn, + Allow, "non-binding let on a expression marked `must_use`" } diff --git a/src/test/ui/let_underscore/let_underscore_drop.rs b/src/test/ui/let_underscore/let_underscore_drop.rs index c1c5207d0fe87..75c6ecec3ee53 100644 --- a/src/test/ui/let_underscore/let_underscore_drop.rs +++ b/src/test/ui/let_underscore/let_underscore_drop.rs @@ -1,4 +1,5 @@ // run-pass +// compile-flags: -W let_underscore_drop struct NontrivialDrop; diff --git a/src/test/ui/let_underscore/let_underscore_drop.stderr b/src/test/ui/let_underscore/let_underscore_drop.stderr index 40ed1abd8dc6f..f4fd663c7f9ea 100644 --- a/src/test/ui/let_underscore/let_underscore_drop.stderr +++ b/src/test/ui/let_underscore/let_underscore_drop.stderr @@ -1,10 +1,10 @@ warning: non-binding let on a type that implements `Drop` - --> $DIR/let_underscore_drop.rs:12:5 + --> $DIR/let_underscore_drop.rs:13:5 | LL | let _ = NontrivialDrop; | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(let_underscore_drop)]` on by default + = note: requested on the command line with `-W let-underscore-drop` = help: consider binding to an unused variable = help: consider explicitly droping with `std::mem::drop` diff --git a/src/test/ui/let_underscore/let_underscore_must_use.rs b/src/test/ui/let_underscore/let_underscore_must_use.rs index 6a78e3fc4b402..8efaad51ea877 100644 --- a/src/test/ui/let_underscore/let_underscore_must_use.rs +++ b/src/test/ui/let_underscore/let_underscore_must_use.rs @@ -1,4 +1,5 @@ // run-pass +// compile-flags: -W let_underscore_must_use #[must_use] struct MustUseType; diff --git a/src/test/ui/let_underscore/let_underscore_must_use.stderr b/src/test/ui/let_underscore/let_underscore_must_use.stderr index 0b840385e5dfa..ea1de45e17b57 100644 --- a/src/test/ui/let_underscore/let_underscore_must_use.stderr +++ b/src/test/ui/let_underscore/let_underscore_must_use.stderr @@ -1,15 +1,15 @@ warning: non-binding let on a expression marked `must_use` - --> $DIR/let_underscore_must_use.rs:10:5 + --> $DIR/let_underscore_must_use.rs:11:5 | LL | let _ = MustUseType; | ^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(let_underscore_must_use)]` on by default + = note: requested on the command line with `-W let-underscore-must-use` = help: consider binding to an unused variable = help: consider explicitly droping with `std::mem::drop` warning: non-binding let on a expression marked `must_use` - --> $DIR/let_underscore_must_use.rs:11:5 + --> $DIR/let_underscore_must_use.rs:12:5 | LL | let _ = must_use_function(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From eba6c789dcfca7065d1c292c06eb447ac9895db3 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Fri, 3 Jun 2022 21:33:13 -0400 Subject: [PATCH 06/38] Show code suggestions in `let_undescore` lint messages. This commit uses `span_suggestion_verbose` to add what specific code changes can be done as suggested by the lint--in this case, either binding the expression to an unused variable or using `std::mem::drop` to drop the value explicitly. --- compiler/rustc_lint/src/let_underscore.rs | 60 +++++++++++++++---- .../let_underscore/let_underscore_drop.stderr | 10 +++- .../let_underscore/let_underscore_lock.stderr | 10 +++- .../let_underscore_must_use.stderr | 20 +++++-- 4 files changed, 79 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 985c7300efa95..4e4cedaeb7821 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -1,6 +1,10 @@ use crate::{LateContext, LateLintPass, LintContext}; +use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_middle::ty::{self, subst::GenericArgKind, Ty}; +use rustc_middle::{ + lint::LintDiagnosticBuilder, + ty::{self, subst::GenericArgKind, Ty}, +}; use rustc_span::Symbol; declare_lint! { @@ -141,30 +145,60 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { }); let is_must_use_ty = is_must_use_ty(cx, cx.typeck_results().expr_ty(init)); let is_must_use_func_call = is_must_use_func_call(cx, init); + if is_sync_lock { cx.struct_span_lint(LET_UNDERSCORE_LOCK, local.span, |lint| { - lint.build("non-binding let on a synchronization lock") - .help("consider binding to an unused variable") - .help("consider explicitly droping with `std::mem::drop`") - .emit(); + build_and_emit_lint( + lint, + local, + init.span, + "non-binding let on a synchronization lock", + ) }) } else if is_must_use_ty || is_must_use_func_call { cx.struct_span_lint(LET_UNDERSCORE_MUST_USE, local.span, |lint| { - lint.build("non-binding let on a expression marked `must_use`") - .help("consider binding to an unused variable") - .help("consider explicitly droping with `std::mem::drop`") - .emit(); + build_and_emit_lint( + lint, + local, + init.span, + "non-binding let on a expression marked `must_use`", + ); }) } else if needs_drop { cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| { - lint.build("non-binding let on a type that implements `Drop`") - .help("consider binding to an unused variable") - .help("consider explicitly droping with `std::mem::drop`") - .emit(); + build_and_emit_lint( + lint, + local, + init.span, + "non-binding let on a type that implements `Drop`", + ); }) } } + fn build_and_emit_lint( + lint: LintDiagnosticBuilder<'_, ()>, + local: &hir::Local<'_>, + init_span: rustc_span::Span, + msg: &str, + ) { + lint.build(msg) + .span_suggestion_verbose( + local.pat.span, + "consider binding to an unused variable", + "_unused", + Applicability::MachineApplicable, + ) + .span_suggestion_verbose( + init_span, + "consider explicitly droping with `std::mem::drop`", + "drop(...)", + Applicability::HasPlaceholders, + ) + .emit(); + } + + // return true if `ty` is a type that is marked as `must_use` fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { ty::Adt(adt, _) => has_must_use_attr(cx, adt.did()), diff --git a/src/test/ui/let_underscore/let_underscore_drop.stderr b/src/test/ui/let_underscore/let_underscore_drop.stderr index f4fd663c7f9ea..5034f682bb76b 100644 --- a/src/test/ui/let_underscore/let_underscore_drop.stderr +++ b/src/test/ui/let_underscore/let_underscore_drop.stderr @@ -5,8 +5,14 @@ LL | let _ = NontrivialDrop; | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: requested on the command line with `-W let-underscore-drop` - = help: consider binding to an unused variable - = help: consider explicitly droping with `std::mem::drop` +help: consider binding to an unused variable + | +LL | let _unused = NontrivialDrop; + | ~~~~~~~ +help: consider explicitly droping with `std::mem::drop` + | +LL | let _ = drop(...); + | ~~~~~~~~~ warning: 1 warning emitted diff --git a/src/test/ui/let_underscore/let_underscore_lock.stderr b/src/test/ui/let_underscore/let_underscore_lock.stderr index 77379d8c3db2c..08f81962f3c65 100644 --- a/src/test/ui/let_underscore/let_underscore_lock.stderr +++ b/src/test/ui/let_underscore/let_underscore_lock.stderr @@ -5,8 +5,14 @@ LL | let _ = data.lock().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(let_underscore_lock)]` on by default - = help: consider binding to an unused variable - = help: consider explicitly droping with `std::mem::drop` +help: consider binding to an unused variable + | +LL | let _unused = data.lock().unwrap(); + | ~~~~~~~ +help: consider explicitly droping with `std::mem::drop` + | +LL | let _ = drop(...); + | ~~~~~~~~~ warning: 1 warning emitted diff --git a/src/test/ui/let_underscore/let_underscore_must_use.stderr b/src/test/ui/let_underscore/let_underscore_must_use.stderr index ea1de45e17b57..959572edd7c0d 100644 --- a/src/test/ui/let_underscore/let_underscore_must_use.stderr +++ b/src/test/ui/let_underscore/let_underscore_must_use.stderr @@ -5,8 +5,14 @@ LL | let _ = MustUseType; | ^^^^^^^^^^^^^^^^^^^^ | = note: requested on the command line with `-W let-underscore-must-use` - = help: consider binding to an unused variable - = help: consider explicitly droping with `std::mem::drop` +help: consider binding to an unused variable + | +LL | let _unused = MustUseType; + | ~~~~~~~ +help: consider explicitly droping with `std::mem::drop` + | +LL | let _ = drop(...); + | ~~~~~~~~~ warning: non-binding let on a expression marked `must_use` --> $DIR/let_underscore_must_use.rs:12:5 @@ -14,8 +20,14 @@ warning: non-binding let on a expression marked `must_use` LL | let _ = must_use_function(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider binding to an unused variable - = help: consider explicitly droping with `std::mem::drop` +help: consider binding to an unused variable + | +LL | let _unused = must_use_function(); + | ~~~~~~~ +help: consider explicitly droping with `std::mem::drop` + | +LL | let _ = drop(...); + | ~~~~~~~~~ warning: 2 warnings emitted From 6b179e3a67a2242b63892a1831ba217d968c2f62 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 4 Jun 2022 13:50:12 -0400 Subject: [PATCH 07/38] Set `let_underscore_lock` to Deny by default. Clippy sets this lint to Deny by default, and it having the lint be Deny is useful for when we test the lint against a Crater run. --- compiler/rustc_lint/src/let_underscore.rs | 4 ++-- src/test/ui/let_underscore/let_underscore_lock.rs | 4 +--- src/test/ui/let_underscore/let_underscore_lock.stderr | 8 ++++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 4e4cedaeb7821..306c6197c24e2 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -55,7 +55,7 @@ declare_lint! { /// of at end of scope, which is typically incorrect. /// /// ### Example - /// ```rust + /// ```compile_fail /// use std::sync::{Arc, Mutex}; /// use std::thread; /// let data = Arc::new(Mutex::new(0)); @@ -83,7 +83,7 @@ declare_lint! { /// calling `std::mem::drop` on the expression is clearer and helps convey /// intent. pub LET_UNDERSCORE_LOCK, - Warn, + Deny, "non-binding let on a synchronization lock" } diff --git a/src/test/ui/let_underscore/let_underscore_lock.rs b/src/test/ui/let_underscore/let_underscore_lock.rs index 774b610db2fb8..c37264136ef7f 100644 --- a/src/test/ui/let_underscore/let_underscore_lock.rs +++ b/src/test/ui/let_underscore/let_underscore_lock.rs @@ -1,8 +1,6 @@ -// run-pass - use std::sync::{Arc, Mutex}; fn main() { let data = Arc::new(Mutex::new(0)); - let _ = data.lock().unwrap(); //~WARNING non-binding let on a synchronization lock + let _ = data.lock().unwrap(); //~ERROR non-binding let on a synchronization lock } diff --git a/src/test/ui/let_underscore/let_underscore_lock.stderr b/src/test/ui/let_underscore/let_underscore_lock.stderr index 08f81962f3c65..b7e14e8c7b5c5 100644 --- a/src/test/ui/let_underscore/let_underscore_lock.stderr +++ b/src/test/ui/let_underscore/let_underscore_lock.stderr @@ -1,10 +1,10 @@ -warning: non-binding let on a synchronization lock - --> $DIR/let_underscore_lock.rs:7:5 +error: non-binding let on a synchronization lock + --> $DIR/let_underscore_lock.rs:5:5 | LL | let _ = data.lock().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(let_underscore_lock)]` on by default + = note: `#[deny(let_underscore_lock)]` on by default help: consider binding to an unused variable | LL | let _unused = data.lock().unwrap(); @@ -14,5 +14,5 @@ help: consider explicitly droping with `std::mem::drop` LL | let _ = drop(...); | ~~~~~~~~~ -warning: 1 warning emitted +error: aborting due to previous error From a7e2b3e879790284b64529e3fb7d659274420a90 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 4 Jun 2022 19:52:12 -0400 Subject: [PATCH 08/38] Move local functions to outer scope. --- compiler/rustc_lint/src/let_underscore.rs | 134 +++++++++++----------- 1 file changed, 65 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 306c6197c24e2..c2d1cff313b87 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -175,74 +175,72 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { }) } } + } +} - fn build_and_emit_lint( - lint: LintDiagnosticBuilder<'_, ()>, - local: &hir::Local<'_>, - init_span: rustc_span::Span, - msg: &str, - ) { - lint.build(msg) - .span_suggestion_verbose( - local.pat.span, - "consider binding to an unused variable", - "_unused", - Applicability::MachineApplicable, - ) - .span_suggestion_verbose( - init_span, - "consider explicitly droping with `std::mem::drop`", - "drop(...)", - Applicability::HasPlaceholders, - ) - .emit(); - } +fn build_and_emit_lint( + lint: LintDiagnosticBuilder<'_, ()>, + local: &hir::Local<'_>, + init_span: rustc_span::Span, + msg: &str, +) { + lint.build(msg) + .span_suggestion_verbose( + local.pat.span, + "consider binding to an unused variable", + "_unused", + Applicability::MachineApplicable, + ) + .span_suggestion_verbose( + init_span, + "consider explicitly droping with `std::mem::drop`", + "drop(...)", + Applicability::HasPlaceholders, + ) + .emit(); +} - // return true if `ty` is a type that is marked as `must_use` - fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.kind() { - ty::Adt(adt, _) => has_must_use_attr(cx, adt.did()), - ty::Foreign(ref did) => has_must_use_attr(cx, *did), - ty::Slice(ty) - | ty::Array(ty, _) - | ty::RawPtr(ty::TypeAndMut { ty, .. }) - | ty::Ref(_, ty, _) => { - // for the Array case we don't need to care for the len == 0 case - // because we don't want to lint functions returning empty arrays - is_must_use_ty(cx, *ty) - } - ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), - ty::Opaque(ref def_id, _) => { - for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { - if let ty::PredicateKind::Trait(trait_predicate) = - predicate.kind().skip_binder() - { - if has_must_use_attr(cx, trait_predicate.trait_ref.def_id) { - return true; - } - } +// return true if `ty` is a type that is marked as `must_use` +fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.kind() { + ty::Adt(adt, _) => has_must_use_attr(cx, adt.did()), + ty::Foreign(ref did) => has_must_use_attr(cx, *did), + ty::Slice(ty) + | ty::Array(ty, _) + | ty::RawPtr(ty::TypeAndMut { ty, .. }) + | ty::Ref(_, ty, _) => { + // for the Array case we don't need to care for the len == 0 case + // because we don't want to lint functions returning empty arrays + is_must_use_ty(cx, *ty) + } + ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), + ty::Opaque(ref def_id, _) => { + for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { + if let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() { + if has_must_use_attr(cx, trait_predicate.trait_ref.def_id) { + return true; } - false } - ty::Dynamic(binder, _) => { - for predicate in binder.iter() { - if let ty::ExistentialPredicate::Trait(ref trait_ref) = - predicate.skip_binder() - { - if has_must_use_attr(cx, trait_ref.def_id) { - return true; - } - } + } + false + } + ty::Dynamic(binder, _) => { + for predicate in binder.iter() { + if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { + if has_must_use_attr(cx, trait_ref.def_id) { + return true; } - false } - _ => false, } + false } + _ => false, + } +} - // check if expr is calling method or function with #[must_use] attribute - fn is_must_use_func_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { - let did = match expr.kind { +// check if expr is calling method or function with #[must_use] attribute +fn is_must_use_func_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + let did = match expr.kind { hir::ExprKind::Call(path, _) if let hir::ExprKind::Path(ref qpath) = path.kind => { if let hir::def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id) { Some(did) @@ -256,15 +254,13 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { _ => None, }; - did.map_or(false, |did| has_must_use_attr(cx, did)) - } + did.map_or(false, |did| has_must_use_attr(cx, did)) +} - // returns true if DefId contains a `#[must_use]` attribute - fn has_must_use_attr(cx: &LateContext<'_>, did: hir::def_id::DefId) -> bool { - cx.tcx - .get_attrs(did, rustc_span::sym::must_use) - .find(|a| a.has_name(rustc_span::sym::must_use)) - .is_some() - } - } +// returns true if DefId contains a `#[must_use]` attribute +fn has_must_use_attr(cx: &LateContext<'_>, did: hir::def_id::DefId) -> bool { + cx.tcx + .get_attrs(did, rustc_span::sym::must_use) + .find(|a| a.has_name(rustc_span::sym::must_use)) + .is_some() } From 7e485bf4ddd3f56c76a572757d60c24dcfaa7dbe Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 4 Jun 2022 20:04:01 -0400 Subject: [PATCH 09/38] Move `let_underscore` tests into the `lint` subfolder. --- src/test/ui/{ => lint}/let_underscore/let_underscore_drop.rs | 0 src/test/ui/{ => lint}/let_underscore/let_underscore_drop.stderr | 0 src/test/ui/{ => lint}/let_underscore/let_underscore_lock.rs | 0 src/test/ui/{ => lint}/let_underscore/let_underscore_lock.stderr | 0 src/test/ui/{ => lint}/let_underscore/let_underscore_must_use.rs | 0 .../ui/{ => lint}/let_underscore/let_underscore_must_use.stderr | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => lint}/let_underscore/let_underscore_drop.rs (100%) rename src/test/ui/{ => lint}/let_underscore/let_underscore_drop.stderr (100%) rename src/test/ui/{ => lint}/let_underscore/let_underscore_lock.rs (100%) rename src/test/ui/{ => lint}/let_underscore/let_underscore_lock.stderr (100%) rename src/test/ui/{ => lint}/let_underscore/let_underscore_must_use.rs (100%) rename src/test/ui/{ => lint}/let_underscore/let_underscore_must_use.stderr (100%) diff --git a/src/test/ui/let_underscore/let_underscore_drop.rs b/src/test/ui/lint/let_underscore/let_underscore_drop.rs similarity index 100% rename from src/test/ui/let_underscore/let_underscore_drop.rs rename to src/test/ui/lint/let_underscore/let_underscore_drop.rs diff --git a/src/test/ui/let_underscore/let_underscore_drop.stderr b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr similarity index 100% rename from src/test/ui/let_underscore/let_underscore_drop.stderr rename to src/test/ui/lint/let_underscore/let_underscore_drop.stderr diff --git a/src/test/ui/let_underscore/let_underscore_lock.rs b/src/test/ui/lint/let_underscore/let_underscore_lock.rs similarity index 100% rename from src/test/ui/let_underscore/let_underscore_lock.rs rename to src/test/ui/lint/let_underscore/let_underscore_lock.rs diff --git a/src/test/ui/let_underscore/let_underscore_lock.stderr b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr similarity index 100% rename from src/test/ui/let_underscore/let_underscore_lock.stderr rename to src/test/ui/lint/let_underscore/let_underscore_lock.stderr diff --git a/src/test/ui/let_underscore/let_underscore_must_use.rs b/src/test/ui/lint/let_underscore/let_underscore_must_use.rs similarity index 100% rename from src/test/ui/let_underscore/let_underscore_must_use.rs rename to src/test/ui/lint/let_underscore/let_underscore_must_use.rs diff --git a/src/test/ui/let_underscore/let_underscore_must_use.stderr b/src/test/ui/lint/let_underscore/let_underscore_must_use.stderr similarity index 100% rename from src/test/ui/let_underscore/let_underscore_must_use.stderr rename to src/test/ui/lint/let_underscore/let_underscore_must_use.stderr From 1421cffca17f8904664d036996768d5880604f71 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 4 Jun 2022 20:12:26 -0400 Subject: [PATCH 10/38] Add `let_underscore` lint group to `GROUP_DESCRIPTIONS`. --- src/tools/lint-docs/src/groups.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs index 9696e35b7963f..2a923a61b0a70 100644 --- a/src/tools/lint-docs/src/groups.rs +++ b/src/tools/lint-docs/src/groups.rs @@ -8,6 +8,7 @@ use std::process::Command; /// Descriptions of rustc lint groups. static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[ ("unused", "Lints that detect things being declared but not used, or excess syntax"), + ("let-underscore", "Lints that detect wildcard let bindings that are likely to be invalid"), ("rustdoc", "Rustdoc-specific lints"), ("rust-2018-idioms", "Lints to nudge you toward idiomatic features of Rust 2018"), ("nonstandard-style", "Violation of standard naming conventions"), From 30e8adb1a766e8444586fef3953bf7715fe588e1 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 4 Jun 2022 20:16:56 -0400 Subject: [PATCH 11/38] Use `has_attr` instead of `get_attrs` in `has_must_use_attr` --- compiler/rustc_lint/src/let_underscore.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index c2d1cff313b87..d33ea450b3e89 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -259,8 +259,5 @@ fn is_must_use_func_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { // returns true if DefId contains a `#[must_use]` attribute fn has_must_use_attr(cx: &LateContext<'_>, did: hir::def_id::DefId) -> bool { - cx.tcx - .get_attrs(did, rustc_span::sym::must_use) - .find(|a| a.has_name(rustc_span::sym::must_use)) - .is_some() + cx.tcx.has_attr(did, rustc_span::sym::must_use) } From e6b66784aca8564557485d902968ff7523cf30ca Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 4 Jun 2022 20:19:19 -0400 Subject: [PATCH 12/38] Bail out early if the type does not has a trivial Drop implementation. If the type has a trivial Drop implementation, then it is probably irrelevant that the type was dropped immediately, since nothing important happens on drop. Hence, we can bail out early instead of doing some expensive checks. --- compiler/rustc_lint/src/let_underscore.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index d33ea450b3e89..1e4565a226c7a 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -129,7 +129,11 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { } if let Some(init) = local.init { let init_ty = cx.typeck_results().expr_ty(init); - let needs_drop = init_ty.needs_drop(cx.tcx, cx.param_env); + // If the type has a trivial Drop implementation, then it doesn't + // matter that we drop the value immediately. + if !init_ty.needs_drop(cx.tcx, cx.param_env) { + return; + } let is_sync_lock = init_ty.walk().any(|inner| match inner.unpack() { GenericArgKind::Type(inner_ty) => { SYNC_GUARD_PATHS.iter().any(|guard_path| match inner_ty.kind() { @@ -164,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { "non-binding let on a expression marked `must_use`", ); }) - } else if needs_drop { + } else { cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| { build_and_emit_lint( lint, From 6342b58ef0f71ca0284dced4b1d22f9726c1c74a Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 4 Jun 2022 22:27:32 -0400 Subject: [PATCH 13/38] Use diagnostic items instead of hard coded paths for `let_underscore_lock` Using diagnostic items avoids having to update the paths if the guard types ever get moved around for some reason. Additionally, it also greatly simplifies the `is_sync_lock` check. --- compiler/rustc_lint/src/let_underscore.rs | 31 ++++++++--------------- compiler/rustc_span/src/symbol.rs | 3 +++ 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 1e4565a226c7a..2ad09312d9d56 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -3,7 +3,7 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_middle::{ lint::LintDiagnosticBuilder, - ty::{self, subst::GenericArgKind, Ty}, + ty::{self, Ty}, }; use rustc_span::Symbol; @@ -114,12 +114,10 @@ declare_lint! { declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_MUST_USE]); -const SYNC_GUARD_PATHS: [&[&str]; 5] = [ - &["std", "sync", "mutex", "MutexGuard"], - &["std", "sync", "rwlock", "RwLockReadGuard"], - &["std", "sync", "rwlock", "RwLockWriteGuard"], - &["parking_lot", "raw_mutex", "RawMutex"], - &["parking_lot", "raw_rwlock", "RawRwLock"], +const SYNC_GUARD_SYMBOLS: [Symbol; 3] = [ + rustc_span::sym::MutexGuard, + rustc_span::sym::RwLockReadGuard, + rustc_span::sym::RwLockWriteGuard, ]; impl<'tcx> LateLintPass<'tcx> for LetUnderscore { @@ -134,19 +132,12 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { if !init_ty.needs_drop(cx.tcx, cx.param_env) { return; } - let is_sync_lock = init_ty.walk().any(|inner| match inner.unpack() { - GenericArgKind::Type(inner_ty) => { - SYNC_GUARD_PATHS.iter().any(|guard_path| match inner_ty.kind() { - ty::Adt(adt, _) => { - let ty_path = cx.get_def_path(adt.did()); - guard_path.iter().map(|x| Symbol::intern(x)).eq(ty_path.iter().copied()) - } - _ => false, - }) - } - - GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, - }); + let is_sync_lock = match init_ty.kind() { + ty::Adt(adt, _) => SYNC_GUARD_SYMBOLS + .iter() + .any(|guard_symbol| cx.tcx.is_diagnostic_item(*guard_symbol, adt.did())), + _ => false, + }; let is_must_use_ty = is_must_use_ty(cx, cx.typeck_results().expr_ty(init)); let is_must_use_func_call = is_must_use_func_call(cx, init); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5c9c16350e469..bc9f5c910df54 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -213,6 +213,7 @@ symbols! { LinkedList, LintPass, Mutex, + MutexGuard, N, None, Ok, @@ -250,6 +251,8 @@ symbols! { Right, RustcDecodable, RustcEncodable, + RwLockReadGuard, + RwLockWriteGuard, Send, SeqCst, SliceIndex, From 11663b1d78cd4e9bc68cf13e55ee73189f1d1cf5 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 4 Jun 2022 23:31:47 -0400 Subject: [PATCH 14/38] Use `check-pass` instead of `run-pass` We don't actually care about running these programs, only checking the warnings they generate. --- src/test/ui/lint/let_underscore/let_underscore_drop.rs | 2 +- src/test/ui/lint/let_underscore/let_underscore_lock.rs | 1 + src/test/ui/lint/let_underscore/let_underscore_must_use.rs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/ui/lint/let_underscore/let_underscore_drop.rs b/src/test/ui/lint/let_underscore/let_underscore_drop.rs index 75c6ecec3ee53..85ca5dd2880a4 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_drop.rs +++ b/src/test/ui/lint/let_underscore/let_underscore_drop.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // compile-flags: -W let_underscore_drop struct NontrivialDrop; diff --git a/src/test/ui/lint/let_underscore/let_underscore_lock.rs b/src/test/ui/lint/let_underscore/let_underscore_lock.rs index c37264136ef7f..7423862cdf05d 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_lock.rs +++ b/src/test/ui/lint/let_underscore/let_underscore_lock.rs @@ -1,3 +1,4 @@ +// check-fail use std::sync::{Arc, Mutex}; fn main() { diff --git a/src/test/ui/lint/let_underscore/let_underscore_must_use.rs b/src/test/ui/lint/let_underscore/let_underscore_must_use.rs index 8efaad51ea877..3f79dc7a096b6 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_must_use.rs +++ b/src/test/ui/lint/let_underscore/let_underscore_must_use.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // compile-flags: -W let_underscore_must_use #[must_use] From b5b5b5471ba324f6b4d5a53957a800ad44126964 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sun, 5 Jun 2022 00:05:50 -0400 Subject: [PATCH 15/38] Remove `let_underscore_must_use` The `let_underscore_must_use` lint was really only added because clippy included it, but it doesn't actually seem very useful. --- compiler/rustc_lint/src/let_underscore.rs | 105 +----------------- compiler/rustc_lint/src/lib.rs | 7 +- .../let_underscore/let_underscore_must_use.rs | 13 --- .../let_underscore_must_use.stderr | 33 ------ 4 files changed, 3 insertions(+), 155 deletions(-) delete mode 100644 src/test/ui/lint/let_underscore/let_underscore_must_use.rs delete mode 100644 src/test/ui/lint/let_underscore/let_underscore_must_use.stderr diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 2ad09312d9d56..dea878c4460b9 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -1,10 +1,7 @@ use crate::{LateContext, LateLintPass, LintContext}; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_middle::{ - lint::LintDiagnosticBuilder, - ty::{self, Ty}, -}; +use rustc_middle::{lint::LintDiagnosticBuilder, ty}; use rustc_span::Symbol; declare_lint! { @@ -87,32 +84,7 @@ declare_lint! { "non-binding let on a synchronization lock" } -declare_lint! { - /// The `let_underscore_must_use` lint checks for statements which don't bind - /// a `must_use` expression to anything, causing the lock to be released - /// immediately instead of at end of scope, which is typically incorrect. - /// - /// ### Example - /// ```rust - /// #[must_use] - /// struct SomeStruct; - /// - /// fn main() { - /// // SomeStuct is dropped immediately instead of at end of scope. - /// let _ = SomeStruct; - /// } - /// ``` - /// ### Explanation - /// - /// Statements which assign an expression to an underscore causes the - /// expression to immediately drop. Usually, it's better to explicitly handle - /// the `must_use` expression. - pub LET_UNDERSCORE_MUST_USE, - Allow, - "non-binding let on a expression marked `must_use`" -} - -declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_MUST_USE]); +declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK]); const SYNC_GUARD_SYMBOLS: [Symbol; 3] = [ rustc_span::sym::MutexGuard, @@ -138,8 +110,6 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { .any(|guard_symbol| cx.tcx.is_diagnostic_item(*guard_symbol, adt.did())), _ => false, }; - let is_must_use_ty = is_must_use_ty(cx, cx.typeck_results().expr_ty(init)); - let is_must_use_func_call = is_must_use_func_call(cx, init); if is_sync_lock { cx.struct_span_lint(LET_UNDERSCORE_LOCK, local.span, |lint| { @@ -150,15 +120,6 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { "non-binding let on a synchronization lock", ) }) - } else if is_must_use_ty || is_must_use_func_call { - cx.struct_span_lint(LET_UNDERSCORE_MUST_USE, local.span, |lint| { - build_and_emit_lint( - lint, - local, - init.span, - "non-binding let on a expression marked `must_use`", - ); - }) } else { cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| { build_and_emit_lint( @@ -194,65 +155,3 @@ fn build_and_emit_lint( ) .emit(); } - -// return true if `ty` is a type that is marked as `must_use` -fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.kind() { - ty::Adt(adt, _) => has_must_use_attr(cx, adt.did()), - ty::Foreign(ref did) => has_must_use_attr(cx, *did), - ty::Slice(ty) - | ty::Array(ty, _) - | ty::RawPtr(ty::TypeAndMut { ty, .. }) - | ty::Ref(_, ty, _) => { - // for the Array case we don't need to care for the len == 0 case - // because we don't want to lint functions returning empty arrays - is_must_use_ty(cx, *ty) - } - ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), - ty::Opaque(ref def_id, _) => { - for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { - if let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() { - if has_must_use_attr(cx, trait_predicate.trait_ref.def_id) { - return true; - } - } - } - false - } - ty::Dynamic(binder, _) => { - for predicate in binder.iter() { - if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { - if has_must_use_attr(cx, trait_ref.def_id) { - return true; - } - } - } - false - } - _ => false, - } -} - -// check if expr is calling method or function with #[must_use] attribute -fn is_must_use_func_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { - let did = match expr.kind { - hir::ExprKind::Call(path, _) if let hir::ExprKind::Path(ref qpath) = path.kind => { - if let hir::def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id) { - Some(did) - } else { - None - } - }, - hir::ExprKind::MethodCall(..) => { - cx.typeck_results().type_dependent_def_id(expr.hir_id) - } - _ => None, - }; - - did.map_or(false, |did| has_must_use_attr(cx, did)) -} - -// returns true if DefId contains a `#[must_use]` attribute -fn has_must_use_attr(cx: &LateContext<'_>, did: hir::def_id::DefId) -> bool { - cx.tcx.has_attr(did, rustc_span::sym::must_use) -} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4359a54b698dc..79661c0fefe8d 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -317,12 +317,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { REDUNDANT_SEMICOLONS ); - add_lint_group!( - "let_underscore", - LET_UNDERSCORE_DROP, - LET_UNDERSCORE_LOCK, - LET_UNDERSCORE_MUST_USE - ); + add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK); add_lint_group!( "rust_2018_idioms", diff --git a/src/test/ui/lint/let_underscore/let_underscore_must_use.rs b/src/test/ui/lint/let_underscore/let_underscore_must_use.rs deleted file mode 100644 index 3f79dc7a096b6..0000000000000 --- a/src/test/ui/lint/let_underscore/let_underscore_must_use.rs +++ /dev/null @@ -1,13 +0,0 @@ -// check-pass -// compile-flags: -W let_underscore_must_use - -#[must_use] -struct MustUseType; - -#[must_use] -fn must_use_function() -> () {} - -fn main() { - let _ = MustUseType; //~WARNING non-binding let on a expression marked `must_use` - let _ = must_use_function(); //~WARNING non-binding let on a expression marked `must_use` -} diff --git a/src/test/ui/lint/let_underscore/let_underscore_must_use.stderr b/src/test/ui/lint/let_underscore/let_underscore_must_use.stderr deleted file mode 100644 index 959572edd7c0d..0000000000000 --- a/src/test/ui/lint/let_underscore/let_underscore_must_use.stderr +++ /dev/null @@ -1,33 +0,0 @@ -warning: non-binding let on a expression marked `must_use` - --> $DIR/let_underscore_must_use.rs:11:5 - | -LL | let _ = MustUseType; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: requested on the command line with `-W let-underscore-must-use` -help: consider binding to an unused variable - | -LL | let _unused = MustUseType; - | ~~~~~~~ -help: consider explicitly droping with `std::mem::drop` - | -LL | let _ = drop(...); - | ~~~~~~~~~ - -warning: non-binding let on a expression marked `must_use` - --> $DIR/let_underscore_must_use.rs:12:5 - | -LL | let _ = must_use_function(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider binding to an unused variable - | -LL | let _unused = must_use_function(); - | ~~~~~~~ -help: consider explicitly droping with `std::mem::drop` - | -LL | let _ = drop(...); - | ~~~~~~~~~ - -warning: 2 warnings emitted - From 321a598b7519733aff7dea8b4ebd3631626d656b Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sun, 5 Jun 2022 01:01:54 -0400 Subject: [PATCH 16/38] Add diagnostic items to MutexGuard and RwLock Guards I forgot to add the diagnostic to the actual types in `std` earlier. --- library/std/src/sync/mutex.rs | 1 + library/std/src/sync/rwlock.rs | 2 ++ src/test/ui/lint/let_underscore/let_underscore_lock.stderr | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index 3d8281fe59389..d976725c2761a 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -193,6 +193,7 @@ unsafe impl Sync for Mutex {} and cause Futures to not implement `Send`"] #[stable(feature = "rust1", since = "1.0.0")] #[clippy::has_significant_drop] +#[cfg_attr(not(test), rustc_diagnostic_item = "MutexGuard")] pub struct MutexGuard<'a, T: ?Sized + 'a> { lock: &'a Mutex, poison: poison::Guard, diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 4f1b4bedaab25..e956f00a12fd3 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -100,6 +100,7 @@ unsafe impl Sync for RwLock {} and cause Futures to not implement `Send`"] #[stable(feature = "rust1", since = "1.0.0")] #[clippy::has_significant_drop] +#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockReadGuard")] pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { lock: &'a RwLock, } @@ -124,6 +125,7 @@ unsafe impl Sync for RwLockReadGuard<'_, T> {} and cause Future's to not implement `Send`"] #[stable(feature = "rust1", since = "1.0.0")] #[clippy::has_significant_drop] +#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockWriteGuard")] pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { lock: &'a RwLock, poison: poison::Guard, diff --git a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr index b7e14e8c7b5c5..7ff42cb152441 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr +++ b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr @@ -1,5 +1,5 @@ error: non-binding let on a synchronization lock - --> $DIR/let_underscore_lock.rs:5:5 + --> $DIR/let_underscore_lock.rs:6:5 | LL | let _ = data.lock().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 211feb106a188fef698bb36d19402808f9930154 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sun, 5 Jun 2022 12:47:19 -0400 Subject: [PATCH 17/38] Add `{{produces}}` tag to lint doc comments. --- compiler/rustc_lint/src/let_underscore.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index dea878c4460b9..520c865cc1922 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -11,7 +11,7 @@ declare_lint! { /// scope. /// /// ### Example - /// ```rust + /// ``` /// struct SomeStruct; /// impl Drop for SomeStruct { /// fn drop(&mut self) { @@ -20,6 +20,7 @@ declare_lint! { /// } /// /// fn main() { + /// #[warn(let_underscore_drop)] /// // SomeStuct is dropped immediately instead of at end of scope, /// // so "Dropping SomeStruct" is printed before "end of main". /// // The order of prints would be reversed if SomeStruct was bound to @@ -28,6 +29,9 @@ declare_lint! { /// println!("end of main"); /// } /// ``` + /// + /// {{produces}} + /// /// ### Explanation /// /// Statements which assign an expression to an underscore causes the @@ -66,6 +70,9 @@ declare_lint! { /// *lock += 1; /// }); /// ``` + /// + /// {{produces}} + /// /// ### Explanation /// /// Statements which assign an expression to an underscore causes the From cdf66060666fa53cbca9647ac7434bdfd2cc37a5 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Thu, 9 Jun 2022 14:03:35 -0400 Subject: [PATCH 18/38] Use `multipart_suggestion` to create an applicable suggestion. The "consider explicitly droping" can now suggest a machine applicable suggestion now. --- compiler/rustc_lint/src/let_underscore.rs | 10 ++++++---- .../ui/lint/let_underscore/let_underscore_drop.stderr | 4 ++-- .../ui/lint/let_underscore/let_underscore_lock.stderr | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 520c865cc1922..18661e8c5059c 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -154,11 +154,13 @@ fn build_and_emit_lint( "_unused", Applicability::MachineApplicable, ) - .span_suggestion_verbose( - init_span, + .multipart_suggestion( "consider explicitly droping with `std::mem::drop`", - "drop(...)", - Applicability::HasPlaceholders, + vec![ + (init_span.shrink_to_lo(), "drop(".to_string()), + (init_span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MachineApplicable, ) .emit(); } diff --git a/src/test/ui/lint/let_underscore/let_underscore_drop.stderr b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr index 5034f682bb76b..dfac6d3f74185 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_drop.stderr +++ b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr @@ -11,8 +11,8 @@ LL | let _unused = NontrivialDrop; | ~~~~~~~ help: consider explicitly droping with `std::mem::drop` | -LL | let _ = drop(...); - | ~~~~~~~~~ +LL | let _ = drop(NontrivialDrop); + | +++++ + warning: 1 warning emitted diff --git a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr index 7ff42cb152441..f37483ddd96d8 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr +++ b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr @@ -11,8 +11,8 @@ LL | let _unused = data.lock().unwrap(); | ~~~~~~~ help: consider explicitly droping with `std::mem::drop` | -LL | let _ = drop(...); - | ~~~~~~~~~ +LL | let _ = drop(data.lock().unwrap()); + | +++++ + error: aborting due to previous error From 7237e8635dc0611a051de8d398759fe7eae90d0a Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 11 Jun 2022 10:19:53 -0400 Subject: [PATCH 19/38] Reword suggestion messages. --- compiler/rustc_lint/src/let_underscore.rs | 4 ++-- src/test/ui/lint/let_underscore/let_underscore_drop.stderr | 4 ++-- src/test/ui/lint/let_underscore/let_underscore_lock.stderr | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 18661e8c5059c..fe0e0511f6b49 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -150,12 +150,12 @@ fn build_and_emit_lint( lint.build(msg) .span_suggestion_verbose( local.pat.span, - "consider binding to an unused variable", + "consider binding to an unused variable to avoid immediately dropping the value", "_unused", Applicability::MachineApplicable, ) .multipart_suggestion( - "consider explicitly droping with `std::mem::drop`", + "consider immediately dropping the value", vec![ (init_span.shrink_to_lo(), "drop(".to_string()), (init_span.shrink_to_hi(), ")".to_string()), diff --git a/src/test/ui/lint/let_underscore/let_underscore_drop.stderr b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr index dfac6d3f74185..b6ff9d1a27cd8 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_drop.stderr +++ b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr @@ -5,11 +5,11 @@ LL | let _ = NontrivialDrop; | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: requested on the command line with `-W let-underscore-drop` -help: consider binding to an unused variable +help: consider binding to an unused variable to avoid immediately dropping the value | LL | let _unused = NontrivialDrop; | ~~~~~~~ -help: consider explicitly droping with `std::mem::drop` +help: consider immediately dropping the value | LL | let _ = drop(NontrivialDrop); | +++++ + diff --git a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr index f37483ddd96d8..1e49b89c5a874 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr +++ b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr @@ -5,11 +5,11 @@ LL | let _ = data.lock().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[deny(let_underscore_lock)]` on by default -help: consider binding to an unused variable +help: consider binding to an unused variable to avoid immediately dropping the value | LL | let _unused = data.lock().unwrap(); | ~~~~~~~ -help: consider explicitly droping with `std::mem::drop` +help: consider immediately dropping the value | LL | let _ = drop(data.lock().unwrap()); | +++++ + From b040666e052a94241d2598b06d5e5dc19c77257b Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 11 Jun 2022 10:36:48 -0400 Subject: [PATCH 20/38] Have the drop code suggestion not include `let _ =` --- compiler/rustc_lint/src/let_underscore.rs | 2 +- src/test/ui/lint/let_underscore/let_underscore_drop.stderr | 4 ++-- src/test/ui/lint/let_underscore/let_underscore_lock.stderr | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index fe0e0511f6b49..2ba79aacace83 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -157,7 +157,7 @@ fn build_and_emit_lint( .multipart_suggestion( "consider immediately dropping the value", vec![ - (init_span.shrink_to_lo(), "drop(".to_string()), + (local.span.until(init_span), "drop(".to_string()), (init_span.shrink_to_hi(), ")".to_string()), ], Applicability::MachineApplicable, diff --git a/src/test/ui/lint/let_underscore/let_underscore_drop.stderr b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr index b6ff9d1a27cd8..cf7b882e946d9 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_drop.stderr +++ b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr @@ -11,8 +11,8 @@ LL | let _unused = NontrivialDrop; | ~~~~~~~ help: consider immediately dropping the value | -LL | let _ = drop(NontrivialDrop); - | +++++ + +LL | drop(NontrivialDrop); + | ~~~~~ + warning: 1 warning emitted diff --git a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr index 1e49b89c5a874..7aa119003b4ba 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr +++ b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr @@ -11,8 +11,8 @@ LL | let _unused = data.lock().unwrap(); | ~~~~~~~ help: consider immediately dropping the value | -LL | let _ = drop(data.lock().unwrap()); - | +++++ + +LL | drop(data.lock().unwrap()); + | ~~~~~ + error: aborting due to previous error From 8807c2d8e512668a6f09ddb14c6742bf28e66816 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Sat, 11 Jun 2022 10:58:04 -0400 Subject: [PATCH 21/38] Make `let_underscore_drop` Deny by default. This is done so that we can check the noisiness of this lint in a Crater run. Note that when I built the compiler, I actually encountered lots of places where this lint will trigger and fail compilation, so I had to also set `RUSTFLAGS_NOT_BOOSTRAP` to `-A let_underscore_drop` when compiling to prevent that. --- compiler/rustc_lint/src/let_underscore.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 2ba79aacace83..d40c83e311f96 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -46,7 +46,7 @@ declare_lint! { /// calling `std::mem::drop` on the expression is clearer and helps convey /// intent. pub LET_UNDERSCORE_DROP, - Allow, + Deny, "non-binding let on a type that implements `Drop`" } From a9095ff2139fb305b15006d1f2a1ff16da0b6c29 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Thu, 16 Jun 2022 21:07:00 -0400 Subject: [PATCH 22/38] Re-allow `let_underscore_drop` by default. This lint is way way too noisy to have it be `Deny` by default. --- compiler/rustc_lint/src/let_underscore.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index d40c83e311f96..2ba79aacace83 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -46,7 +46,7 @@ declare_lint! { /// calling `std::mem::drop` on the expression is clearer and helps convey /// intent. pub LET_UNDERSCORE_DROP, - Deny, + Allow, "non-binding let on a type that implements `Drop`" } From a9f1b7bd2a25e34de29eb88f81550690f4fec5dc Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Thu, 4 Aug 2022 17:00:48 -0400 Subject: [PATCH 23/38] Explain why let-underscoring a lock guard is incorrect. Currently, the let_underscore_lock lint simply tells what is wrong, but not why it is wrong. We fix this by using a `MultiSpan` to explain specifically that doing `let _ = ` immediately drops the lock guard because it does not assign the lock guard to a binding. --- compiler/rustc_lint/src/let_underscore.rs | 13 +++++++++++-- .../lint/let_underscore/let_underscore_lock.stderr | 6 ++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 2ba79aacace83..79d1443dc353c 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -1,5 +1,5 @@ use crate::{LateContext, LateLintPass, LintContext}; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, MultiSpan}; use rustc_hir as hir; use rustc_middle::{lint::LintDiagnosticBuilder, ty}; use rustc_span::Symbol; @@ -119,7 +119,16 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { }; if is_sync_lock { - cx.struct_span_lint(LET_UNDERSCORE_LOCK, local.span, |lint| { + let mut span = MultiSpan::from_spans(vec![local.pat.span, init.span]); + span.push_span_label( + local.pat.span, + "this lock is not assigned to a binding and is immediately dropped".to_string(), + ); + span.push_span_label( + init.span, + "this binding will immediately drop the value assigned to it".to_string(), + ); + cx.struct_span_lint(LET_UNDERSCORE_LOCK, span, |lint| { build_and_emit_lint( lint, local, diff --git a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr index 7aa119003b4ba..fb58af0a42f81 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr +++ b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr @@ -1,8 +1,10 @@ error: non-binding let on a synchronization lock - --> $DIR/let_underscore_lock.rs:6:5 + --> $DIR/let_underscore_lock.rs:6:9 | LL | let _ = data.lock().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ ^^^^^^^^^^^^^^^^^^^^ this binding will immediately drop the value assigned to it + | | + | this lock is not assigned to a binding and is immediately dropped | = note: `#[deny(let_underscore_lock)]` on by default help: consider binding to an unused variable to avoid immediately dropping the value From d355ec94ff0ef409bfa953f715987a98de13fd64 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Thu, 4 Aug 2022 17:31:08 -0400 Subject: [PATCH 24/38] Fix imports. I'm not really sure why this is nessecary to do, but the checks on the PR do not seem to work if do not do this. --- compiler/rustc_lint/src/let_underscore.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 79d1443dc353c..7e885e6c51aad 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -1,7 +1,7 @@ use crate::{LateContext, LateLintPass, LintContext}; -use rustc_errors::{Applicability, MultiSpan}; +use rustc_errors::{Applicability, LintDiagnosticBuilder, MultiSpan}; use rustc_hir as hir; -use rustc_middle::{lint::LintDiagnosticBuilder, ty}; +use rustc_middle::ty; use rustc_span::Symbol; declare_lint! { From 76c90c3015a7e3ad6f0e6b807839ff59f17eba89 Mon Sep 17 00:00:00 2001 From: Aaron Kofsky Date: Fri, 5 Aug 2022 13:20:43 -0400 Subject: [PATCH 25/38] Use `#![warn(let_underscore_drop)]` in tests. --- src/test/ui/lint/let_underscore/let_underscore_drop.rs | 2 +- src/test/ui/lint/let_underscore/let_underscore_drop.stderr | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/test/ui/lint/let_underscore/let_underscore_drop.rs b/src/test/ui/lint/let_underscore/let_underscore_drop.rs index 85ca5dd2880a4..f298871f122d3 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_drop.rs +++ b/src/test/ui/lint/let_underscore/let_underscore_drop.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -W let_underscore_drop +#![warn(let_underscore_drop)] struct NontrivialDrop; diff --git a/src/test/ui/lint/let_underscore/let_underscore_drop.stderr b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr index cf7b882e946d9..7b7de202e4626 100644 --- a/src/test/ui/lint/let_underscore/let_underscore_drop.stderr +++ b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr @@ -4,7 +4,11 @@ warning: non-binding let on a type that implements `Drop` LL | let _ = NontrivialDrop; | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: requested on the command line with `-W let-underscore-drop` +note: the lint level is defined here + --> $DIR/let_underscore_drop.rs:2:9 + | +LL | #![warn(let_underscore_drop)] + | ^^^^^^^^^^^^^^^^^^^ help: consider binding to an unused variable to avoid immediately dropping the value | LL | let _unused = NontrivialDrop; From 38de102cffb7692738ec7940794e59452372d395 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Wed, 20 Jul 2022 21:43:37 -0400 Subject: [PATCH 26/38] Support eager and lazy methods for providing references and values There are times where computing a value may be cheap, or where computing a reference may be expensive, so this fills out the possibilities. --- library/core/src/any.rs | 74 +++++++++++++++++++++++++++++++++++---- library/core/tests/any.rs | 2 +- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/library/core/src/any.rs b/library/core/src/any.rs index e54f6c912d594..3bfb675531e64 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -796,7 +796,7 @@ pub trait Provider { /// impl Provider for SomeConcreteType { /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { /// demand.provide_ref::(&self.field) - /// .provide_value::(|| self.num_field); + /// .provide_value::(self.num_field); /// } /// } /// ``` @@ -881,28 +881,55 @@ impl<'a> Demand<'a> { /// /// # Examples /// + /// Provides an `u8`. + /// + /// ```rust + /// #![feature(provide_any)] + /// + /// use std::any::{Provider, Demand}; + /// # struct SomeConcreteType { field: u8 } + /// + /// impl Provider for SomeConcreteType { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// demand.provide_value::(self.field); + /// } + /// } + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn provide_value(&mut self, value: T) -> &mut Self + where + T: 'static, + { + self.provide::>(value) + } + + /// Provide a value or other type with only static lifetimes computed using a closure. + /// + /// # Examples + /// /// Provides a `String` by cloning. /// /// ```rust - /// # #![feature(provide_any)] + /// #![feature(provide_any)] + /// /// use std::any::{Provider, Demand}; /// # struct SomeConcreteType { field: String } /// /// impl Provider for SomeConcreteType { /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand.provide_value::(|| self.field.clone()); + /// demand.provide_value_with::(|| self.field.clone()); /// } /// } /// ``` #[unstable(feature = "provide_any", issue = "96024")] - pub fn provide_value(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self + pub fn provide_value_with(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self where T: 'static, { self.provide_with::>(fulfil) } - /// Provide a reference, note that the referee type must be bounded by `'static`, + /// Provide a reference. The referee type must be bounded by `'static`, /// but may be unsized. /// /// # Examples @@ -910,7 +937,8 @@ impl<'a> Demand<'a> { /// Provides a reference to a field as a `&str`. /// /// ```rust - /// # #![feature(provide_any)] + /// #![feature(provide_any)] + /// /// use std::any::{Provider, Demand}; /// # struct SomeConcreteType { field: String } /// @@ -925,6 +953,40 @@ impl<'a> Demand<'a> { self.provide::>>(value) } + /// Provide a reference computed using a closure. The referee type + /// must be bounded by `'static`, but may be unsized. + /// + /// # Examples + /// + /// Provides a reference to a field as a `&str`. + /// + /// ```rust + /// #![feature(provide_any)] + /// + /// use std::any::{Provider, Demand}; + /// # struct SomeConcreteType { business: String, party: String } + /// # fn today_is_a_weekday() -> bool { true } + /// + /// impl Provider for SomeConcreteType { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// demand.provide_ref_with::(|| { + /// if today_is_a_weekday() { + /// &self.business + /// } else { + /// &self.party + /// } + /// }); + /// } + /// } + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn provide_ref_with( + &mut self, + fulfil: impl FnOnce() -> &'a T, + ) -> &mut Self { + self.provide_with::>>(fulfil) + } + /// Provide a value with the given `Type` tag. fn provide(&mut self, value: I::Reified) -> &mut Self where diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs index 8ed0c88808fe2..9538b81394957 100644 --- a/library/core/tests/any.rs +++ b/library/core/tests/any.rs @@ -142,7 +142,7 @@ impl Provider for SomeConcreteType { demand .provide_ref::(&self.some_string) .provide_ref::(&self.some_string) - .provide_value::(|| "bye".to_owned()); + .provide_value_with::(|| "bye".to_owned()); } } From 260ec9347838714ad9fa4f7e083bdc0448f4f9be Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 21 Jul 2022 21:39:20 -0400 Subject: [PATCH 27/38] Add `Provider::{would_be_satisfied_by_value_of,would_be_satisfied_by_ref_of}` While the `provide_*` methods already short-circuit when a value has been provided, there are times where an expensive computation is needed to determine if the `provide_*` method can even be called. --- library/core/src/any.rs | 165 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 3bfb675531e64..1a379ecc11c01 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -1008,6 +1008,156 @@ impl<'a> Demand<'a> { } self } + + /// Check if the `Demand` would be satisfied if provided with a + /// value of the specified type. If the type does not match or has + /// already been provided, returns false. + /// + /// # Examples + /// + /// Check if an `u8` still needs to be provided and then provides + /// it. + /// + /// ```rust + /// #![feature(provide_any)] + /// + /// use std::any::{Provider, Demand}; + /// + /// struct Parent(Option); + /// + /// impl Provider for Parent { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// if let Some(v) = self.0 { + /// demand.provide_value::(v); + /// } + /// } + /// } + /// + /// struct Child { + /// parent: Parent, + /// } + /// + /// impl Child { + /// // Pretend that this takes a lot of resources to evaluate. + /// fn an_expensive_computation(&self) -> Option { + /// Some(99) + /// } + /// } + /// + /// impl Provider for Child { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// // In general, we don't know if this call will provide + /// // an `u8` value or not... + /// self.parent.provide(demand); + /// + /// // ...so we check to see if the `u8` is needed before + /// // we run our expensive computation. + /// if demand.would_be_satisfied_by_value_of::() { + /// if let Some(v) = self.an_expensive_computation() { + /// demand.provide_value::(v); + /// } + /// } + /// + /// // The demand will be satisfied now, regardless of if + /// // the parent provided the value or we did. + /// assert!(!demand.would_be_satisfied_by_value_of::()); + /// } + /// } + /// + /// let parent = Parent(Some(42)); + /// let child = Child { parent }; + /// assert_eq!(Some(42), std::any::request_value::(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent }; + /// assert_eq!(Some(99), std::any::request_value::(&child)); + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn would_be_satisfied_by_value_of(&self) -> bool + where + T: 'static, + { + self.would_be_satisfied_by::>() + } + + /// Check if the `Demand` would be satisfied if provided with a + /// reference to a value of the specified type. If the type does + /// not match or has already been provided, returns false. + /// + /// # Examples + /// + /// Check if a `&str` still needs to be provided and then provides + /// it. + /// + /// ```rust + /// #![feature(provide_any)] + /// + /// use std::any::{Provider, Demand}; + /// + /// struct Parent(Option); + /// + /// impl Provider for Parent { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// if let Some(v) = &self.0 { + /// demand.provide_ref::(v); + /// } + /// } + /// } + /// + /// struct Child { + /// parent: Parent, + /// name: String, + /// } + /// + /// impl Child { + /// // Pretend that this takes a lot of resources to evaluate. + /// fn an_expensive_computation(&self) -> Option<&str> { + /// Some(&self.name) + /// } + /// } + /// + /// impl Provider for Child { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// // In general, we don't know if this call will provide + /// // a `str` reference or not... + /// self.parent.provide(demand); + /// + /// // ...so we check to see if the `&str` is needed before + /// // we run our expensive computation. + /// if demand.would_be_satisfied_by_ref_of::() { + /// if let Some(v) = self.an_expensive_computation() { + /// demand.provide_ref::(v); + /// } + /// } + /// + /// // The demand will be satisfied now, regardless of if + /// // the parent provided the reference or we did. + /// assert!(!demand.would_be_satisfied_by_ref_of::()); + /// } + /// } + /// + /// let parent = Parent(Some("parent".into())); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("parent"), std::any::request_ref::(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("child"), std::any::request_ref::(&child)); + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn would_be_satisfied_by_ref_of(&self) -> bool + where + T: ?Sized + 'static, + { + self.would_be_satisfied_by::>>() + } + + fn would_be_satisfied_by(&self) -> bool + where + I: tags::Type<'a>, + { + matches!(self.0.downcast::(), Some(TaggedOption(None))) + } } #[unstable(feature = "provide_any", issue = "96024")] @@ -1112,6 +1262,21 @@ impl<'a> dyn Erased<'a> + 'a { /// Returns some reference to the dynamic value if it is tagged with `I`, /// or `None` otherwise. #[inline] + fn downcast(&self) -> Option<&TaggedOption<'a, I>> + where + I: tags::Type<'a>, + { + if self.tag_id() == TypeId::of::() { + // SAFETY: Just checked whether we're pointing to an I. + Some(unsafe { &*(self as *const Self).cast::>() }) + } else { + None + } + } + + /// Returns some mutable reference to the dynamic value if it is tagged with `I`, + /// or `None` otherwise. + #[inline] fn downcast_mut(&mut self) -> Option<&mut TaggedOption<'a, I>> where I: tags::Type<'a>, From 10804672c221882cfd1c94809ad09846a35fe49d Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Sun, 14 Aug 2022 17:04:30 +0300 Subject: [PATCH 28/38] access_levels.rs refactor --- compiler/rustc_resolve/src/access_levels.rs | 158 +++++++------------- compiler/rustc_resolve/src/imports.rs | 27 ++-- compiler/rustc_resolve/src/lib.rs | 18 +++ 3 files changed, 80 insertions(+), 123 deletions(-) diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs index 3fba923d9fdf4..c98f7f0ccef44 100644 --- a/compiler/rustc_resolve/src/access_levels.rs +++ b/compiler/rustc_resolve/src/access_levels.rs @@ -1,25 +1,21 @@ +use crate::imports::ImportKind; +use crate::NameBinding; +use crate::NameBindingKind; +use crate::Resolver; use rustc_ast::ast; use rustc_ast::visit; use rustc_ast::visit::Visitor; use rustc_ast::Crate; use rustc_ast::EnumDef; -use rustc_ast::ForeignMod; use rustc_ast::NodeId; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::middle::privacy::AccessLevel; -use rustc_middle::ty::Visibility; +use rustc_middle::ty::DefIdTree; use rustc_span::sym; -use crate::imports::ImportKind; -use crate::BindingKey; -use crate::NameBinding; -use crate::NameBindingKind; -use crate::Resolver; - pub struct AccessLevelsVisitor<'r, 'a> { r: &'r mut Resolver<'a>, - prev_level: Option, changed: bool, } @@ -28,11 +24,10 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we /// need access to a TyCtxt for that. pub fn compute_access_levels<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) { - let mut visitor = - AccessLevelsVisitor { r, changed: false, prev_level: Some(AccessLevel::Public) }; + let mut visitor = AccessLevelsVisitor { r, changed: false }; visitor.set_access_level_def_id(CRATE_DEF_ID, Some(AccessLevel::Public)); - visitor.set_exports_access_level(CRATE_DEF_ID); + visitor.set_bindings_access_level(CRATE_DEF_ID); while visitor.changed { visitor.reset(); @@ -44,15 +39,17 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { fn reset(&mut self) { self.changed = false; - self.prev_level = Some(AccessLevel::Public); } - /// Update the access level of the exports of the given module accordingly. The module access + /// Update the access level of the bindings in the given module accordingly. The module access /// level has to be Exported or Public. /// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level). - fn set_exports_access_level(&mut self, module_id: LocalDefId) { + fn set_bindings_access_level(&mut self, module_id: LocalDefId) { assert!(self.r.module_map.contains_key(&&module_id.to_def_id())); - + let module_level = self.r.access_levels.map.get(&module_id).copied(); + if !module_level.is_some() { + return; + } // Set the given binding access level to `AccessLevel::Public` and // sets the rest of the `use` chain to `AccessLevel::Exported` until // we hit the actual exported item. @@ -72,28 +69,20 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { } }; - let module_level = self.r.access_levels.map.get(&module_id).copied(); - assert!(module_level >= Some(AccessLevel::Exported)); - - if let Some(exports) = self.r.reexport_map.get(&module_id) { - let pub_exports = exports - .iter() - .filter(|ex| ex.vis == Visibility::Public) - .cloned() - .collect::>(); - - let module = self.r.get_module(module_id.to_def_id()).unwrap(); - for export in pub_exports.into_iter() { - if let Some(export_def_id) = export.res.opt_def_id().and_then(|id| id.as_local()) { - self.set_access_level_def_id(export_def_id, Some(AccessLevel::Exported)); - } - - if let Some(ns) = export.res.ns() { - let key = BindingKey { ident: export.ident, ns, disambiguator: 0 }; - let name_res = self.r.resolution(module, key); - if let Some(binding) = name_res.borrow().binding() { - set_import_binding_access_level(self, binding, module_level) - } + let module = self.r.get_module(module_id.to_def_id()).unwrap(); + let resolutions = self.r.resolutions(module); + + for (.., name_resolution) in resolutions.borrow().iter() { + if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() { + let access_level = match binding.is_import() { + true => { + set_import_binding_access_level(self, binding, module_level); + Some(AccessLevel::Exported) + }, + false => module_level, + }; + if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) { + self.set_access_level_def_id(def_id, access_level); } } } @@ -127,97 +116,59 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { fn visit_item(&mut self, item: &'ast ast::Item) { - let inherited_item_level = match item.kind { + let def_id = self.r.local_def_id(item.id); + // Set access level of nested items. + // If it's a mod, also make the visitor walk all of its items + match item.kind { // Resolved in rustc_privacy when types are available ast::ItemKind::Impl(..) => return, - // Only exported `macro_rules!` items are public, but they always are - ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => { - let is_macro_export = - item.attrs.iter().any(|attr| attr.has_name(sym::macro_export)); - if is_macro_export { Some(AccessLevel::Public) } else { None } - } - - // Foreign modules inherit level from parents. - ast::ItemKind::ForeignMod(..) => self.prev_level, - - // Other `pub` items inherit levels from parents. - ast::ItemKind::ExternCrate(..) - | ast::ItemKind::Use(..) - | ast::ItemKind::Static(..) - | ast::ItemKind::Const(..) - | ast::ItemKind::Fn(..) - | ast::ItemKind::Mod(..) - | ast::ItemKind::GlobalAsm(..) - | ast::ItemKind::TyAlias(..) - | ast::ItemKind::Enum(..) - | ast::ItemKind::Struct(..) - | ast::ItemKind::Union(..) - | ast::ItemKind::Trait(..) - | ast::ItemKind::TraitAlias(..) - | ast::ItemKind::MacroDef(..) => { - if item.vis.kind.is_pub() { - self.prev_level - } else { - None - } - } - // Should be unreachable at this stage ast::ItemKind::MacCall(..) => panic!( "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage" ), - }; - let access_level = self.set_access_level(item.id, inherited_item_level); + // Foreign modules inherit level from parents. + ast::ItemKind::ForeignMod(..) => { + let parent_level = + self.r.access_levels.map.get(&self.r.local_parent(def_id)).copied(); + self.set_access_level(item.id, parent_level); + } - // Set access level of nested items. - // If it's a mod, also make the visitor walk all of its items - match item.kind { - ast::ItemKind::Mod(..) => { - if access_level.is_some() { - self.set_exports_access_level(self.r.local_def_id(item.id)); + // Only exported `macro_rules!` items are public, but they always are + ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => { + if item.attrs.iter().any(|attr| attr.has_name(sym::macro_export)) { + self.set_access_level(item.id, Some(AccessLevel::Public)); } + } - let orig_level = std::mem::replace(&mut self.prev_level, access_level); + ast::ItemKind::Mod(..) => { + self.set_bindings_access_level(def_id); visit::walk_item(self, item); - self.prev_level = orig_level; } - ast::ItemKind::ForeignMod(ForeignMod { ref items, .. }) => { - for nested in items { - if nested.vis.kind.is_pub() { - self.set_access_level(nested.id, access_level); - } - } - } ast::ItemKind::Enum(EnumDef { ref variants }, _) => { + self.set_bindings_access_level(def_id); for variant in variants { - let variant_level = self.set_access_level(variant.id, access_level); - if let Some(ctor_id) = variant.data.ctor_id() { - self.set_access_level(ctor_id, access_level); - } - + let variant_def_id = self.r.local_def_id(variant.id); + let variant_level = self.r.access_levels.map.get(&variant_def_id).copied(); for field in variant.data.fields() { self.set_access_level(field.id, variant_level); } } } - ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => { - if let Some(ctor_id) = def.ctor_id() { - self.set_access_level(ctor_id, access_level); - } + ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => { + let inherited_level = self.r.access_levels.map.get(&def_id).copied(); for field in def.fields() { if field.vis.kind.is_pub() { - self.set_access_level(field.id, access_level); + self.set_access_level(field.id, inherited_level); } } } - ast::ItemKind::Trait(ref trait_kind) => { - for nested in trait_kind.items.iter() { - self.set_access_level(nested.id, access_level); - } + + ast::ItemKind::Trait(..) => { + self.set_bindings_access_level(def_id); } ast::ItemKind::ExternCrate(..) @@ -229,9 +180,6 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { | ast::ItemKind::TraitAlias(..) | ast::ItemKind::MacroDef(..) | ast::ItemKind::Fn(..) => return, - - // Unreachable kinds - ast::ItemKind::Impl(..) | ast::ItemKind::MacCall(..) => unreachable!(), } } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index c2491c6ebdec0..9a2c39fab72fd 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1135,24 +1135,15 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if let Some(def_id) = module.opt_def_id() { let mut reexports = Vec::new(); - module.for_each_child(self.r, |_, ident, _, binding| { - // FIXME: Consider changing the binding inserted by `#[macro_export] macro_rules` - // into the crate root to actual `NameBindingKind::Import`. - if binding.is_import() - || matches!(binding.kind, NameBindingKind::Res(_, _is_macro_export @ true)) - { - let res = binding.res().expect_non_local(); - // Ambiguous imports are treated as errors at this point and are - // not exposed to other crates (see #36837 for more details). - if res != def::Res::Err && !binding.is_ambiguity() { - reexports.push(ModChild { - ident, - res, - vis: binding.vis, - span: binding.span, - macro_rules: false, - }); - } + module.for_each_child(self.r, |this, ident, _, binding| { + if let Some(res) = this.is_reexport(binding) { + reexports.push(ModChild { + ident, + res, + vis: binding.vis, + span: binding.span, + macro_rules: false, + }); } }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 66090c96d1ee2..74f73bbd85cd3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2021,6 +2021,24 @@ impl<'a> Resolver<'a> { } self.main_def = Some(MainDefinition { res, is_import, span }); } + + // Items that go to reexport table encoded to metadata and visible through it to other crates. + fn is_reexport(&self, binding: &NameBinding<'a>) -> Option> { + // FIXME: Consider changing the binding inserted by `#[macro_export] macro_rules` + // into the crate root to actual `NameBindingKind::Import`. + if binding.is_import() + || matches!(binding.kind, NameBindingKind::Res(_, _is_macro_export @ true)) + { + let res = binding.res().expect_non_local(); + // Ambiguous imports are treated as errors at this point and are + // not exposed to other crates (see #36837 for more details). + if res != def::Res::Err && !binding.is_ambiguity() { + return Some(res); + } + } + + return None; + } } fn names_to_string(names: &[Symbol]) -> String { From 0111fb00dac90d67f8d770ca2a25923cfd24e25d Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Sun, 14 Aug 2022 17:05:17 +0300 Subject: [PATCH 29/38] add TestReachabilityVisitor --- .../locales/en-US/privacy.ftl | 2 + compiler/rustc_feature/src/builtin_attrs.rs | 1 + compiler/rustc_privacy/src/errors.rs | 8 ++ compiler/rustc_privacy/src/lib.rs | 62 ++++++++- compiler/rustc_span/src/symbol.rs | 1 + src/test/ui/privacy/access_levels.rs | 49 +++++++ src/test/ui/privacy/access_levels.stderr | 125 ++++++++++++++++++ 7 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/privacy/access_levels.rs create mode 100644 src/test/ui/privacy/access_levels.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/privacy.ftl b/compiler/rustc_error_messages/locales/en-US/privacy.ftl index 223092a74bd97..da987152ff660 100644 --- a/compiler/rustc_error_messages/locales/en-US/privacy.ftl +++ b/compiler/rustc_error_messages/locales/en-US/privacy.ftl @@ -11,6 +11,8 @@ privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interfac .label = can't leak {$vis_descr} {$kind} .visibility_label = `{$descr}` declared as {$vis_descr} +privacy_report_access_level = {$descr} + privacy_from_private_dep_in_public_interface = {$kind} `{$descr}` from private dependency '{$krate}' in public interface diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 0487270b52a9a..0c88379d49899 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -758,6 +758,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Testing: // ========================================================================== + rustc_attr!(TEST, rustc_access_level, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing), diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index 1e423ddb7102c..63f83f8965ec5 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -75,6 +75,14 @@ pub struct InPublicInterface<'a> { pub vis_span: Span, } +#[derive(SessionDiagnostic)] +#[diag(privacy::report_access_level)] +pub struct ReportAccessLevel { + #[primary_span] + pub span: Span, + pub descr: String, +} + #[derive(LintDiagnostic)] #[diag(privacy::from_private_dep_in_public_interface)] pub struct FromPrivateDependencyInPublicInterface<'a> { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 5d562f18a8158..075a1411f02b4 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -30,7 +30,7 @@ use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind}; use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_session::lint; use rustc_span::hygiene::Transparency; -use rustc_span::symbol::{kw, Ident}; +use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; use std::marker::PhantomData; @@ -39,7 +39,8 @@ use std::{cmp, fmt, mem}; use errors::{ FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface, - InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, UnnamedItemIsPrivate, + InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportAccessLevel, + UnnamedItemIsPrivate, }; //////////////////////////////////////////////////////////////////////////////// @@ -904,6 +905,60 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> } } +//////////////////////////////////////////////////////////////////////////////// +/// Visitor, used for AccessLevels table checking +//////////////////////////////////////////////////////////////////////////////// +pub struct TestReachabilityVisitor<'tcx, 'a> { + tcx: TyCtxt<'tcx>, + access_levels: &'a AccessLevels, +} + +impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { + fn access_level_diagnostic(&mut self, def_id: LocalDefId) { + if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_access_level) { + let access_level = format!("{:?}", self.access_levels.map.get(&def_id)); + let span = self.tcx.def_span(def_id.to_def_id()); + self.tcx.sess.emit_err(ReportAccessLevel { span, descr: access_level }); + } + } +} + +impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { + fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + self.access_level_diagnostic(item.def_id); + + match item.kind { + hir::ItemKind::Enum(ref def, _) => { + for variant in def.variants.iter() { + let variant_id = self.tcx.hir().local_def_id(variant.id); + self.access_level_diagnostic(variant_id); + for field in variant.data.fields() { + let def_id = self.tcx.hir().local_def_id(field.hir_id); + self.access_level_diagnostic(def_id); + } + } + } + hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { + for field in def.fields() { + let def_id = self.tcx.hir().local_def_id(field.hir_id); + self.access_level_diagnostic(def_id); + } + } + _ => {} + } + } + + fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) { + self.access_level_diagnostic(item.def_id); + } + fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) { + self.access_level_diagnostic(item.def_id); + } + fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { + self.access_level_diagnostic(item.def_id); + } +} + ////////////////////////////////////////////////////////////////////////////////////// /// Name privacy visitor, checks privacy and reports violations. /// Most of name privacy checks are performed during the main resolution phase, @@ -2042,6 +2097,9 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { } } + let mut check_visitor = TestReachabilityVisitor { tcx, access_levels: &visitor.access_levels }; + tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor); + tcx.arena.alloc(visitor.access_levels) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6eca7dc52b26a..f854395ff8149 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1206,6 +1206,7 @@ symbols! { rust_eh_unregister_frames, rust_oom, rustc, + rustc_access_level, rustc_allocator, rustc_allocator_nounwind, rustc_allocator_zeroed, diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs new file mode 100644 index 0000000000000..d51d2b57267b6 --- /dev/null +++ b/src/test/ui/privacy/access_levels.rs @@ -0,0 +1,49 @@ +#![feature(rustc_attrs)] + +#[rustc_access_level] mod outer { //~ ERROR None + #[rustc_access_level] pub mod inner { //~ ERROR Some(Exported) + #[rustc_access_level] + extern "C" { //~ ERROR Some(Exported) + #[rustc_access_level] static a: u8; //~ ERROR None + #[rustc_access_level] pub fn b(); //~ ERROR Some(Exported) + } + #[rustc_access_level] + pub trait Trait { //~ ERROR Some(Exported) + #[rustc_access_level] const A: i32; //~ ERROR Some(Exported) + #[rustc_access_level] type B; //~ ERROR Some(Exported) + } + + #[rustc_access_level] + pub struct Struct { //~ ERROR Some(Exported) + #[rustc_access_level] a: u8, //~ ERROR None + #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported) + } + + #[rustc_access_level] + pub union Union { //~ ERROR Some(Exported) + #[rustc_access_level] a: u8, //~ ERROR None + #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported) + } + + #[rustc_access_level] + pub enum Enum { //~ ERROR Some(Exported) + #[rustc_access_level] A( //~ ERROR Some(Exported) + #[rustc_access_level] Struct, //~ ERROR Some(Exported) + #[rustc_access_level] Union, //~ ERROR Some(Exported) + ), + } + } + + #[rustc_access_level] macro_rules! none_macro { //~ ERROR None + () => {}; + } + + #[macro_export] + #[rustc_access_level] macro_rules! public_macro { //~ ERROR Some(Public) + () => {}; + } +} + +pub use outer::inner; + +fn main() {} diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr new file mode 100644 index 0000000000000..f326293c384a5 --- /dev/null +++ b/src/test/ui/privacy/access_levels.stderr @@ -0,0 +1,125 @@ +error: None + --> $DIR/access_levels.rs:3:23 + | +LL | #[rustc_access_level] mod outer { + | ^^^^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:4:27 + | +LL | #[rustc_access_level] pub mod inner { + | ^^^^^^^^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:6:9 + | +LL | / extern "C" { +LL | | #[rustc_access_level] static a: u8; +LL | | #[rustc_access_level] pub fn b(); +LL | | } + | |_________^ + +error: Some(Exported) + --> $DIR/access_levels.rs:11:9 + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:17:9 + | +LL | pub struct Struct { + | ^^^^^^^^^^^^^^^^^ + +error: None + --> $DIR/access_levels.rs:18:35 + | +LL | #[rustc_access_level] a: u8, + | ^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:19:35 + | +LL | #[rustc_access_level] pub b: u8, + | ^^^^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:23:9 + | +LL | pub union Union { + | ^^^^^^^^^^^^^^^ + +error: None + --> $DIR/access_levels.rs:24:35 + | +LL | #[rustc_access_level] a: u8, + | ^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:25:35 + | +LL | #[rustc_access_level] pub b: u8, + | ^^^^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:29:9 + | +LL | pub enum Enum { + | ^^^^^^^^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:30:35 + | +LL | #[rustc_access_level] A( + | ^ + +error: Some(Exported) + --> $DIR/access_levels.rs:31:39 + | +LL | #[rustc_access_level] Struct, + | ^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:32:39 + | +LL | #[rustc_access_level] Union, + | ^^^^^ + +error: None + --> $DIR/access_levels.rs:37:27 + | +LL | #[rustc_access_level] macro_rules! none_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: Some(Public) + --> $DIR/access_levels.rs:42:27 + | +LL | #[rustc_access_level] macro_rules! public_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:12:35 + | +LL | #[rustc_access_level] const A: i32; + | ^^^^^^^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:13:35 + | +LL | #[rustc_access_level] type B; + | ^^^^^^ + +error: None + --> $DIR/access_levels.rs:7:35 + | +LL | #[rustc_access_level] static a: u8; + | ^^^^^^^^^^^^ + +error: Some(Exported) + --> $DIR/access_levels.rs:8:35 + | +LL | #[rustc_access_level] pub fn b(); + | ^^^^^^^^^^ + +error: aborting due to 20 previous errors + From 117169799ffb6df9a86f4d3e933968274022bdd3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 29 Aug 2022 18:05:21 +0200 Subject: [PATCH 30/38] Generate error index with mdbook instead of raw HTML pages --- Cargo.lock | 2 +- src/bootstrap/doc.rs | 2 +- src/tools/error_index_generator/Cargo.toml | 2 +- .../error_index_generator/book_config.toml | 19 ++ .../error_index_generator/error-index.css | 38 +++ .../error_index_generator/error-index.js | 9 + src/tools/error_index_generator/main.rs | 273 +++++++++--------- src/tools/error_index_generator/redirect.js | 10 + 8 files changed, 214 insertions(+), 141 deletions(-) create mode 100644 src/tools/error_index_generator/book_config.toml create mode 100644 src/tools/error_index_generator/error-index.css create mode 100644 src/tools/error_index_generator/error-index.js create mode 100644 src/tools/error_index_generator/redirect.js diff --git a/Cargo.lock b/Cargo.lock index 7c3879fdd98d4..8dff674a630ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1268,7 +1268,7 @@ dependencies = [ name = "error_index_generator" version = "0.0.0" dependencies = [ - "rustdoc", + "mdbook", ] [[package]] diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 2852442d0be6f..f909ecc0ab858 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -793,7 +793,7 @@ impl Step for ErrorIndex { t!(fs::create_dir_all(&out)); let mut index = tool::ErrorIndex::command(builder); index.arg("html"); - index.arg(out.join("error-index.html")); + index.arg(out); index.arg(&builder.version); builder.run(&mut index); diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml index b9fd852f742cf..f4dac6e947e32 100644 --- a/src/tools/error_index_generator/Cargo.toml +++ b/src/tools/error_index_generator/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" edition = "2021" [dependencies] -rustdoc = { path = "../../librustdoc" } +mdbook = { version = "0.4", default-features = false, features = ["search"] } [[bin]] name = "error_index_generator" diff --git a/src/tools/error_index_generator/book_config.toml b/src/tools/error_index_generator/book_config.toml new file mode 100644 index 0000000000000..885100ae3a449 --- /dev/null +++ b/src/tools/error_index_generator/book_config.toml @@ -0,0 +1,19 @@ +[book] +title = "Error codes index" +description = "Book listing all Rust error codes" +src = "" + +[output.html] +git-repository-url = "https://github.com/rust-lang/rust/" +additional-css = ["error-index.css"] +additional-js = ["error-index.js"] + +[output.html.search] +enable = true +limit-results = 20 +use-boolean-and = true +boost-title = 2 +boost-hierarchy = 2 +boost-paragraph = 1 +expand = true +heading-split-level = 0 diff --git a/src/tools/error_index_generator/error-index.css b/src/tools/error_index_generator/error-index.css new file mode 100644 index 0000000000000..8975af82de03b --- /dev/null +++ b/src/tools/error_index_generator/error-index.css @@ -0,0 +1,38 @@ +code.compile_fail { + border-left: 2px solid red; +} + +pre .tooltip { + position: absolute; + left: -25px; + top: 0; + z-index: 1; + color: red; + cursor: pointer; +} +pre .tooltip::after { + display: none; + content: "This example deliberately fails to compile"; + background-color: #000; + color: #fff; + border-color: #000; + text-align: center; + padding: 5px 3px 3px 3px; + border-radius: 6px; + margin-left: 5px; +} +pre .tooltip::before { + display: none; + border-color: transparent black transparent transparent; + content: " "; + position: absolute; + top: 50%; + left: 16px; + margin-top: -5px; + border-width: 5px; + border-style: solid; +} + +pre .tooltip:hover::before, pre .tooltip:hover::after { + display: inline; +} diff --git a/src/tools/error_index_generator/error-index.js b/src/tools/error_index_generator/error-index.js new file mode 100644 index 0000000000000..39b371be04b95 --- /dev/null +++ b/src/tools/error_index_generator/error-index.js @@ -0,0 +1,9 @@ +for (const elem of document.querySelectorAll("pre.playground")) { + if (elem.querySelector(".compile_fail") === null) { + continue; + } + const child = document.createElement("div"); + child.className = "tooltip"; + child.textContent = "ⓘ"; + elem.appendChild(child); +} diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 68c46700361a8..5451e45b28be0 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -1,20 +1,21 @@ #![feature(rustc_private)] extern crate rustc_driver; -extern crate rustc_span; +// We use the function we generate from `register_diagnostics!`. use crate::error_codes::error_codes; use std::env; use std::error::Error; -use std::fs::{create_dir_all, File}; +use std::fs::{self, create_dir_all, File}; use std::io::Write; use std::path::Path; use std::path::PathBuf; -use rustc_span::edition::DEFAULT_EDITION; +use std::str::FromStr; -use rustdoc::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground}; +use mdbook::book::{parse_summary, BookItem, Chapter}; +use mdbook::{Config, MDBook}; macro_rules! register_diagnostics { ($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => { @@ -33,104 +34,21 @@ macro_rules! register_diagnostics { mod error_codes; enum OutputFormat { - HTML(HTMLFormatter), + HTML, Markdown, Unknown(String), } impl OutputFormat { - fn from(format: &str, resource_suffix: &str) -> OutputFormat { + fn from(format: &str) -> OutputFormat { match &*format.to_lowercase() { - "html" => OutputFormat::HTML(HTMLFormatter(resource_suffix.to_owned())), + "html" => OutputFormat::HTML, "markdown" => OutputFormat::Markdown, s => OutputFormat::Unknown(s.to_owned()), } } } -struct HTMLFormatter(String); - -impl HTMLFormatter { - fn create_error_code_file( - &self, - err_code: &str, - explanation: &str, - parent_dir: &Path, - ) -> Result<(), Box> { - let mut output_file = File::create(parent_dir.join(err_code).with_extension("html"))?; - - self.header(&mut output_file, "../", "")?; - self.title(&mut output_file, &format!("Error code {}", err_code))?; - - let mut id_map = IdMap::new(); - let playground = - Playground { crate_name: None, url: String::from("https://play.rust-lang.org/") }; - write!( - output_file, - "{}", - Markdown { - content: explanation, - links: &[], - ids: &mut id_map, - error_codes: ErrorCodes::Yes, - edition: DEFAULT_EDITION, - playground: &Some(playground), - heading_offset: HeadingOffset::H1, - } - .into_string() - )?; - write!( - output_file, - "

\ - Back to list of error codes\ -

", - )?; - - self.footer(&mut output_file) - } - - fn header( - &self, - output: &mut dyn Write, - extra_path: &str, - extra: &str, - ) -> Result<(), Box> { - write!( - output, - r##" - - -Rust Compiler Error Index - - - - - -{extra} - - -"##, - suffix = self.0, - )?; - Ok(()) - } - - fn title(&self, output: &mut dyn Write, title: &str) -> Result<(), Box> { - write!(output, "

{}

\n", title)?; - Ok(()) - } - - fn footer(&self, output: &mut dyn Write) -> Result<(), Box> { - write!(output, "")?; - Ok(()) - } -} - /// Output an HTML page for the errors in `err_map` to `output_path`. fn render_markdown(output_path: &Path) -> Result<(), Box> { let mut output_file = File::create(output_path)?; @@ -147,61 +65,144 @@ fn render_markdown(output_path: &Path) -> Result<(), Box> { Ok(()) } -fn render_html(output_path: &Path, formatter: HTMLFormatter) -> Result<(), Box> { - let mut output_file = File::create(output_path)?; +fn move_folder(source: &Path, target: &Path) -> Result<(), Box> { + let entries = + fs::read_dir(source)?.map(|res| res.map(|e| e.path())).collect::, _>>()?; - let error_codes_dir = "error_codes"; + for entry in entries { + let file_name = entry.file_name().expect("file_name() failed").to_os_string(); + let output = target.join(file_name); + if entry.is_file() { + fs::rename(entry, output)?; + } else { + if !output.exists() { + create_dir_all(&output)?; + } + move_folder(&entry, &output)?; + } + } + + fs::remove_dir(&source)?; + + Ok(()) +} - let parent = output_path.parent().expect("There should have a parent").join(error_codes_dir); +fn render_html(output_path: &Path) -> Result<(), Box> { + // We need to render into a temporary folder to prevent `mdbook` from removing everything + // in the output folder (including other completely unrelated things). + let tmp_output = output_path.join("tmp"); - if !parent.exists() { - create_dir_all(&parent)?; + if !tmp_output.exists() { + create_dir_all(&tmp_output)?; } - formatter.header( - &mut output_file, - "", - &format!( - r#""# - ), - )?; - formatter.title(&mut output_file, "Rust Compiler Error Index")?; + render_html_inner(&tmp_output)?; - write!( - output_file, - "

This page lists all the error codes emitted by the Rust compiler. If you want a full \ - explanation on an error code, click on it.

\ -
    ", - )?; - for (err_code, explanation) in error_codes().iter() { + move_folder(&tmp_output, output_path)?; + + Ok(()) +} + +// By default, mdbook doesn't consider code blocks as Rust ones contrary to rustdoc so we have +// to manually add `rust` attribute whenever needed. +fn add_rust_attribute_on_codeblock(explanation: &str) -> String { + // Very hacky way to add the rust attribute on all code blocks. + let mut skip = true; + explanation.split("\n```").fold(String::new(), |mut acc, part| { + if !acc.is_empty() { + acc.push_str("\n```"); + } + if !skip { + if let Some(attrs) = part.split('\n').next() { + if !attrs.contains("rust") + && (attrs.is_empty() + || attrs.contains("compile_fail") + || attrs.contains("ignore") + || attrs.contains("edition")) + { + if !attrs.is_empty() { + acc.push_str("rust,"); + } else { + acc.push_str("rust"); + } + } + } + } + skip = !skip; + acc.push_str(part); + acc + }) +} + +fn render_html_inner(output_path: &Path) -> Result<(), Box> { + // We need to have a little difference between `summary` and `introduction` because the "draft" + // chapters (the ones looking like `[a]()`) are not handled correctly when being put into a + // `Chapter` directly: they generate a link whereas they shouldn't. + let mut introduction = format!( + " +# Rust error codes index + +This page lists all the error codes emitted by the Rust compiler. + +", + include_str!("redirect.js") + ); + + let err_codes = error_codes(); + let mut chapters = Vec::with_capacity(err_codes.len()); + + for (err_code, explanation) in err_codes.iter() { if let Some(explanation) = explanation { - write!( - output_file, - "
  • {1}
  • ", - error_codes_dir, err_code - )?; - formatter.create_error_code_file(err_code, explanation, &parent)?; + introduction.push_str(&format!(" * [{0}](./error_codes/{0}.html)\n", err_code)); + + let content = add_rust_attribute_on_codeblock(explanation); + chapters.push(BookItem::Chapter(Chapter { + name: err_code.to_string(), + content: format!("# Error code {}\n\n{}\n", err_code, content), + number: None, + sub_items: Vec::new(), + // We generate it into the `error_codes` folder. + path: Some(PathBuf::from(&format!("error_codes/{}.html", err_code))), + source_path: None, + parent_names: Vec::new(), + })); } else { - write!(output_file, "
  • {}
  • ", err_code)?; + introduction.push_str(&format!(" * {}\n", err_code)); } } - write!(output_file, "
")?; - formatter.footer(&mut output_file) + + let mut config = Config::from_str(include_str!("book_config.toml"))?; + config.build.build_dir = output_path.to_path_buf(); + let mut book = MDBook::load_with_config_and_summary( + env!("CARGO_MANIFEST_DIR"), + config, + parse_summary("")?, + )?; + let chapter = Chapter { + name: "Rust error codes index".to_owned(), + content: introduction, + number: None, + sub_items: chapters, + // Very important: this file is named as `error-index.html` and not `index.html`! + path: Some(PathBuf::from("error-index.html")), + source_path: None, + parent_names: Vec::new(), + }; + book.book.sections.push(BookItem::Chapter(chapter)); + book.build()?; + + // We don't need this file since it's handled by doc.rust-lang.org directly. + let _ = fs::remove_file(output_path.join("404.html")); + // We don't want this file either because it would overwrite the already existing `index.html`. + let _ = fs::remove_file(output_path.join("index.html")); + + Ok(()) } fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box> { match format { OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s), - OutputFormat::HTML(h) => render_html(dst, h), + OutputFormat::HTML => render_html(dst), OutputFormat::Markdown => render_markdown(dst), } } @@ -210,12 +211,9 @@ fn parse_args() -> (OutputFormat, PathBuf) { let mut args = env::args().skip(1); let format = args.next(); let dst = args.next(); - let resource_suffix = args.next().unwrap_or_else(String::new); - let format = format - .map(|a| OutputFormat::from(&a, &resource_suffix)) - .unwrap_or(OutputFormat::from("html", &resource_suffix)); + let format = format.map(|a| OutputFormat::from(&a)).unwrap_or(OutputFormat::from("html")); let dst = dst.map(PathBuf::from).unwrap_or_else(|| match format { - OutputFormat::HTML(..) => PathBuf::from("doc/error-index.html"), + OutputFormat::HTML => PathBuf::from("doc"), OutputFormat::Markdown => PathBuf::from("doc/error-index.md"), OutputFormat::Unknown(..) => PathBuf::from(""), }); @@ -225,9 +223,8 @@ fn parse_args() -> (OutputFormat, PathBuf) { fn main() { rustc_driver::init_env_logger("RUST_LOG"); let (format, dst) = parse_args(); - let result = - rustc_span::create_default_session_globals_then(move || main_with_result(format, &dst)); + let result = main_with_result(format, &dst); if let Err(e) = result { - panic!("{}", e.to_string()); + panic!("{:?}", e); } } diff --git a/src/tools/error_index_generator/redirect.js b/src/tools/error_index_generator/redirect.js new file mode 100644 index 0000000000000..e6e910658e483 --- /dev/null +++ b/src/tools/error_index_generator/redirect.js @@ -0,0 +1,10 @@ +(function() {{ + if (window.location.hash) {{ + let code = window.location.hash.replace(/^#/, ''); + // We have to make sure this pattern matches to avoid inadvertently creating an + // open redirect. + if (/^E[0-9]+$/.test(code)) {{ + window.location = './error_codes/' + code + '.html'; + }} + }} +}})() From f5857d5c5e1d2fde302f330d11c5cdea8005eb2a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 31 Aug 2022 21:00:05 +0200 Subject: [PATCH 31/38] Move error code book into a sub folder --- src/tools/error_index_generator/main.rs | 81 +++++++-------------- src/tools/error_index_generator/redirect.js | 18 +++-- 2 files changed, 40 insertions(+), 59 deletions(-) diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 5451e45b28be0..1bde8e007826d 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -7,7 +7,7 @@ use crate::error_codes::error_codes; use std::env; use std::error::Error; -use std::fs::{self, create_dir_all, File}; +use std::fs::{self, File}; use std::io::Write; use std::path::Path; use std::path::PathBuf; @@ -65,44 +65,6 @@ fn render_markdown(output_path: &Path) -> Result<(), Box> { Ok(()) } -fn move_folder(source: &Path, target: &Path) -> Result<(), Box> { - let entries = - fs::read_dir(source)?.map(|res| res.map(|e| e.path())).collect::, _>>()?; - - for entry in entries { - let file_name = entry.file_name().expect("file_name() failed").to_os_string(); - let output = target.join(file_name); - if entry.is_file() { - fs::rename(entry, output)?; - } else { - if !output.exists() { - create_dir_all(&output)?; - } - move_folder(&entry, &output)?; - } - } - - fs::remove_dir(&source)?; - - Ok(()) -} - -fn render_html(output_path: &Path) -> Result<(), Box> { - // We need to render into a temporary folder to prevent `mdbook` from removing everything - // in the output folder (including other completely unrelated things). - let tmp_output = output_path.join("tmp"); - - if !tmp_output.exists() { - create_dir_all(&tmp_output)?; - } - - render_html_inner(&tmp_output)?; - - move_folder(&tmp_output, output_path)?; - - Ok(()) -} - // By default, mdbook doesn't consider code blocks as Rust ones contrary to rustdoc so we have // to manually add `rust` attribute whenever needed. fn add_rust_attribute_on_codeblock(explanation: &str) -> String { @@ -134,18 +96,14 @@ fn add_rust_attribute_on_codeblock(explanation: &str) -> String { }) } -fn render_html_inner(output_path: &Path) -> Result<(), Box> { - // We need to have a little difference between `summary` and `introduction` because the "draft" - // chapters (the ones looking like `[a]()`) are not handled correctly when being put into a - // `Chapter` directly: they generate a link whereas they shouldn't. +fn render_html(output_path: &Path) -> Result<(), Box> { let mut introduction = format!( - " + " # Rust error codes index This page lists all the error codes emitted by the Rust compiler. -", - include_str!("redirect.js") +" ); let err_codes = error_codes(); @@ -153,7 +111,7 @@ This page lists all the error codes emitted by the Rust compiler. for (err_code, explanation) in err_codes.iter() { if let Some(explanation) = explanation { - introduction.push_str(&format!(" * [{0}](./error_codes/{0}.html)\n", err_code)); + introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code)); let content = add_rust_attribute_on_codeblock(explanation); chapters.push(BookItem::Chapter(Chapter { @@ -162,7 +120,7 @@ This page lists all the error codes emitted by the Rust compiler. number: None, sub_items: Vec::new(), // We generate it into the `error_codes` folder. - path: Some(PathBuf::from(&format!("error_codes/{}.html", err_code))), + path: Some(PathBuf::from(&format!("{}.html", err_code))), source_path: None, parent_names: Vec::new(), })); @@ -172,7 +130,7 @@ This page lists all the error codes emitted by the Rust compiler. } let mut config = Config::from_str(include_str!("book_config.toml"))?; - config.build.build_dir = output_path.to_path_buf(); + config.build.build_dir = output_path.join("error_codes").to_path_buf(); let mut book = MDBook::load_with_config_and_summary( env!("CARGO_MANIFEST_DIR"), config, @@ -191,10 +149,27 @@ This page lists all the error codes emitted by the Rust compiler. book.book.sections.push(BookItem::Chapter(chapter)); book.build()?; - // We don't need this file since it's handled by doc.rust-lang.org directly. - let _ = fs::remove_file(output_path.join("404.html")); - // We don't want this file either because it would overwrite the already existing `index.html`. - let _ = fs::remove_file(output_path.join("index.html")); + // We can't put this content into another file, otherwise `mbdbook` will also put it into the + // output directory, making a duplicate. + fs::write( + output_path.join("error-index.html"), + r#" + + + Rust error codes index - Error codes index + + + + + +
If you are not automatically redirected to the error code index, please here. + + +"#, + )?; + + // No need for a 404 file, it's already handled by the server. + fs::remove_file(output_path.join("error_codes/404.html"))?; Ok(()) } diff --git a/src/tools/error_index_generator/redirect.js b/src/tools/error_index_generator/redirect.js index e6e910658e483..8c907f5795d32 100644 --- a/src/tools/error_index_generator/redirect.js +++ b/src/tools/error_index_generator/redirect.js @@ -1,10 +1,16 @@ -(function() {{ - if (window.location.hash) {{ +(function() { + if (window.location.hash) { let code = window.location.hash.replace(/^#/, ''); // We have to make sure this pattern matches to avoid inadvertently creating an // open redirect. - if (/^E[0-9]+$/.test(code)) {{ + if (!/^E[0-9]+$/.test(code)) { + return; + } + if (window.location.pathname.indexOf("/error_codes/") !== -1) { + // We're not at the top level, so we don't prepend with "./error_codes/". + window.location = './' + code + '.html'; + } else { window.location = './error_codes/' + code + '.html'; - }} - }} -}})() + } + } +})() From 7dc186ff7efd4526316fe48845dad581706ea529 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 14 Aug 2022 20:28:34 +0300 Subject: [PATCH 32/38] rustc_target: Add a compatibility layer to separate internal and user-facing linker flavors --- compiler/rustc_codegen_ssa/src/back/link.rs | 3 +- compiler/rustc_session/src/config.rs | 4 +- compiler/rustc_session/src/options.rs | 10 +- compiler/rustc_target/src/spec/mod.rs | 190 +++++++++++++----- .../rustc_target/src/spec/tests/tests_impl.rs | 6 +- 5 files changed, 152 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index d2f2c7bf7988a..efad767edef22 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1236,7 +1236,8 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { // linker and linker flavor specified via command line have precedence over what the target // specification specifies - if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), sess.opts.cg.linker_flavor) { + let linker_flavor = sess.opts.cg.linker_flavor.map(LinkerFlavor::from_cli); + if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) { return ret; } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 162fc9aa0a6ea..c894b20e1a7da 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -12,7 +12,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::ToStableHashKey; use rustc_target::abi::{Align, TargetDataLayout}; -use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings}; +use rustc_target::spec::{LinkerFlavorCli, SplitDebuginfo, Target, TargetTriple, TargetWarnings}; use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS}; use crate::parse::{CrateCheckConfig, CrateConfig}; @@ -2379,7 +2379,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } - if cg.linker_flavor == Some(LinkerFlavor::L4Bender) + if cg.linker_flavor == Some(LinkerFlavorCli::L4Bender) && !nightly_options::is_unstable_enabled(matches) { early_error( diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 46bba02537dc7..9f07394b61ab8 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -5,7 +5,7 @@ use crate::lint; use crate::search_paths::SearchPath; use crate::utils::NativeLib; use rustc_errors::LanguageIdentifier; -use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet}; +use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet}; use rustc_target::spec::{ RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, }; @@ -382,7 +382,7 @@ mod desc { "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_strip: &str = "either `none`, `debuginfo`, or `symbols`"; - pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of(); + pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`"; pub const parse_instrument_coverage: &str = @@ -763,8 +763,8 @@ mod parse { true } - pub(crate) fn parse_linker_flavor(slot: &mut Option, v: Option<&str>) -> bool { - match v.and_then(LinkerFlavor::from_str) { + 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), _ => return false, } @@ -1139,7 +1139,7 @@ options! { on C toolchain installed in the system"), linker: Option = (None, parse_opt_pathbuf, [UNTRACKED], "system linker to link outputs with"), - linker_flavor: Option = (None, parse_linker_flavor, [UNTRACKED], + linker_flavor: Option = (None, parse_linker_flavor, [UNTRACKED], "linker flavor"), linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled, parse_linker_plugin_lto, [TRACKED], diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 2459b0280cd66..168fd154cf001 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -102,6 +102,18 @@ pub enum LinkerFlavor { BpfLinker, } +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub enum LinkerFlavorCli { + Em, + Gcc, + L4Bender, + Ld, + Msvc, + Lld(LldFlavor), + PtxLinker, + BpfLinker, +} + #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum LldFlavor { Wasm, @@ -137,14 +149,37 @@ impl ToJson for LldFlavor { } } -impl ToJson for LinkerFlavor { - fn to_json(&self) -> Json { - self.desc().to_json() +impl LinkerFlavor { + pub fn from_cli(cli: LinkerFlavorCli) -> LinkerFlavor { + match cli { + LinkerFlavorCli::Em => LinkerFlavor::Em, + LinkerFlavorCli::Gcc => LinkerFlavor::Gcc, + LinkerFlavorCli::L4Bender => LinkerFlavor::L4Bender, + LinkerFlavorCli::Ld => LinkerFlavor::Ld, + LinkerFlavorCli::Msvc => LinkerFlavor::Msvc, + LinkerFlavorCli::Lld(lld_flavor) => LinkerFlavor::Lld(lld_flavor), + LinkerFlavorCli::PtxLinker => LinkerFlavor::PtxLinker, + LinkerFlavorCli::BpfLinker => LinkerFlavor::BpfLinker, + } + } + + fn to_cli(self) -> LinkerFlavorCli { + match self { + LinkerFlavor::Em => LinkerFlavorCli::Em, + LinkerFlavor::Gcc => LinkerFlavorCli::Gcc, + LinkerFlavor::L4Bender => LinkerFlavorCli::L4Bender, + LinkerFlavor::Ld => LinkerFlavorCli::Ld, + LinkerFlavor::Msvc => LinkerFlavorCli::Msvc, + LinkerFlavor::Lld(lld_flavor) => LinkerFlavorCli::Lld(lld_flavor), + LinkerFlavor::PtxLinker => LinkerFlavorCli::PtxLinker, + LinkerFlavor::BpfLinker => LinkerFlavorCli::BpfLinker, + } } } + macro_rules! flavor_mappings { ($((($($flavor:tt)*), $string:expr),)*) => ( - impl LinkerFlavor { + impl LinkerFlavorCli { pub const fn one_of() -> &'static str { concat!("one of: ", $($string, " ",)*) } @@ -166,17 +201,23 @@ macro_rules! flavor_mappings { } flavor_mappings! { - ((LinkerFlavor::Em), "em"), - ((LinkerFlavor::Gcc), "gcc"), - ((LinkerFlavor::L4Bender), "l4-bender"), - ((LinkerFlavor::Ld), "ld"), - ((LinkerFlavor::Msvc), "msvc"), - ((LinkerFlavor::PtxLinker), "ptx-linker"), - ((LinkerFlavor::BpfLinker), "bpf-linker"), - ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"), - ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"), - ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"), - ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"), + ((LinkerFlavorCli::Em), "em"), + ((LinkerFlavorCli::Gcc), "gcc"), + ((LinkerFlavorCli::L4Bender), "l4-bender"), + ((LinkerFlavorCli::Ld), "ld"), + ((LinkerFlavorCli::Msvc), "msvc"), + ((LinkerFlavorCli::PtxLinker), "ptx-linker"), + ((LinkerFlavorCli::BpfLinker), "bpf-linker"), + ((LinkerFlavorCli::Lld(LldFlavor::Wasm)), "wasm-ld"), + ((LinkerFlavorCli::Lld(LldFlavor::Ld64)), "ld64.lld"), + ((LinkerFlavorCli::Lld(LldFlavor::Ld)), "ld.lld"), + ((LinkerFlavorCli::Lld(LldFlavor::Link)), "lld-link"), +} + +impl ToJson for LinkerFlavorCli { + fn to_json(&self) -> Json { + self.desc().to_json() + } } #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)] @@ -467,6 +508,7 @@ impl fmt::Display for LinkOutputKind { } pub type LinkArgs = BTreeMap>>; +pub type LinkArgsCli = BTreeMap>>; /// Which kind of debuginfo does the target use? /// @@ -1213,6 +1255,7 @@ pub struct TargetOptions { /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed /// on the command line. Defaults to `LinkerFlavor::Gcc`. pub linker_flavor: LinkerFlavor, + linker_flavor_json: LinkerFlavorCli, /// Linker to invoke pub linker: Option>, @@ -1223,6 +1266,7 @@ pub struct TargetOptions { /// Linker arguments that are passed *before* any user-defined libraries. pub pre_link_args: LinkArgs, + pre_link_args_json: LinkArgsCli, /// Objects to link before and after all other object code. pub pre_link_objects: CrtObjects, pub post_link_objects: CrtObjects, @@ -1235,15 +1279,19 @@ pub struct TargetOptions { /// user-defined but before post-link objects. Standard platform /// libraries that should be always be linked to, usually go here. pub late_link_args: LinkArgs, + late_link_args_json: LinkArgsCli, /// Linker arguments used in addition to `late_link_args` if at least one /// Rust dependency is dynamically linked. pub late_link_args_dynamic: LinkArgs, + late_link_args_dynamic_json: LinkArgsCli, /// Linker arguments used in addition to `late_link_args` if all Rust /// dependencies are statically linked. pub late_link_args_static: LinkArgs, + late_link_args_static_json: LinkArgsCli, /// Linker arguments that are unconditionally passed *after* any /// user-defined libraries. pub post_link_args: LinkArgs, + post_link_args_json: LinkArgsCli, /// Optional link script applied to `dylib` and `executable` crate types. /// This is a string containing the script, not a path. Can only be applied /// to linkers where `linker_is_gnu` is true. @@ -1554,6 +1602,36 @@ impl TargetOptions { fn add_post_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) { add_link_args(&mut self.post_link_args, flavor, args); } + + fn update_from_cli(&mut self) { + self.linker_flavor = LinkerFlavor::from_cli(self.linker_flavor_json); + for (args, args_json) in [ + (&mut self.pre_link_args, &self.pre_link_args_json), + (&mut self.late_link_args, &self.late_link_args_json), + (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json), + (&mut self.late_link_args_static, &self.late_link_args_static_json), + (&mut self.post_link_args, &self.post_link_args_json), + ] { + *args = args_json + .iter() + .map(|(flavor, args)| (LinkerFlavor::from_cli(*flavor), args.clone())) + .collect(); + } + } + + fn update_to_cli(&mut self) { + self.linker_flavor_json = self.linker_flavor.to_cli(); + for (args, args_json) in [ + (&self.pre_link_args, &mut self.pre_link_args_json), + (&self.late_link_args, &mut self.late_link_args_json), + (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json), + (&self.late_link_args_static, &mut self.late_link_args_static_json), + (&self.post_link_args, &mut self.post_link_args_json), + ] { + *args_json = + args.iter().map(|(flavor, args)| (flavor.to_cli(), args.clone())).collect(); + } + } } impl Default for TargetOptions { @@ -1569,10 +1647,13 @@ impl Default for TargetOptions { abi: "".into(), vendor: "unknown".into(), linker_flavor: LinkerFlavor::Gcc, + linker_flavor_json: LinkerFlavorCli::Gcc, linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()), lld_flavor: LldFlavor::Ld, pre_link_args: LinkArgs::new(), + pre_link_args_json: LinkArgsCli::new(), post_link_args: LinkArgs::new(), + post_link_args_json: LinkArgsCli::new(), link_script: None, asm_args: cvs![], cpu: "generic".into(), @@ -1613,8 +1694,11 @@ impl Default for TargetOptions { post_link_objects_self_contained: Default::default(), link_self_contained: LinkSelfContainedDefault::False, late_link_args: LinkArgs::new(), + late_link_args_json: LinkArgsCli::new(), late_link_args_dynamic: LinkArgs::new(), + late_link_args_dynamic_json: LinkArgsCli::new(), late_link_args_static: LinkArgs::new(), + late_link_args_static_json: LinkArgsCli::new(), link_env: cvs![], link_env_remove: cvs![], archive_format: "gnu".into(), @@ -2019,13 +2103,13 @@ impl Target { Some(Ok(())) })).unwrap_or(Ok(())) } ); - ($key_name:ident, LinkerFlavor) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match LinkerFlavor::from_str(s) { + ($key_name:ident = $json_name:expr, LinkerFlavor) => ( { + let name = $json_name; + obj.remove(name).and_then(|o| o.as_str().and_then(|s| { + match LinkerFlavorCli::from_str(s) { Some(linker_flavor) => base.$key_name = linker_flavor, _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \ - Use {}", s, LinkerFlavor::one_of()))), + Use {}", s, LinkerFlavorCli::one_of()))), } Some(Ok(())) })).unwrap_or(Ok(())) @@ -2106,14 +2190,14 @@ impl Target { base.$key_name = args; } } ); - ($key_name:ident, link_args) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(val) = obj.remove(&name) { + ($key_name:ident = $json_name:expr, link_args) => ( { + let name = $json_name; + if let Some(val) = obj.remove(name) { let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ JSON object with fields per linker-flavor.", name))?; - let mut args = LinkArgs::new(); + let mut args = LinkArgsCli::new(); for (k, v) in obj { - let flavor = LinkerFlavor::from_str(&k).ok_or_else(|| { + let flavor = LinkerFlavorCli::from_str(&k).ok_or_else(|| { format!("{}: '{}' is not a valid value for linker-flavor. \ Use 'em', 'gcc', 'ld' or 'msvc'", name, k) })?; @@ -2199,7 +2283,7 @@ impl Target { key!(env); key!(abi); key!(vendor); - key!(linker_flavor, LinkerFlavor)?; + key!(linker_flavor_json = "linker-flavor", LinkerFlavor)?; key!(linker, optional); key!(lld_flavor, LldFlavor)?; key!(pre_link_objects = "pre-link-objects", link_objects); @@ -2207,11 +2291,11 @@ impl Target { key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects); key!(post_link_objects_self_contained = "post-link-objects-fallback", link_objects); key!(link_self_contained = "crt-objects-fallback", link_self_contained)?; - key!(pre_link_args, link_args); - key!(late_link_args, link_args); - key!(late_link_args_dynamic, link_args); - key!(late_link_args_static, link_args); - key!(post_link_args, link_args); + key!(pre_link_args_json = "pre-link-args", link_args); + key!(late_link_args_json = "late-link-args", link_args); + key!(late_link_args_dynamic_json = "late-link-args-dynamic", link_args); + key!(late_link_args_static_json = "late-link-args-static", link_args); + key!(post_link_args_json = "post-link-args", link_args); key!(link_script, optional); key!(link_env, env); key!(link_env_remove, list); @@ -2296,6 +2380,8 @@ impl Target { // This can cause unfortunate ICEs later down the line. return Err("may not set is_builtin for targets not built-in".into()); } + base.update_from_cli(); + // Each field should have been read using `Json::remove` so any keys remaining are unused. let remaining_keys = obj.keys(); Ok(( @@ -2387,42 +2473,44 @@ impl ToJson for Target { fn to_json(&self) -> Json { let mut d = serde_json::Map::new(); let default: TargetOptions = Default::default(); + let mut target = self.clone(); + target.update_to_cli(); macro_rules! target_val { ($attr:ident) => {{ let name = (stringify!($attr)).replace("_", "-"); - d.insert(name, self.$attr.to_json()); + d.insert(name, target.$attr.to_json()); }}; } macro_rules! target_option_val { ($attr:ident) => {{ let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != self.$attr { - d.insert(name, self.$attr.to_json()); + if default.$attr != target.$attr { + d.insert(name, target.$attr.to_json()); } }}; - ($attr:ident, $key_name:expr) => {{ - let name = $key_name; - if default.$attr != self.$attr { - d.insert(name.into(), self.$attr.to_json()); + ($attr:ident, $json_name:expr) => {{ + let name = $json_name; + if default.$attr != target.$attr { + d.insert(name.into(), target.$attr.to_json()); } }}; - (link_args - $attr:ident) => {{ - let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != self.$attr { - let obj = self + (link_args - $attr:ident, $json_name:expr) => {{ + let name = $json_name; + if default.$attr != target.$attr { + let obj = target .$attr .iter() .map(|(k, v)| (k.desc().to_string(), v.clone())) .collect::>(); - d.insert(name, obj.to_json()); + d.insert(name.to_string(), obj.to_json()); } }}; (env - $attr:ident) => {{ let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != self.$attr { - let obj = self + if default.$attr != target.$attr { + let obj = target .$attr .iter() .map(|&(ref k, ref v)| format!("{k}={v}")) @@ -2444,7 +2532,7 @@ impl ToJson for Target { target_option_val!(env); target_option_val!(abi); target_option_val!(vendor); - target_option_val!(linker_flavor); + target_option_val!(linker_flavor_json, "linker-flavor"); target_option_val!(linker); target_option_val!(lld_flavor); target_option_val!(pre_link_objects); @@ -2452,11 +2540,11 @@ impl ToJson for Target { target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback"); target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback"); target_option_val!(link_self_contained, "crt-objects-fallback"); - target_option_val!(link_args - pre_link_args); - target_option_val!(link_args - late_link_args); - target_option_val!(link_args - late_link_args_dynamic); - target_option_val!(link_args - late_link_args_static); - target_option_val!(link_args - post_link_args); + target_option_val!(link_args - pre_link_args_json, "pre-link-args"); + target_option_val!(link_args - late_link_args_json, "late-link-args"); + target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic"); + target_option_val!(link_args - late_link_args_static_json, "late-link-args-static"); + target_option_val!(link_args - post_link_args_json, "post-link-args"); target_option_val!(link_script); target_option_val!(env - link_env); target_option_val!(link_env_remove); diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index 4a53b9c173d1f..244f826242850 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -2,9 +2,11 @@ use super::super::*; use std::assert_matches::assert_matches; // Test target self-consistency and JSON encoding/decoding roundtrip. -pub(super) fn test_target(target: Target, triple: &str) { +pub(super) fn test_target(mut target: Target, triple: &str) { + let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j); + target.update_to_cli(); target.check_consistency(triple); - assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target)); + assert_eq!(recycled_target, Ok(target)); } impl Target { From a0e21ff10506dc83deb5ef90c8bf3b308ae5b2b8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 15 Aug 2022 00:31:31 +0300 Subject: [PATCH 33/38] rustc_target: Refactor internal linker flavors slightly Remove one unstable user-facing linker flavor (l4-bender) --- compiler/rustc_codegen_ssa/src/back/link.rs | 27 +++-- compiler/rustc_codegen_ssa/src/back/linker.rs | 21 ++-- compiler/rustc_interface/src/tests.rs | 8 +- compiler/rustc_session/src/config.rs | 14 +-- .../src/spec/asmjs_unknown_emscripten.rs | 2 +- compiler/rustc_target/src/spec/bpf_base.rs | 2 +- compiler/rustc_target/src/spec/l4re_base.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 110 ++++++++---------- .../src/spec/nvptx64_nvidia_cuda.rs | 2 +- .../rustc_target/src/spec/tests/tests_impl.rs | 22 ++-- .../src/spec/wasm32_unknown_emscripten.rs | 4 +- 11 files changed, 93 insertions(+), 121 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index efad767edef22..1ebe5bac203de 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1173,13 +1173,6 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { // only the linker flavor is known; use the default linker for the selected flavor (None, Some(flavor)) => Some(( PathBuf::from(match flavor { - LinkerFlavor::Em => { - if cfg!(windows) { - "emcc.bat" - } else { - "emcc" - } - } LinkerFlavor::Gcc => { if cfg!(any(target_os = "solaris", target_os = "illumos")) { // On historical Solaris systems, "cc" may have @@ -1194,11 +1187,17 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { } } LinkerFlavor::Ld => "ld", - LinkerFlavor::Msvc => "link.exe", LinkerFlavor::Lld(_) => "lld", - LinkerFlavor::PtxLinker => "rust-ptx-linker", - LinkerFlavor::BpfLinker => "bpf-linker", - LinkerFlavor::L4Bender => "l4-bender", + LinkerFlavor::Msvc => "link.exe", + LinkerFlavor::EmCc => { + if cfg!(windows) { + "emcc.bat" + } else { + "emcc" + } + } + LinkerFlavor::Bpf => "bpf-linker", + LinkerFlavor::Ptx => "rust-ptx-linker", }), flavor, )), @@ -1208,7 +1207,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { }); let flavor = if stem == "emcc" { - LinkerFlavor::Em + LinkerFlavor::EmCc } else if stem == "gcc" || stem.ends_with("-gcc") || stem == "clang" @@ -2114,11 +2113,11 @@ fn add_order_independent_options( }); } - if flavor == LinkerFlavor::PtxLinker { + if flavor == LinkerFlavor::Ptx { // Provide the linker with fallback to internal `target-cpu`. cmd.arg("--fallback-arch"); cmd.arg(&codegen_results.crate_info.target_cpu); - } else if flavor == LinkerFlavor::BpfLinker { + } else if flavor == LinkerFlavor::Bpf { cmd.arg("--cpu"); cmd.arg(&codegen_results.crate_info.target_cpu); cmd.arg("--cpu-features"); diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index ce51b2e9531fc..8c6f526b054bc 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -126,29 +126,26 @@ pub fn get_linker<'a>( // to the linker args construction. assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp"); match flavor { - LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { - Box::new(MsvcLinker { cmd, sess }) as Box - } - LinkerFlavor::Em => Box::new(EmLinker { cmd, sess }) as Box, LinkerFlavor::Gcc => { Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false }) as Box } - + LinkerFlavor::Ld if sess.target.os == "l4re" => { + Box::new(L4Bender::new(cmd, sess)) as Box + } LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Lld(LldFlavor::Ld64) | LinkerFlavor::Ld => { Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true }) as Box } - + LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { + Box::new(MsvcLinker { cmd, sess }) as Box + } LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box, - - LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box, - - LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box, - - LinkerFlavor::L4Bender => Box::new(L4Bender::new(cmd, sess)) as Box, + LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box, + LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box, + LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box, } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 9207a0488623c..5df5ab3ddc032 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -21,10 +21,8 @@ use rustc_session::{build_session, getopts, DiagnosticOutput, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; -use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; -use rustc_target::spec::{ - RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, -}; +use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel}; +use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; @@ -552,7 +550,7 @@ fn test_codegen_options_tracking_hash() { untracked!(link_args, vec![String::from("abc"), String::from("def")]); untracked!(link_self_contained, Some(true)); untracked!(linker, Some(PathBuf::from("linker"))); - untracked!(linker_flavor, Some(LinkerFlavor::Gcc)); + untracked!(linker_flavor, Some(LinkerFlavorCli::Gcc)); untracked!(no_stack_check, true); untracked!(remark, Passes::Some(vec![String::from("pass1"), String::from("pass2")])); untracked!(rpath, true); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c894b20e1a7da..c1c064352d061 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -12,8 +12,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::ToStableHashKey; use rustc_target::abi::{Align, TargetDataLayout}; -use rustc_target::spec::{LinkerFlavorCli, SplitDebuginfo, Target, TargetTriple, TargetWarnings}; -use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS}; +use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo}; +use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS}; use crate::parse::{CrateCheckConfig, CrateConfig}; use rustc_feature::UnstableFeatures; @@ -2379,16 +2379,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } - if cg.linker_flavor == Some(LinkerFlavorCli::L4Bender) - && !nightly_options::is_unstable_enabled(matches) - { - early_error( - error_format, - "`l4-bender` linker flavor is unstable, `-Z unstable-options` \ - flag must also be passed to explicitly use it", - ); - } - let prints = collect_print_requests(&mut cg, &mut unstable_opts, matches, error_format); let cg = cg; diff --git a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs index b4cf2c5ee2294..f492c3451a418 100644 --- a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs @@ -2,6 +2,6 @@ use super::{wasm32_unknown_emscripten, LinkerFlavor, Target}; pub fn target() -> Target { let mut target = wasm32_unknown_emscripten::target(); - target.add_post_link_args(LinkerFlavor::Em, &["-sWASM=0", "--memory-init-file", "0"]); + target.add_post_link_args(LinkerFlavor::EmCc, &["-sWASM=0", "--memory-init-file", "0"]); target } diff --git a/compiler/rustc_target/src/spec/bpf_base.rs b/compiler/rustc_target/src/spec/bpf_base.rs index 3c4da6f883d9d..baf36587147a6 100644 --- a/compiler/rustc_target/src/spec/bpf_base.rs +++ b/compiler/rustc_target/src/spec/bpf_base.rs @@ -5,7 +5,7 @@ pub fn opts(endian: Endian) -> TargetOptions { TargetOptions { allow_asm: true, endian, - linker_flavor: LinkerFlavor::BpfLinker, + linker_flavor: LinkerFlavor::Bpf, atomic_cas: false, dynamic_linking: true, no_builtins: true, diff --git a/compiler/rustc_target/src/spec/l4re_base.rs b/compiler/rustc_target/src/spec/l4re_base.rs index cab4dd333d43d..b7bc1072bf328 100644 --- a/compiler/rustc_target/src/spec/l4re_base.rs +++ b/compiler/rustc_target/src/spec/l4re_base.rs @@ -4,7 +4,7 @@ pub fn opts() -> TargetOptions { TargetOptions { os: "l4re".into(), env: "uclibc".into(), - linker_flavor: LinkerFlavor::L4Bender, + linker_flavor: LinkerFlavor::Ld, panic_strategy: PanicStrategy::Abort, linker: Some("l4-bender".into()), linker_is_gnu: false, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 168fd154cf001..47eb5fc6a1dcb 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -92,26 +92,24 @@ mod windows_uwp_msvc_base; #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum LinkerFlavor { - Em, Gcc, - L4Bender, Ld, - Msvc, Lld(LldFlavor), - PtxLinker, - BpfLinker, + Msvc, + EmCc, + Bpf, + Ptx, } #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum LinkerFlavorCli { - Em, Gcc, - L4Bender, Ld, - Msvc, Lld(LldFlavor), - PtxLinker, + Msvc, + Em, BpfLinker, + PtxLinker, } #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -152,39 +150,37 @@ impl ToJson for LldFlavor { impl LinkerFlavor { pub fn from_cli(cli: LinkerFlavorCli) -> LinkerFlavor { match cli { - LinkerFlavorCli::Em => LinkerFlavor::Em, LinkerFlavorCli::Gcc => LinkerFlavor::Gcc, - LinkerFlavorCli::L4Bender => LinkerFlavor::L4Bender, LinkerFlavorCli::Ld => LinkerFlavor::Ld, - LinkerFlavorCli::Msvc => LinkerFlavor::Msvc, LinkerFlavorCli::Lld(lld_flavor) => LinkerFlavor::Lld(lld_flavor), - LinkerFlavorCli::PtxLinker => LinkerFlavor::PtxLinker, - LinkerFlavorCli::BpfLinker => LinkerFlavor::BpfLinker, + LinkerFlavorCli::Msvc => LinkerFlavor::Msvc, + LinkerFlavorCli::Em => LinkerFlavor::EmCc, + LinkerFlavorCli::BpfLinker => LinkerFlavor::Bpf, + LinkerFlavorCli::PtxLinker => LinkerFlavor::Ptx, } } fn to_cli(self) -> LinkerFlavorCli { match self { - LinkerFlavor::Em => LinkerFlavorCli::Em, LinkerFlavor::Gcc => LinkerFlavorCli::Gcc, - LinkerFlavor::L4Bender => LinkerFlavorCli::L4Bender, LinkerFlavor::Ld => LinkerFlavorCli::Ld, - LinkerFlavor::Msvc => LinkerFlavorCli::Msvc, LinkerFlavor::Lld(lld_flavor) => LinkerFlavorCli::Lld(lld_flavor), - LinkerFlavor::PtxLinker => LinkerFlavorCli::PtxLinker, - LinkerFlavor::BpfLinker => LinkerFlavorCli::BpfLinker, + LinkerFlavor::Msvc => LinkerFlavorCli::Msvc, + LinkerFlavor::EmCc => LinkerFlavorCli::Em, + LinkerFlavor::Bpf => LinkerFlavorCli::BpfLinker, + LinkerFlavor::Ptx => LinkerFlavorCli::PtxLinker, } } } -macro_rules! flavor_mappings { - ($((($($flavor:tt)*), $string:expr),)*) => ( +macro_rules! linker_flavor_cli_impls { + ($(($($flavor:tt)*) $string:literal)*) => ( impl LinkerFlavorCli { pub const fn one_of() -> &'static str { concat!("one of: ", $($string, " ",)*) } - pub fn from_str(s: &str) -> Option { + pub fn from_str(s: &str) -> Option { Some(match s { $($string => $($flavor)*,)* _ => return None, @@ -200,18 +196,17 @@ macro_rules! flavor_mappings { ) } -flavor_mappings! { - ((LinkerFlavorCli::Em), "em"), - ((LinkerFlavorCli::Gcc), "gcc"), - ((LinkerFlavorCli::L4Bender), "l4-bender"), - ((LinkerFlavorCli::Ld), "ld"), - ((LinkerFlavorCli::Msvc), "msvc"), - ((LinkerFlavorCli::PtxLinker), "ptx-linker"), - ((LinkerFlavorCli::BpfLinker), "bpf-linker"), - ((LinkerFlavorCli::Lld(LldFlavor::Wasm)), "wasm-ld"), - ((LinkerFlavorCli::Lld(LldFlavor::Ld64)), "ld64.lld"), - ((LinkerFlavorCli::Lld(LldFlavor::Ld)), "ld.lld"), - ((LinkerFlavorCli::Lld(LldFlavor::Link)), "lld-link"), +linker_flavor_cli_impls! { + (LinkerFlavorCli::Gcc) "gcc" + (LinkerFlavorCli::Ld) "ld" + (LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld" + (LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld" + (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link" + (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld" + (LinkerFlavorCli::Msvc) "msvc" + (LinkerFlavorCli::Em) "em" + (LinkerFlavorCli::BpfLinker) "bpf-linker" + (LinkerFlavorCli::PtxLinker) "ptx-linker" } impl ToJson for LinkerFlavorCli { @@ -1252,21 +1247,21 @@ pub struct TargetOptions { pub abi: StaticCow, /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown". pub vendor: StaticCow, + + /// Linker to invoke + pub linker: Option>, /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed /// on the command line. Defaults to `LinkerFlavor::Gcc`. pub linker_flavor: LinkerFlavor, linker_flavor_json: LinkerFlavorCli, - - /// Linker to invoke - pub linker: Option>, - /// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker /// without clarifying its flavor in any way. + /// FIXME: Merge this into `LinkerFlavor`. pub lld_flavor: LldFlavor, + /// Whether the linker support GNU-like arguments such as -O. Defaults to true. + /// FIXME: Merge this into `LinkerFlavor`. + pub linker_is_gnu: bool, - /// Linker arguments that are passed *before* any user-defined libraries. - pub pre_link_args: LinkArgs, - pre_link_args_json: LinkArgsCli, /// Objects to link before and after all other object code. pub pre_link_objects: CrtObjects, pub post_link_objects: CrtObjects, @@ -1275,6 +1270,9 @@ pub struct TargetOptions { pub post_link_objects_self_contained: CrtObjects, pub link_self_contained: LinkSelfContainedDefault, + /// Linker arguments that are passed *before* any user-defined libraries. + pub pre_link_args: LinkArgs, + pre_link_args_json: LinkArgsCli, /// Linker arguments that are unconditionally passed after any /// user-defined but before post-link objects. Standard platform /// libraries that should be always be linked to, usually go here. @@ -1292,11 +1290,11 @@ pub struct TargetOptions { /// user-defined libraries. pub post_link_args: LinkArgs, post_link_args_json: LinkArgsCli, + /// Optional link script applied to `dylib` and `executable` crate types. /// This is a string containing the script, not a path. Can only be applied /// to linkers where `linker_is_gnu` is true. pub link_script: Option>, - /// Environment variables to be set for the linker invocation. pub link_env: StaticCow<[(StaticCow, StaticCow)]>, /// Environment variables to be removed for the linker invocation. @@ -1381,8 +1379,6 @@ pub struct TargetOptions { /// Default supported version of DWARF on this platform. /// Useful because some platforms (osx, bsd) only want up to DWARF2. pub default_dwarf_version: u32, - /// Whether the linker support GNU-like arguments such as -O. Defaults to true. - pub linker_is_gnu: bool, /// The MinGW toolchain has a known issue that prevents it from correctly /// handling COFF object files with more than 215 sections. Since each weak /// symbol needs its own COMDAT section, weak linkage implies a large @@ -1580,11 +1576,7 @@ fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'stati LinkerFlavor::Lld(lld_flavor) => { panic!("add_link_args: use non-LLD flavor for {:?}", lld_flavor) } - LinkerFlavor::Gcc - | LinkerFlavor::Em - | LinkerFlavor::L4Bender - | LinkerFlavor::BpfLinker - | LinkerFlavor::PtxLinker => {} + LinkerFlavor::Gcc | LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => {} } } @@ -1646,14 +1638,11 @@ impl Default for TargetOptions { env: "".into(), abi: "".into(), vendor: "unknown".into(), + linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()), linker_flavor: LinkerFlavor::Gcc, linker_flavor_json: LinkerFlavorCli::Gcc, - linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()), lld_flavor: LldFlavor::Ld, - pre_link_args: LinkArgs::new(), - pre_link_args_json: LinkArgsCli::new(), - post_link_args: LinkArgs::new(), - post_link_args_json: LinkArgsCli::new(), + linker_is_gnu: true, link_script: None, asm_args: cvs![], cpu: "generic".into(), @@ -1680,7 +1669,6 @@ impl Default for TargetOptions { is_like_msvc: false, is_like_wasm: false, default_dwarf_version: 4, - linker_is_gnu: true, allows_weak_linkage: true, has_rpath: false, no_default_libraries: true, @@ -1693,12 +1681,16 @@ impl Default for TargetOptions { pre_link_objects_self_contained: Default::default(), post_link_objects_self_contained: Default::default(), link_self_contained: LinkSelfContainedDefault::False, + pre_link_args: LinkArgs::new(), + pre_link_args_json: LinkArgsCli::new(), late_link_args: LinkArgs::new(), late_link_args_json: LinkArgsCli::new(), late_link_args_dynamic: LinkArgs::new(), late_link_args_dynamic_json: LinkArgsCli::new(), late_link_args_static: LinkArgs::new(), late_link_args_static_json: LinkArgsCli::new(), + post_link_args: LinkArgs::new(), + post_link_args_json: LinkArgsCli::new(), link_env: cvs![], link_env_remove: cvs![], archive_format: "gnu".into(), @@ -2283,9 +2275,10 @@ impl Target { key!(env); key!(abi); key!(vendor); - key!(linker_flavor_json = "linker-flavor", LinkerFlavor)?; key!(linker, optional); + key!(linker_flavor_json = "linker-flavor", LinkerFlavor)?; key!(lld_flavor, LldFlavor)?; + key!(linker_is_gnu, bool); key!(pre_link_objects = "pre-link-objects", link_objects); key!(post_link_objects = "post-link-objects", link_objects); key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects); @@ -2323,7 +2316,6 @@ impl Target { key!(is_like_msvc, bool); key!(is_like_wasm, bool); key!(default_dwarf_version, u32); - key!(linker_is_gnu, bool); key!(allows_weak_linkage, bool); key!(has_rpath, bool); key!(no_default_libraries, bool); @@ -2532,9 +2524,10 @@ impl ToJson for Target { target_option_val!(env); target_option_val!(abi); target_option_val!(vendor); - target_option_val!(linker_flavor_json, "linker-flavor"); target_option_val!(linker); + target_option_val!(linker_flavor_json, "linker-flavor"); target_option_val!(lld_flavor); + target_option_val!(linker_is_gnu); target_option_val!(pre_link_objects); target_option_val!(post_link_objects); target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback"); @@ -2573,7 +2566,6 @@ impl ToJson for Target { target_option_val!(is_like_msvc); target_option_val!(is_like_wasm); target_option_val!(default_dwarf_version); - target_option_val!(linker_is_gnu); target_option_val!(allows_weak_linkage); target_option_val!(has_rpath); target_option_val!(no_default_libraries); diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs index 1c5b68001b957..6ab3a8b7eb5a0 100644 --- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { options: TargetOptions { os: "cuda".into(), vendor: "nvidia".into(), - linker_flavor: LinkerFlavor::PtxLinker, + linker_flavor: LinkerFlavor::Ptx, // The linker can be installed from `crates.io`. linker: Some("rust-ptx-linker".into()), linker_is_gnu: false, diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index 244f826242850..d03f959076de0 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -24,10 +24,9 @@ impl Target { assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64)); assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link)); assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm)); - assert_eq!(self.os == "l4re", matches!(self.linker_flavor, LinkerFlavor::L4Bender)); - assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::Em)); - assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::BpfLinker)); - assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::PtxLinker)); + assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::EmCc)); + assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::Bpf)); + assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::Ptx)); for args in [ &self.pre_link_args, @@ -67,17 +66,14 @@ impl Target { LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc ) } - (LinkerFlavor::L4Bender, LldFlavor::Ld) => { - assert_matches!(flavor, LinkerFlavor::L4Bender) + (LinkerFlavor::EmCc, LldFlavor::Wasm) => { + assert_matches!(flavor, LinkerFlavor::EmCc) } - (LinkerFlavor::Em, LldFlavor::Wasm) => { - assert_matches!(flavor, LinkerFlavor::Em) + (LinkerFlavor::Bpf, LldFlavor::Ld) => { + assert_matches!(flavor, LinkerFlavor::Bpf) } - (LinkerFlavor::BpfLinker, LldFlavor::Ld) => { - assert_matches!(flavor, LinkerFlavor::BpfLinker) - } - (LinkerFlavor::PtxLinker, LldFlavor::Ld) => { - assert_matches!(flavor, LinkerFlavor::PtxLinker) + (LinkerFlavor::Ptx, LldFlavor::Ld) => { + assert_matches!(flavor, LinkerFlavor::Ptx) } flavors => unreachable!("unexpected flavor combination: {:?}", flavors), } diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index c7e7d22108656..6f77ef98c015d 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -5,13 +5,13 @@ pub fn target() -> Target { // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests. let pre_link_args = LinkArgs::new(); let post_link_args = TargetOptions::link_args( - LinkerFlavor::Em, + LinkerFlavor::EmCc, &["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"], ); let opts = TargetOptions { os: "emscripten".into(), - linker_flavor: LinkerFlavor::Em, + linker_flavor: LinkerFlavor::EmCc, // emcc emits two files - a .js file to instantiate the wasm and supply platform // functionality, and a .wasm file. exe_suffix: ".js".into(), From 9df75ee254a2999fe0b7e4c3bddebef34b539891 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 1 Sep 2022 19:42:49 +0200 Subject: [PATCH 34/38] Revert parts of "use derive proc macro to impl SessionDiagnostic" This reverts parts of commit ac638c1f5fca36484506415319ab254ad522a692. During rebase, this commit accidentally reverted unrelated changes to the subdiagnostic derive (those allowing multipart_suggestions to be derived). This commit reverts all changes to the subdiagnostic code made in ac638c1f5fc, the next commit will reintroduce the actually intended changes. --- .../src/diagnostics/subdiagnostic.rs | 694 +++++++++++------- .../subdiagnostic-derive.rs | 164 ++++- .../subdiagnostic-derive.stderr | 234 ++++-- 3 files changed, 758 insertions(+), 334 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index c1b82abc1e064..8b40e295bd8a7 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -12,7 +12,7 @@ use quote::{format_ident, quote}; use std::collections::HashMap; use std::fmt; use std::str::FromStr; -use syn::{spanned::Spanned, Meta, MetaList, MetaNameValue, NestedMeta, Path}; +use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; /// Which kind of suggestion is being created? @@ -28,8 +28,41 @@ enum SubdiagnosticSuggestionKind { Verbose, } +impl FromStr for SubdiagnosticSuggestionKind { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "" => Ok(SubdiagnosticSuggestionKind::Normal), + "_short" => Ok(SubdiagnosticSuggestionKind::Short), + "_hidden" => Ok(SubdiagnosticSuggestionKind::Hidden), + "_verbose" => Ok(SubdiagnosticSuggestionKind::Verbose), + _ => Err(()), + } + } +} + +impl SubdiagnosticSuggestionKind { + pub fn to_suggestion_style(&self) -> TokenStream { + match self { + SubdiagnosticSuggestionKind::Normal => { + quote! { rustc_errors::SuggestionStyle::ShowCode } + } + SubdiagnosticSuggestionKind::Short => { + quote! { rustc_errors::SuggestionStyle::HideCodeInline } + } + SubdiagnosticSuggestionKind::Hidden => { + quote! { rustc_errors::SuggestionStyle::HideCodeAlways } + } + SubdiagnosticSuggestionKind::Verbose => { + quote! { rustc_errors::SuggestionStyle::ShowAlways } + } + } + } +} + /// Which kind of subdiagnostic is being created from a variant? -#[derive(Clone, Copy)] +#[derive(Clone)] enum SubdiagnosticKind { /// `#[label(...)]` Label, @@ -40,31 +73,9 @@ enum SubdiagnosticKind { /// `#[warning(...)]` Warn, /// `#[suggestion{,_short,_hidden,_verbose}]` - Suggestion(SubdiagnosticSuggestionKind), -} - -impl FromStr for SubdiagnosticKind { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - "label" => Ok(SubdiagnosticKind::Label), - "note" => Ok(SubdiagnosticKind::Note), - "help" => Ok(SubdiagnosticKind::Help), - "warning" => Ok(SubdiagnosticKind::Warn), - "suggestion" => Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Normal)), - "suggestion_short" => { - Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Short)) - } - "suggestion_hidden" => { - Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Hidden)) - } - "suggestion_verbose" => { - Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Verbose)) - } - _ => Err(()), - } - } + Suggestion { suggestion_kind: SubdiagnosticSuggestionKind, code: TokenStream }, + /// `#[multipart_suggestion{,_short,_hidden,_verbose}]` + MultipartSuggestion { suggestion_kind: SubdiagnosticSuggestionKind }, } impl quote::IdentFragment for SubdiagnosticKind { @@ -74,17 +85,9 @@ impl quote::IdentFragment for SubdiagnosticKind { SubdiagnosticKind::Note => write!(f, "note"), SubdiagnosticKind::Help => write!(f, "help"), SubdiagnosticKind::Warn => write!(f, "warn"), - SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Normal) => { - write!(f, "suggestion") - } - SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Short) => { - write!(f, "suggestion_short") - } - SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Hidden) => { - write!(f, "suggestion_hidden") - } - SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Verbose) => { - write!(f, "suggestion_verbose") + SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"), + SubdiagnosticKind::MultipartSuggestion { .. } => { + write!(f, "multipart_suggestion_with_style") } } } @@ -148,11 +151,9 @@ impl<'a> SessionSubdiagnosticDerive<'a> { variant, span, fields: fields_map, - kinds: Vec::new(), - slugs: Vec::new(), - code: None, span_field: None, applicability: None, + has_suggestion_parts: false, }; builder.into_tokens().unwrap_or_else(|v| v.to_compile_error()) }); @@ -193,21 +194,15 @@ struct SessionSubdiagnosticDeriveBuilder<'a> { /// derive builder. fields: HashMap, - /// Subdiagnostic kind of the type/variant. - kinds: Vec<(SubdiagnosticKind, proc_macro::Span)>, - - /// Slugs of the subdiagnostic - corresponds to the Fluent identifier for the message - from the - /// `#[kind(slug)]` attribute on the type or variant. - slugs: Vec<(Path, proc_macro::Span)>, - /// If a suggestion, the code to suggest as a replacement - from the `#[kind(code = "...")]` - /// attribute on the type or variant. - code: Option<(TokenStream, proc_macro::Span)>, - /// Identifier for the binding to the `#[primary_span]` field. span_field: Option<(proc_macro2::Ident, proc_macro::Span)>, /// If a suggestion, the identifier for the binding to the `#[applicability]` field or a /// `rustc_errors::Applicability::*` variant directly. applicability: Option<(TokenStream, proc_macro::Span)>, + + /// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error + /// during finalization if still `false`. + has_suggestion_parts: bool, } impl<'a> HasFieldMap for SessionSubdiagnosticDeriveBuilder<'a> { @@ -217,124 +212,133 @@ impl<'a> HasFieldMap for SessionSubdiagnosticDeriveBuilder<'a> { } impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { - fn identify_kind(&mut self) -> Result<(), DiagnosticDeriveError> { - for (i, attr) in self.variant.ast().attrs.iter().enumerate() { + fn identify_kind( + &mut self, + ) -> Result, DiagnosticDeriveError> { + let mut kind_slug = None; + + for attr in self.variant.ast().attrs { let span = attr.span().unwrap(); let name = attr.path.segments.last().unwrap().ident.to_string(); let name = name.as_str(); let meta = attr.parse_meta()?; - let kind = match meta { - Meta::List(MetaList { ref nested, .. }) => { - let mut nested_iter = nested.into_iter(); - if let Some(nested_attr) = nested_iter.next() { - match nested_attr { - NestedMeta::Meta(Meta::Path(path)) => { - self.slugs.push((path.clone(), span)); - } - NestedMeta::Meta(meta @ Meta::NameValue(_)) - if matches!( - meta.path().segments.last().unwrap().ident.to_string().as_str(), - "code" | "applicability" - ) => - { - // don't error for valid follow-up attributes - } - nested_attr => { - throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "first argument of the attribute should be the diagnostic \ - slug", - ) - }) - } - }; - } + let Meta::List(MetaList { ref nested, .. }) = meta else { + throw_invalid_attr!(attr, &meta); + }; - for nested_attr in nested_iter { - let meta = match nested_attr { - NestedMeta::Meta(ref meta) => meta, - _ => 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 meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - match nested_name { - "code" => { - let formatted_str = self.build_format(&s.value(), s.span()); - self.code.set_once((formatted_str, span)); - } - "applicability" => { - let value = match Applicability::from_str(&s.value()) { - Ok(v) => v, - Err(()) => { - span_err(span, "invalid applicability").emit(); - Applicability::Unspecified - } - }; - self.applicability.set_once((quote! { #value }, span)); - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "only `code` and `applicability` are valid nested \ - attributes", - ) - }), - } - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - if matches!(meta, Meta::Path(_)) { - diag.help( - "a diagnostic slug must be the first argument to the \ - attribute", - ) - } else { - diag - } - }), - } + let mut kind = match name { + "label" => SubdiagnosticKind::Label, + "note" => SubdiagnosticKind::Note, + "help" => SubdiagnosticKind::Help, + "warning" => SubdiagnosticKind::Warn, + _ => { + if let Some(suggestion_kind) = + name.strip_prefix("suggestion").and_then(|s| s.parse().ok()) + { + SubdiagnosticKind::Suggestion { suggestion_kind, code: TokenStream::new() } + } else if let Some(suggestion_kind) = + name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok()) + { + SubdiagnosticKind::MultipartSuggestion { suggestion_kind } + } else { + throw_invalid_attr!(attr, &meta); } - - let Ok(kind) = SubdiagnosticKind::from_str(name) else { - throw_invalid_attr!(attr, &meta) - }; - - kind } - _ => throw_invalid_attr!(attr, &meta), }; - if matches!( - kind, - SubdiagnosticKind::Label | SubdiagnosticKind::Help | SubdiagnosticKind::Note - ) && self.code.is_some() - { - throw_span_err!( - span, - &format!("`code` is not a valid nested attribute of a `{}` attribute", name) - ); + let mut slug = None; + let mut code = None; + + let mut nested_iter = nested.into_iter(); + if let Some(nested_attr) = nested_iter.next() { + match nested_attr { + NestedMeta::Meta(Meta::Path(path)) => { + slug.set_once((path.clone(), span)); + } + NestedMeta::Meta(meta @ Meta::NameValue(_)) + if matches!( + meta.path().segments.last().unwrap().ident.to_string().as_str(), + "code" | "applicability" + ) => + { + // Don't error for valid follow-up attributes. + } + nested_attr => { + throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help( + "first argument of the attribute should be the diagnostic \ + slug", + ) + }) + } + }; } - if matches!( - kind, - SubdiagnosticKind::Label | SubdiagnosticKind::Help | SubdiagnosticKind::Note - ) && self.applicability.is_some() - { - throw_span_err!( - span, - &format!( - "`applicability` is not a valid nested attribute of a `{}` attribute", - name - ) - ); + for nested_attr in nested_iter { + let meta = match nested_attr { + NestedMeta::Meta(ref meta) => meta, + _ => 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(); + + let value = match meta { + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value, + Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("a diagnostic slug must be the first argument to the attribute") + }), + _ => throw_invalid_nested_attr!(attr, &nested_attr), + }; + + match nested_name { + "code" => { + if matches!(kind, SubdiagnosticKind::Suggestion { .. }) { + let formatted_str = self.build_format(&value.value(), value.span()); + code.set_once((formatted_str, span)); + } else { + span_err( + span, + &format!( + "`code` is not a valid nested attribute of a `{}` attribute", + name + ), + ) + .emit(); + } + } + "applicability" => { + if matches!( + kind, + SubdiagnosticKind::Suggestion { .. } + | SubdiagnosticKind::MultipartSuggestion { .. } + ) { + let value = + Applicability::from_str(&value.value()).unwrap_or_else(|()| { + span_err(span, "invalid applicability").emit(); + Applicability::Unspecified + }); + self.applicability.set_once((quote! { #value }, span)); + } else { + span_err( + span, + &format!( + "`applicability` is not a valid nested attribute of a `{}` attribute", + name + ) + ).emit(); + } + } + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("only `code` and `applicability` are valid nested attributes") + }), + } } - if self.slugs.len() != i + 1 { + let Some((slug, _)) = slug else { throw_span_err!( span, &format!( @@ -342,146 +346,338 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { name ) ); + }; + + match kind { + SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => { + let Some((code, _)) = code else { + throw_span_err!(span, "suggestion without `code = \"...\"`"); + }; + *code_field = code; + } + SubdiagnosticKind::Label + | SubdiagnosticKind::Note + | SubdiagnosticKind::Help + | SubdiagnosticKind::Warn + | SubdiagnosticKind::MultipartSuggestion { .. } => {} } - self.kinds.push((kind, span)); + kind_slug.set_once(((kind, slug), span)) } - Ok(()) + Ok(kind_slug.map(|(kind_slug, _)| kind_slug)) + } + + /// Generates the code for a field with no attributes. + fn generate_field_set_arg(&mut self, binding: &BindingInfo<'_>) -> TokenStream { + let ast = binding.ast(); + assert_eq!(ast.attrs.len(), 0, "field with attribute used as diagnostic arg"); + + let diag = &self.diag; + let ident = ast.ident.as_ref().unwrap(); + quote! { + #diag.set_arg( + stringify!(#ident), + #binding + ); + } } - fn generate_field_code( + /// Generates the necessary code for all attributes on a field. + fn generate_field_attr_code( &mut self, binding: &BindingInfo<'_>, - have_suggestion: bool, - ) -> Result { + kind: &SubdiagnosticKind, + ) -> TokenStream { let ast = binding.ast(); + assert!(ast.attrs.len() > 0, "field without attributes generating attr code"); + // Abstract over `Vec` and `Option` fields using `FieldInnerTy`, which will + // apply the generated code on each element in the `Vec` or `Option`. let inner_ty = FieldInnerTy::from_type(&ast.ty); - let info = FieldInfo { - binding: binding, - ty: inner_ty.inner_type().unwrap_or(&ast.ty), - span: &ast.span(), - }; + ast.attrs + .iter() + .map(|attr| { + let info = FieldInfo { + binding, + ty: inner_ty.inner_type().unwrap_or(&ast.ty), + span: &ast.span(), + }; - for attr in &ast.attrs { - let name = attr.path.segments.last().unwrap().ident.to_string(); - let name = name.as_str(); - let span = attr.span().unwrap(); + let generated = self + .generate_field_code_inner(kind, attr, info) + .unwrap_or_else(|v| v.to_compile_error()); - let meta = attr.parse_meta()?; - match meta { - Meta::Path(_) => match name { - "primary_span" => { - report_error_if_not_applied_to_span(attr, &info)?; - self.span_field.set_once((binding.binding.clone(), span)); - return Ok(quote! {}); - } - "applicability" if have_suggestion => { - report_error_if_not_applied_to_applicability(attr, &info)?; - let binding = binding.binding.clone(); - self.applicability.set_once((quote! { #binding }, span)); - return Ok(quote! {}); - } - "applicability" => { - span_err(span, "`#[applicability]` is only valid on suggestions").emit(); - return Ok(quote! {}); - } - "skip_arg" => { - return Ok(quote! {}); - } - _ => throw_invalid_attr!(attr, &meta, |diag| { + inner_ty.with(binding, generated) + }) + .collect() + } + + fn generate_field_code_inner( + &mut self, + kind: &SubdiagnosticKind, + attr: &Attribute, + info: FieldInfo<'_>, + ) -> Result { + let meta = attr.parse_meta()?; + match meta { + Meta::Path(path) => self.generate_field_code_inner_path(kind, attr, info, path), + Meta::List(list @ MetaList { .. }) => { + self.generate_field_code_inner_list(kind, attr, info, list) + } + _ => throw_invalid_attr!(attr, &meta), + } + } + + /// Generates the code for a `[Meta::Path]`-like attribute on a field (e.g. `#[primary_span]`). + fn generate_field_code_inner_path( + &mut self, + kind: &SubdiagnosticKind, + attr: &Attribute, + info: FieldInfo<'_>, + path: Path, + ) -> Result { + let span = attr.span().unwrap(); + let ident = &path.segments.last().unwrap().ident; + let name = ident.to_string(); + let name = name.as_str(); + + match name { + "skip_arg" => Ok(quote! {}), + "primary_span" => { + if matches!(kind, SubdiagnosticKind::MultipartSuggestion { .. }) { + throw_invalid_attr!(attr, &Meta::Path(path), |diag| { diag.help( - "only `primary_span`, `applicability` and `skip_arg` are valid field \ - attributes", + "multipart suggestions use one or more `#[suggestion_part]`s rather \ + than one `#[primary_span]`", ) - }), - }, - _ => throw_invalid_attr!(attr, &meta), + }) + } + + report_error_if_not_applied_to_span(attr, &info)?; + + let binding = info.binding.binding.clone(); + self.span_field.set_once((binding, span)); + + Ok(quote! {}) + } + "suggestion_part" => { + self.has_suggestion_parts = true; + + match kind { + SubdiagnosticKind::MultipartSuggestion { .. } => { + span_err( + span, + "`#[suggestion_part(...)]` attribute without `code = \"...\"`", + ) + .emit(); + Ok(quote! {}) + } + SubdiagnosticKind::Label + | SubdiagnosticKind::Note + | SubdiagnosticKind::Help + | SubdiagnosticKind::Warn + | SubdiagnosticKind::Suggestion { .. } => { + throw_invalid_attr!(attr, &Meta::Path(path), |diag| { + diag.help( + "`#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead", + ) + }); + } + } } + "applicability" => { + if let SubdiagnosticKind::Suggestion { .. } + | SubdiagnosticKind::MultipartSuggestion { .. } = kind + { + report_error_if_not_applied_to_applicability(attr, &info)?; + + let binding = info.binding.binding.clone(); + self.applicability.set_once((quote! { #binding }, span)); + } else { + span_err(span, "`#[applicability]` is only valid on suggestions").emit(); + } + + Ok(quote! {}) + } + _ => throw_invalid_attr!(attr, &Meta::Path(path), |diag| { + let span_attr = if let SubdiagnosticKind::MultipartSuggestion { .. } = kind { + "suggestion_part" + } else { + "primary_span" + }; + diag.help(format!( + "only `{span_attr}`, `applicability` and `skip_arg` are valid field attributes", + )) + }), } + } - let ident = ast.ident.as_ref().unwrap(); + /// Generates the code for a `[Meta::List]`-like attribute on a field (e.g. + /// `#[suggestion_part(code = "...")]`). + fn generate_field_code_inner_list( + &mut self, + kind: &SubdiagnosticKind, + attr: &Attribute, + info: FieldInfo<'_>, + list: MetaList, + ) -> Result { + let span = attr.span().unwrap(); + let ident = &list.path.segments.last().unwrap().ident; + let name = ident.to_string(); + let name = name.as_str(); + + match name { + "suggestion_part" => { + if !matches!(kind, SubdiagnosticKind::MultipartSuggestion { .. }) { + throw_invalid_attr!(attr, &Meta::List(list), |diag| { + diag.help( + "`#[suggestion_part(...)]` is only valid in multipart suggestions", + ) + }) + } - let diag = &self.diag; - let generated = quote! { - #diag.set_arg( - stringify!(#ident), - #binding - ); - }; + self.has_suggestion_parts = true; + + 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(); + + let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) = meta else { + throw_invalid_nested_attr!(attr, &nested_attr); + }; + + match nested_name { + "code" => { + let formatted_str = self.build_format(&value.value(), value.span()); + code.set_once((formatted_str, span)); + } + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("`code` is the only valid nested attribute") + }), + } + } + + let Some((code, _)) = code else { + span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") + .emit(); + return Ok(quote! {}); + }; + let binding = info.binding; - Ok(inner_ty.with(binding, generated)) + Ok(quote! { suggestions.push((#binding, #code)); }) + } + _ => throw_invalid_attr!(attr, &Meta::List(list), |diag| { + let span_attr = if let SubdiagnosticKind::MultipartSuggestion { .. } = kind { + "suggestion_part" + } else { + "primary_span" + }; + diag.help(format!( + "only `{span_attr}`, `applicability` and `skip_arg` are valid field attributes", + )) + }), + } } - fn into_tokens(&mut self) -> Result { - self.identify_kind()?; - if self.kinds.is_empty() { + pub fn into_tokens(&mut self) -> Result { + let Some((kind, slug)) = self.identify_kind()? else { throw_span_err!( self.variant.ast().ident.span().unwrap(), "subdiagnostic kind not specified" ); }; - let have_suggestion = - self.kinds.iter().any(|(k, _)| matches!(k, SubdiagnosticKind::Suggestion(_))); - let mut args = TokenStream::new(); - for binding in self.variant.bindings() { - let arg = self - .generate_field_code(binding, have_suggestion) - .unwrap_or_else(|v| v.to_compile_error()); - args.extend(arg); - } - let mut tokens = TokenStream::new(); - for ((kind, _), (slug, _)) in self.kinds.iter().zip(&self.slugs) { - let code = match self.code.as_ref() { - Some((code, _)) => Some(quote! { #code }), - None if have_suggestion => { - span_err(self.span, "suggestion without `code = \"...\"`").emit(); - Some(quote! { /* macro error */ "..." }) - } - None => None, - }; - let span_field = self.span_field.as_ref().map(|(span, _)| span); - let applicability = match self.applicability.clone() { - Some((applicability, _)) => Some(applicability), - None if have_suggestion => { - span_err(self.span, "suggestion without `applicability`").emit(); - Some(quote! { rustc_errors::Applicability::Unspecified }) - } - None => None, - }; + let init = match &kind { + SubdiagnosticKind::Label + | SubdiagnosticKind::Note + | SubdiagnosticKind::Help + | SubdiagnosticKind::Warn + | SubdiagnosticKind::Suggestion { .. } => quote! {}, + SubdiagnosticKind::MultipartSuggestion { .. } => { + quote! { let mut suggestions = Vec::new(); } + } + }; + + let attr_args: TokenStream = self + .variant + .bindings() + .iter() + .filter(|binding| !binding.ast().attrs.is_empty()) + .map(|binding| self.generate_field_attr_code(binding, &kind)) + .collect(); + + let span_field = self.span_field.as_ref().map(|(span, _)| span); + let applicability = self.applicability.take().map_or_else( + || quote! { rustc_errors::Applicability::Unspecified }, + |(applicability, _)| applicability, + ); - let diag = &self.diag; - let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); - let message = quote! { rustc_errors::fluent::#slug }; - let call = if matches!(kind, SubdiagnosticKind::Suggestion(..)) { + let diag = &self.diag; + let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); + let message = quote! { rustc_errors::fluent::#slug }; + let call = match kind { + SubdiagnosticKind::Suggestion { suggestion_kind, code } => { if let Some(span) = span_field { - quote! { #diag.#name(#span, #message, #code, #applicability); } + let style = suggestion_kind.to_suggestion_style(); + + quote! { #diag.#name(#span, #message, #code, #applicability, #style); } } else { span_err(self.span, "suggestion without `#[primary_span]` field").emit(); quote! { unreachable!(); } } - } else if matches!(kind, SubdiagnosticKind::Label) { + } + SubdiagnosticKind::MultipartSuggestion { suggestion_kind } => { + if !self.has_suggestion_parts { + span_err( + self.span, + "multipart suggestion without any `#[suggestion_part(...)]` fields", + ) + .emit(); + } + + let style = suggestion_kind.to_suggestion_style(); + + quote! { #diag.#name(#message, suggestions, #applicability, #style); } + } + SubdiagnosticKind::Label => { if let Some(span) = span_field { quote! { #diag.#name(#span, #message); } } else { span_err(self.span, "label without `#[primary_span]` field").emit(); quote! { unreachable!(); } } - } else { + } + _ => { if let Some(span) = span_field { quote! { #diag.#name(#span, #message); } } else { quote! { #diag.#name(#message); } } - }; - tokens.extend(quote! { - #call - #args - }); - } + } + }; - Ok(tokens) + let plain_args: TokenStream = self + .variant + .bindings() + .iter() + .filter(|binding| binding.ast().attrs.is_empty()) + .map(|binding| self.generate_field_set_arg(binding)) + .collect(); + + Ok(quote! { + #init + #attr_args + #call + #plain_args + }) } } diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index f0843c60543df..89eaec78c6f11 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -167,8 +167,8 @@ enum P { #[derive(SessionSubdiagnostic)] enum Q { #[bar] -//~^ ERROR `#[bar]` is not a valid attribute -//~^^ ERROR cannot find attribute `bar` in this scope + //~^ ERROR `#[bar]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope A { #[primary_span] span: Span, @@ -179,8 +179,8 @@ enum Q { #[derive(SessionSubdiagnostic)] enum R { #[bar = "..."] -//~^ ERROR `#[bar = ...]` is not a valid attribute -//~^^ ERROR cannot find attribute `bar` in this scope + //~^ ERROR `#[bar = ...]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope A { #[primary_span] span: Span, @@ -191,8 +191,8 @@ enum R { #[derive(SessionSubdiagnostic)] enum S { #[bar = 4] -//~^ ERROR `#[bar = ...]` is not a valid attribute -//~^^ ERROR cannot find attribute `bar` in this scope + //~^ ERROR `#[bar = ...]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope A { #[primary_span] span: Span, @@ -203,8 +203,8 @@ enum S { #[derive(SessionSubdiagnostic)] enum T { #[bar("...")] -//~^ ERROR `#[bar("...")]` is not a valid attribute -//~^^ ERROR cannot find attribute `bar` in this scope + //~^ ERROR `#[bar(...)]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope A { #[primary_span] span: Span, @@ -215,7 +215,7 @@ enum T { #[derive(SessionSubdiagnostic)] enum U { #[label(code = "...")] -//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute + //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute A { #[primary_span] span: Span, @@ -232,7 +232,7 @@ enum V { var: String, }, B { -//~^ ERROR subdiagnostic kind not specified + //~^ ERROR subdiagnostic kind not specified #[primary_span] span: Span, var: String, @@ -307,6 +307,16 @@ union AC { b: u64 } +#[derive(SessionSubdiagnostic)] +#[label(parser::add_paren)] +//~^ NOTE previously specified here +#[label(parser::add_paren)] +//~^ ERROR specified multiple times +struct AD { + #[primary_span] + span: Span, +} + #[derive(SessionSubdiagnostic)] #[label(parser::add_paren, parser::add_paren)] //~^ ERROR `#[label(parser::add_paren)]` is not a valid attribute @@ -319,16 +329,16 @@ struct AE { #[label(parser::add_paren)] struct AF { #[primary_span] -//~^ NOTE previously specified here + //~^ NOTE previously specified here span_a: Span, #[primary_span] -//~^ ERROR specified multiple times + //~^ ERROR specified multiple times span_b: Span, } #[derive(SessionSubdiagnostic)] struct AG { -//~^ ERROR subdiagnostic kind not specified + //~^ ERROR subdiagnostic kind not specified #[primary_span] span: Span, } @@ -380,27 +390,25 @@ struct AK { #[primary_span] span: Span, #[applicability] -//~^ NOTE previously specified here + //~^ NOTE previously specified here applicability_a: Applicability, #[applicability] -//~^ ERROR specified multiple times + //~^ ERROR specified multiple times applicability_b: Applicability, } #[derive(SessionSubdiagnostic)] #[suggestion(parser::add_paren, code = "...")] -//~^ ERROR suggestion without `applicability` struct AL { #[primary_span] span: Span, #[applicability] -//~^ ERROR the `#[applicability]` attribute can only be applied to fields of type `Applicability` + //~^ ERROR the `#[applicability]` attribute can only be applied to fields of type `Applicability` applicability: Span, } #[derive(SessionSubdiagnostic)] #[suggestion(parser::add_paren, code = "...")] -//~^ ERROR suggestion without `applicability` struct AM { #[primary_span] span: Span, @@ -436,8 +444,7 @@ struct AQ; #[derive(SessionSubdiagnostic)] #[suggestion(parser::add_paren, code = "...")] -//~^ ERROR suggestion without `applicability` -//~^^ ERROR suggestion without `#[primary_span]` field +//~^ ERROR suggestion without `#[primary_span]` field struct AR { var: String, } @@ -507,3 +514,120 @@ struct AZ { #[primary_span] span: Span, } + +#[derive(SessionSubdiagnostic)] +#[suggestion(parser::add_paren, code = "...")] +//~^ ERROR suggestion without `#[primary_span]` field +struct BA { + #[suggestion_part] + //~^ ERROR `#[suggestion_part]` is not a valid attribute + span: Span, + #[suggestion_part(code = "...")] + //~^ ERROR `#[suggestion_part(...)]` is not a valid attribute + span2: Span, + #[applicability] + applicability: Applicability, + var: String, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] +//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields +//~| ERROR `code` is not a valid nested attribute of a `multipart_suggestion` attribute +struct BBa { + var: String, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] +struct BBb { + #[suggestion_part] + //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + span1: Span, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] +struct BBc { + #[suggestion_part()] + //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + span1: Span, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren)] +//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields +struct BC { + #[primary_span] + //~^ ERROR `#[primary_span]` is not a valid attribute + span: Span, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren)] +struct BD { + #[suggestion_part] + //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + span1: Span, + #[suggestion_part()] + //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + span2: Span, + #[suggestion_part(foo = "bar")] + //~^ ERROR `#[suggestion_part(foo = ...)]` is not a valid attribute + span4: Span, + #[suggestion_part(code = "...")] + //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + s1: String, + #[suggestion_part()] + //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + s2: String, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] +struct BE { + #[suggestion_part(code = "...", code = ",,,")] + //~^ ERROR specified multiple times + //~| NOTE previously specified here + span: Span, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] +struct BF { + #[suggestion_part(code = "(")] + first: Span, + #[suggestion_part(code = ")")] + second: Span, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren)] +struct BG { + #[applicability] + appl: Applicability, + #[suggestion_part(code = "(")] + first: Span, + #[suggestion_part(code = ")")] + second: Span, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] +//~^ NOTE previously specified here +struct BH { + #[applicability] + //~^ ERROR specified multiple times + appl: Applicability, + #[suggestion_part(code = "(")] + first: Span, + #[suggestion_part(code = ")")] + second: Span, +} + +#[derive(SessionSubdiagnostic)] +#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] +struct BI { + #[suggestion_part(code = "")] + spans: Vec, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 6bd9144dbf6f0..75a34f44bbe72 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -65,16 +65,16 @@ LL | #[label()] | ^^^^^^^^^^ error: `code` is not a valid nested attribute of a `label` attribute - --> $DIR/subdiagnostic-derive.rs:137:1 + --> $DIR/subdiagnostic-derive.rs:137:28 | LL | #[label(parser::add_paren, code = "...")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error: `applicability` is not a valid nested attribute of a `label` attribute - --> $DIR/subdiagnostic-derive.rs:146:1 + --> $DIR/subdiagnostic-derive.rs:146:28 | LL | #[label(parser::add_paren, applicability = "machine-applicable")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsupported type attribute for subdiagnostic enum --> $DIR/subdiagnostic-derive.rs:155:1 @@ -100,13 +100,11 @@ error: `#[bar = ...]` is not a valid attribute LL | #[bar = 4] | ^^^^^^^^^^ -error: `#[bar("...")]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:205:11 +error: `#[bar(...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:205:5 | LL | #[bar("...")] - | ^^^^^ - | - = help: first argument of the attribute should be the diagnostic slug + | ^^^^^^^^^^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive.rs:217:5 @@ -163,6 +161,8 @@ error: `#[bar(...)]` is not a valid attribute | LL | #[bar("...")] | ^^^^^^^^^^^^^ + | + = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: unexpected unsupported untagged union --> $DIR/subdiagnostic-derive.rs:304:1 @@ -174,8 +174,20 @@ LL | | b: u64 LL | | } | |_^ +error: specified multiple times + --> $DIR/subdiagnostic-derive.rs:313:1 + | +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive.rs:311:1 + | +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: `#[label(parser::add_paren)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:311:28 + --> $DIR/subdiagnostic-derive.rs:321:28 | LL | #[label(parser::add_paren, parser::add_paren)] | ^^^^^^^^^^^^^^^^^ @@ -183,133 +195,225 @@ LL | #[label(parser::add_paren, parser::add_paren)] = help: a diagnostic slug must be the first argument to the attribute error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:324:5 + --> $DIR/subdiagnostic-derive.rs:334:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:321:5 + --> $DIR/subdiagnostic-derive.rs:331:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:330:8 + --> $DIR/subdiagnostic-derive.rs:340:8 | LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:367:47 + --> $DIR/subdiagnostic-derive.rs:377:47 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:367:33 + --> $DIR/subdiagnostic-derive.rs:377:33 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:385:5 + --> $DIR/subdiagnostic-derive.rs:395:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:382:5 + --> $DIR/subdiagnostic-derive.rs:392:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:396:5 + --> $DIR/subdiagnostic-derive.rs:405:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ -error: suggestion without `applicability` - --> $DIR/subdiagnostic-derive.rs:391:1 +error: suggestion without `code = "..."` + --> $DIR/subdiagnostic-derive.rs:418:1 + | +LL | #[suggestion(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: invalid applicability + --> $DIR/subdiagnostic-derive.rs:428:46 | -LL | / #[suggestion(parser::add_paren, code = "...")] -LL | | -LL | | struct AL { -LL | | #[primary_span] -... | -LL | | applicability: Span, -LL | | } - | |_^ +LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^ -error: suggestion without `applicability` - --> $DIR/subdiagnostic-derive.rs:402:1 +error: suggestion without `#[primary_span]` field + --> $DIR/subdiagnostic-derive.rs:446:1 | LL | / #[suggestion(parser::add_paren, code = "...")] LL | | -LL | | struct AM { -LL | | #[primary_span] -LL | | span: Span, +LL | | struct AR { +LL | | var: String, LL | | } | |_^ -error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:410:1 +error: unsupported type attribute for subdiagnostic enum + --> $DIR/subdiagnostic-derive.rs:460:1 + | +LL | #[label] + | ^^^^^^^^ + +error: `var` doesn't refer to a field on this type + --> $DIR/subdiagnostic-derive.rs:480:39 + | +LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] + | ^^^^^^^ + +error: `var` doesn't refer to a field on this type + --> $DIR/subdiagnostic-derive.rs:499:43 + | +LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] + | ^^^^^^^ + +error: `#[suggestion_part]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:522:5 + | +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:525:5 + | +LL | #[suggestion_part(code = "...")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[suggestion_part(...)]` is only valid in multipart suggestions + +error: suggestion without `#[primary_span]` field + --> $DIR/subdiagnostic-derive.rs:519:1 | -LL | / #[suggestion(parser::add_paren)] +LL | / #[suggestion(parser::add_paren, code = "...")] LL | | -LL | | struct AN { -LL | | #[primary_span] +LL | | struct BA { +LL | | #[suggestion_part] ... | -LL | | applicability: Applicability, +LL | | var: String, LL | | } | |_^ -error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:420:46 +error: `code` is not a valid nested attribute of a `multipart_suggestion` attribute + --> $DIR/subdiagnostic-derive.rs:534:43 | -LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] + | ^^^^^^^^^^^^ -error: suggestion without `applicability` - --> $DIR/subdiagnostic-derive.rs:438:1 +error: multipart suggestion without any `#[suggestion_part(...)]` fields + --> $DIR/subdiagnostic-derive.rs:534:1 | -LL | / #[suggestion(parser::add_paren, code = "...")] +LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] LL | | LL | | -LL | | struct AR { +LL | | struct BBa { LL | | var: String, LL | | } | |_^ -error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:438:1 +error: `#[suggestion_part(...)]` attribute without `code = "..."` + --> $DIR/subdiagnostic-derive.rs:544:5 | -LL | / #[suggestion(parser::add_paren, code = "...")] +LL | #[suggestion_part] + | ^^^^^^^^^^^^^^^^^^ + +error: `#[suggestion_part(...)]` attribute without `code = "..."` + --> $DIR/subdiagnostic-derive.rs:552:5 + | +LL | #[suggestion_part()] + | ^^^^^^^^^^^^^^^^^^^^ + +error: `#[primary_span]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:561:5 + | +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:558:1 + | +LL | / #[multipart_suggestion(parser::add_paren)] LL | | +LL | | struct BC { +LL | | #[primary_span] LL | | -LL | | struct AR { -LL | | var: String, +LL | | span: Span, LL | | } | |_^ -error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:453:1 +error: `#[suggestion_part(...)]` attribute without `code = "..."` + --> $DIR/subdiagnostic-derive.rs:569:5 | -LL | #[label] - | ^^^^^^^^ +LL | #[suggestion_part] + | ^^^^^^^^^^^^^^^^^^ -error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:473:39 +error: `#[suggestion_part(...)]` attribute without `code = "..."` + --> $DIR/subdiagnostic-derive.rs:572:5 | -LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] - | ^^^^^^^ +LL | #[suggestion_part()] + | ^^^^^^^^^^^^^^^^^^^^ -error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:492:43 +error: `#[suggestion_part(foo = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:575:23 | -LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] - | ^^^^^^^ +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:578:5 + | +LL | #[suggestion_part(code = "...")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + --> $DIR/subdiagnostic-derive.rs:581:5 + | +LL | #[suggestion_part()] + | ^^^^^^^^^^^^^^^^^^^^ + +error: specified multiple times + --> $DIR/subdiagnostic-derive.rs:589:37 + | +LL | #[suggestion_part(code = "...", code = ",,,")] + | ^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive.rs:589:23 + | +LL | #[suggestion_part(code = "...", code = ",,,")] + | ^^^^^^^^^^^^ + +error: specified multiple times + --> $DIR/subdiagnostic-derive.rs:619:5 + | +LL | #[applicability] + | ^^^^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive.rs:616:43 + | +LL | #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `foo` in this scope --> $DIR/subdiagnostic-derive.rs:63:3 @@ -371,6 +475,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent` LL | #[label(slug)] | ^^^^ not found in `rustc_errors::fluent` -error: aborting due to 50 previous errors +error: aborting due to 64 previous errors For more information about this error, try `rustc --explain E0425`. From d9b874c083936fa14d139fec243f9df0897fdf09 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 1 Sep 2022 20:53:59 +0200 Subject: [PATCH 35/38] Allow deriving multiple subdiagnostics using one SessionSubdiagnostic This reimplements ac638c1, which had to be reverted in the previous commit because it contains a rebase accident that itself reverted significant unrelated changes to SessionSubdiagnostic. --- .../src/diagnostics/subdiagnostic.rs | 216 ++++++++++-------- .../subdiagnostic-derive.rs | 2 - .../subdiagnostic-derive.stderr | 80 +++---- 3 files changed, 154 insertions(+), 144 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 8b40e295bd8a7..dce5d3cfb84ff 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -211,11 +211,39 @@ impl<'a> HasFieldMap for SessionSubdiagnosticDeriveBuilder<'a> { } } +/// Provides frequently-needed information about the diagnostic kinds being derived for this type. +#[derive(Clone, Copy, Debug)] +struct KindsStatistics { + has_multipart_suggestion: bool, + all_multipart_suggestions: bool, + has_normal_suggestion: bool, +} + +impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics { + fn from_iter>(kinds: T) -> Self { + let mut ret = Self { + has_multipart_suggestion: false, + all_multipart_suggestions: true, + has_normal_suggestion: false, + }; + for kind in kinds { + if let SubdiagnosticKind::MultipartSuggestion { .. } = kind { + ret.has_multipart_suggestion = true; + } else { + ret.all_multipart_suggestions = false; + } + + if let SubdiagnosticKind::Suggestion { .. } = kind { + ret.has_normal_suggestion = true; + } + } + ret + } +} + impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { - fn identify_kind( - &mut self, - ) -> Result, DiagnosticDeriveError> { - let mut kind_slug = None; + fn identify_kind(&mut self) -> Result, DiagnosticDeriveError> { + let mut kind_slugs = vec![]; for attr in self.variant.ast().attrs { let span = attr.span().unwrap(); @@ -362,10 +390,10 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { | SubdiagnosticKind::MultipartSuggestion { .. } => {} } - kind_slug.set_once(((kind, slug), span)) + kind_slugs.push((kind, slug)) } - Ok(kind_slug.map(|(kind_slug, _)| kind_slug)) + Ok(kind_slugs) } /// Generates the code for a field with no attributes. @@ -387,7 +415,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { fn generate_field_attr_code( &mut self, binding: &BindingInfo<'_>, - kind: &SubdiagnosticKind, + kind_stats: KindsStatistics, ) -> TokenStream { let ast = binding.ast(); assert!(ast.attrs.len() > 0, "field without attributes generating attr code"); @@ -405,7 +433,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { }; let generated = self - .generate_field_code_inner(kind, attr, info) + .generate_field_code_inner(kind_stats, attr, info) .unwrap_or_else(|v| v.to_compile_error()); inner_ty.with(binding, generated) @@ -415,15 +443,15 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { fn generate_field_code_inner( &mut self, - kind: &SubdiagnosticKind, + kind_stats: KindsStatistics, attr: &Attribute, info: FieldInfo<'_>, ) -> Result { let meta = attr.parse_meta()?; match meta { - Meta::Path(path) => self.generate_field_code_inner_path(kind, attr, info, path), + Meta::Path(path) => self.generate_field_code_inner_path(kind_stats, attr, info, path), Meta::List(list @ MetaList { .. }) => { - self.generate_field_code_inner_list(kind, attr, info, list) + self.generate_field_code_inner_list(kind_stats, attr, info, list) } _ => throw_invalid_attr!(attr, &meta), } @@ -432,7 +460,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { /// Generates the code for a `[Meta::Path]`-like attribute on a field (e.g. `#[primary_span]`). fn generate_field_code_inner_path( &mut self, - kind: &SubdiagnosticKind, + kind_stats: KindsStatistics, attr: &Attribute, info: FieldInfo<'_>, path: Path, @@ -445,7 +473,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { match name { "skip_arg" => Ok(quote! {}), "primary_span" => { - if matches!(kind, SubdiagnosticKind::MultipartSuggestion { .. }) { + if kind_stats.has_multipart_suggestion { throw_invalid_attr!(attr, &Meta::Path(path), |diag| { diag.help( "multipart suggestions use one or more `#[suggestion_part]`s rather \ @@ -464,32 +492,20 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { "suggestion_part" => { self.has_suggestion_parts = true; - match kind { - SubdiagnosticKind::MultipartSuggestion { .. } => { - span_err( - span, - "`#[suggestion_part(...)]` attribute without `code = \"...\"`", - ) + if kind_stats.has_multipart_suggestion { + span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") .emit(); - Ok(quote! {}) - } - SubdiagnosticKind::Label - | SubdiagnosticKind::Note - | SubdiagnosticKind::Help - | SubdiagnosticKind::Warn - | SubdiagnosticKind::Suggestion { .. } => { - throw_invalid_attr!(attr, &Meta::Path(path), |diag| { - diag.help( + Ok(quote! {}) + } else { + throw_invalid_attr!(attr, &Meta::Path(path), |diag| { + diag.help( "`#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead", ) - }); - } + }); } } "applicability" => { - if let SubdiagnosticKind::Suggestion { .. } - | SubdiagnosticKind::MultipartSuggestion { .. } = kind - { + if kind_stats.has_multipart_suggestion || kind_stats.has_normal_suggestion { report_error_if_not_applied_to_applicability(attr, &info)?; let binding = info.binding.binding.clone(); @@ -501,13 +517,16 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { Ok(quote! {}) } _ => throw_invalid_attr!(attr, &Meta::Path(path), |diag| { - let span_attr = if let SubdiagnosticKind::MultipartSuggestion { .. } = kind { - "suggestion_part" - } else { - "primary_span" - }; + let mut span_attrs = vec![]; + if kind_stats.has_multipart_suggestion { + span_attrs.push("suggestion_part"); + } + if !kind_stats.all_multipart_suggestions { + span_attrs.push("primary_span") + } diag.help(format!( - "only `{span_attr}`, `applicability` and `skip_arg` are valid field attributes", + "only `{}`, `applicability` and `skip_arg` are valid field attributes", + span_attrs.join(", ") )) }), } @@ -517,7 +536,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { /// `#[suggestion_part(code = "...")]`). fn generate_field_code_inner_list( &mut self, - kind: &SubdiagnosticKind, + kind_stats: KindsStatistics, attr: &Attribute, info: FieldInfo<'_>, list: MetaList, @@ -529,7 +548,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { match name { "suggestion_part" => { - if !matches!(kind, SubdiagnosticKind::MultipartSuggestion { .. }) { + if !kind_stats.has_multipart_suggestion { throw_invalid_attr!(attr, &Meta::List(list), |diag| { diag.help( "`#[suggestion_part(...)]` is only valid in multipart suggestions", @@ -576,35 +595,36 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { Ok(quote! { suggestions.push((#binding, #code)); }) } _ => throw_invalid_attr!(attr, &Meta::List(list), |diag| { - let span_attr = if let SubdiagnosticKind::MultipartSuggestion { .. } = kind { - "suggestion_part" - } else { - "primary_span" - }; + let mut span_attrs = vec![]; + if kind_stats.has_multipart_suggestion { + span_attrs.push("suggestion_part"); + } + if !kind_stats.all_multipart_suggestions { + span_attrs.push("primary_span") + } diag.help(format!( - "only `{span_attr}`, `applicability` and `skip_arg` are valid field attributes", + "only `{}`, `applicability` and `skip_arg` are valid field attributes", + span_attrs.join(", ") )) }), } } pub fn into_tokens(&mut self) -> Result { - let Some((kind, slug)) = self.identify_kind()? else { + let kind_slugs = self.identify_kind()?; + if kind_slugs.is_empty() { throw_span_err!( self.variant.ast().ident.span().unwrap(), "subdiagnostic kind not specified" ); }; - let init = match &kind { - SubdiagnosticKind::Label - | SubdiagnosticKind::Note - | SubdiagnosticKind::Help - | SubdiagnosticKind::Warn - | SubdiagnosticKind::Suggestion { .. } => quote! {}, - SubdiagnosticKind::MultipartSuggestion { .. } => { - quote! { let mut suggestions = Vec::new(); } - } + let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect(); + + let init = if kind_stats.has_multipart_suggestion { + quote! { let mut suggestions = Vec::new(); } + } else { + quote! {} }; let attr_args: TokenStream = self @@ -612,7 +632,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { .bindings() .iter() .filter(|binding| !binding.ast().attrs.is_empty()) - .map(|binding| self.generate_field_attr_code(binding, &kind)) + .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); let span_field = self.span_field.as_ref().map(|(span, _)| span); @@ -622,48 +642,52 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { ); let diag = &self.diag; - let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); - let message = quote! { rustc_errors::fluent::#slug }; - let call = match kind { - SubdiagnosticKind::Suggestion { suggestion_kind, code } => { - if let Some(span) = span_field { - let style = suggestion_kind.to_suggestion_style(); - - quote! { #diag.#name(#span, #message, #code, #applicability, #style); } - } else { - span_err(self.span, "suggestion without `#[primary_span]` field").emit(); - quote! { unreachable!(); } - } - } - SubdiagnosticKind::MultipartSuggestion { suggestion_kind } => { - if !self.has_suggestion_parts { - span_err( - self.span, - "multipart suggestion without any `#[suggestion_part(...)]` fields", - ) - .emit(); + let mut calls = TokenStream::new(); + for (kind, slug) in kind_slugs { + let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); + let message = quote! { rustc_errors::fluent::#slug }; + let call = match kind { + SubdiagnosticKind::Suggestion { suggestion_kind, code } => { + if let Some(span) = span_field { + let style = suggestion_kind.to_suggestion_style(); + + quote! { #diag.#name(#span, #message, #code, #applicability, #style); } + } else { + span_err(self.span, "suggestion without `#[primary_span]` field").emit(); + quote! { unreachable!(); } + } } + SubdiagnosticKind::MultipartSuggestion { suggestion_kind } => { + if !self.has_suggestion_parts { + span_err( + self.span, + "multipart suggestion without any `#[suggestion_part(...)]` fields", + ) + .emit(); + } - let style = suggestion_kind.to_suggestion_style(); + let style = suggestion_kind.to_suggestion_style(); - quote! { #diag.#name(#message, suggestions, #applicability, #style); } - } - SubdiagnosticKind::Label => { - if let Some(span) = span_field { - quote! { #diag.#name(#span, #message); } - } else { - span_err(self.span, "label without `#[primary_span]` field").emit(); - quote! { unreachable!(); } + quote! { #diag.#name(#message, suggestions, #applicability, #style); } } - } - _ => { - if let Some(span) = span_field { - quote! { #diag.#name(#span, #message); } - } else { - quote! { #diag.#name(#message); } + SubdiagnosticKind::Label => { + if let Some(span) = span_field { + quote! { #diag.#name(#span, #message); } + } else { + span_err(self.span, "label without `#[primary_span]` field").emit(); + quote! { unreachable!(); } + } } - } - }; + _ => { + if let Some(span) = span_field { + quote! { #diag.#name(#span, #message); } + } else { + quote! { #diag.#name(#message); } + } + } + }; + calls.extend(call); + } let plain_args: TokenStream = self .variant @@ -676,7 +700,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { Ok(quote! { #init #attr_args - #call + #calls #plain_args }) } diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 89eaec78c6f11..812ca0c72bd05 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -309,9 +309,7 @@ union AC { #[derive(SessionSubdiagnostic)] #[label(parser::add_paren)] -//~^ NOTE previously specified here #[label(parser::add_paren)] -//~^ ERROR specified multiple times struct AD { #[primary_span] span: Span, diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 75a34f44bbe72..0a0247e898088 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -174,20 +174,8 @@ LL | | b: u64 LL | | } | |_^ -error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:313:1 - | -LL | #[label(parser::add_paren)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:311:1 - | -LL | #[label(parser::add_paren)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: `#[label(parser::add_paren)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:321:28 + --> $DIR/subdiagnostic-derive.rs:319:28 | LL | #[label(parser::add_paren, parser::add_paren)] | ^^^^^^^^^^^^^^^^^ @@ -195,67 +183,67 @@ LL | #[label(parser::add_paren, parser::add_paren)] = help: a diagnostic slug must be the first argument to the attribute error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:334:5 + --> $DIR/subdiagnostic-derive.rs:332:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:331:5 + --> $DIR/subdiagnostic-derive.rs:329:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:340:8 + --> $DIR/subdiagnostic-derive.rs:338:8 | LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:377:47 + --> $DIR/subdiagnostic-derive.rs:375:47 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:377:33 + --> $DIR/subdiagnostic-derive.rs:375:33 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:395:5 + --> $DIR/subdiagnostic-derive.rs:393:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:392:5 + --> $DIR/subdiagnostic-derive.rs:390:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:405:5 + --> $DIR/subdiagnostic-derive.rs:403:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:418:1 + --> $DIR/subdiagnostic-derive.rs:416:1 | LL | #[suggestion(parser::add_paren)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:428:46 + --> $DIR/subdiagnostic-derive.rs:426:46 | LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")] | ^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:446:1 + --> $DIR/subdiagnostic-derive.rs:444:1 | LL | / #[suggestion(parser::add_paren, code = "...")] LL | | @@ -265,25 +253,25 @@ LL | | } | |_^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:460:1 + --> $DIR/subdiagnostic-derive.rs:458:1 | LL | #[label] | ^^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:480:39 + --> $DIR/subdiagnostic-derive.rs:478:39 | LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:499:43 + --> $DIR/subdiagnostic-derive.rs:497:43 | LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:522:5 + --> $DIR/subdiagnostic-derive.rs:520:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ @@ -291,7 +279,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:525:5 + --> $DIR/subdiagnostic-derive.rs:523:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -299,7 +287,7 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:519:1 + --> $DIR/subdiagnostic-derive.rs:517:1 | LL | / #[suggestion(parser::add_paren, code = "...")] LL | | @@ -311,13 +299,13 @@ LL | | } | |_^ error: `code` is not a valid nested attribute of a `multipart_suggestion` attribute - --> $DIR/subdiagnostic-derive.rs:534:43 + --> $DIR/subdiagnostic-derive.rs:532:43 | LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] | ^^^^^^^^^^^^ error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:534:1 + --> $DIR/subdiagnostic-derive.rs:532:1 | LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] LL | | @@ -328,19 +316,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:544:5 + --> $DIR/subdiagnostic-derive.rs:542:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:552:5 + --> $DIR/subdiagnostic-derive.rs:550:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:561:5 + --> $DIR/subdiagnostic-derive.rs:559:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -348,7 +336,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:558:1 + --> $DIR/subdiagnostic-derive.rs:556:1 | LL | / #[multipart_suggestion(parser::add_paren)] LL | | @@ -360,19 +348,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:569:5 + --> $DIR/subdiagnostic-derive.rs:567:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:572:5 + --> $DIR/subdiagnostic-derive.rs:570:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(foo = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:575:23 + --> $DIR/subdiagnostic-derive.rs:573:23 | LL | #[suggestion_part(foo = "bar")] | ^^^^^^^^^^^ @@ -380,37 +368,37 @@ 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:578:5 + --> $DIR/subdiagnostic-derive.rs:576:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:581:5 + --> $DIR/subdiagnostic-derive.rs:579:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:589:37 + --> $DIR/subdiagnostic-derive.rs:587:37 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:589:23 + --> $DIR/subdiagnostic-derive.rs:587:23 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:619:5 + --> $DIR/subdiagnostic-derive.rs:617:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:616:43 + --> $DIR/subdiagnostic-derive.rs:614:43 | LL | #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -475,6 +463,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent` LL | #[label(slug)] | ^^^^ not found in `rustc_errors::fluent` -error: aborting due to 64 previous errors +error: aborting due to 63 previous errors For more information about this error, try `rustc --explain E0425`. From 096efc29f1be25daca6675f5f7684780ff294613 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 1 Sep 2022 13:06:24 -0700 Subject: [PATCH 36/38] rustdoc: remove unused CSS `#main-content > .since` This rule was added (actually, it was called `#main > .since` back then) with cdca0843779eed0b9046e9fee48c91458ad51605 and you can see an example of the bug it's intended to fix in by looking at the `1.0.0` version marker. However, a5a2f2b951ea982a666eaf52b1874d8f1b17290b changed it so that `` is always placed in an out-of-band wrapper, so it's never nested directly below `#main` / `#main-content` any more. --- src/librustdoc/html/static/css/rustdoc.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index deed6eaf0cb6b..3198347ce7fa9 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -216,7 +216,6 @@ details.rustdoc-toggle > summary::before, div.impl-items > div:not(.docblock):not(.item-info), .content ul.crate a.crate, a.srclink, -#main-content > .since, #help-button > button, details.rustdoc-toggle.top-doc > summary, details.rustdoc-toggle.top-doc > summary::before, From 1cd28639c9773474bf447375a74b5c2491014c56 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 1 Sep 2022 20:49:12 -0500 Subject: [PATCH 37/38] Add autolabels for `A-query-system` --- triagebot.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 8a90bc0e3c143..89d1574726f09 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -195,6 +195,13 @@ trigger_files = [ "compiler/rustc_macros/src/diagnostics" ] +[autolabel."A-query-system"] +trigger_files = [ + "compiler/rustc_query_system", + "compiler/rustc_query_impl", + "compiler/rustc_macros/src/query.rs" +] + [notify-zulip."I-prioritize"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts topic = "#{number} {title}" From e5d60af3c6f44be48371e32ef553416d277c92ec Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Sat, 20 Aug 2022 21:47:53 -0700 Subject: [PATCH 38/38] Simplify MIR opt tests This commit removes many cases of MIR opt tests emitting `.diff`s for more than one pass. These tests cannot be `unit-test`s, and so they are easy to break, and they also provide little value due to having excessively strong opinions over *how* a piece of code should be optimized. Where reasonable, we instead add separate test files that only emit the `PreCodegen.after` MIR for code where we want to track what the result of the net result of the optimization pipeline's output is. --- .../mir-opt/early_otherwise_branch_68867.rs | 5 +- ...re-SimplifyConstCondition-final.after.diff | 322 ------------------ ...ch_68867.try_sum.EarlyOtherwiseBranch.diff | 12 +- src/test/mir-opt/issue-73223.rs | 1 - .../issue_73223.main.PreCodegen.32bit.diff | 117 ------- .../issue_73223.main.PreCodegen.64bit.diff | 117 ------- ...wer_array_len.array_bound.InstCombine.diff | 66 ---- ..._array_len.array_bound.SimplifyLocals.diff | 70 ---- ...array_len.array_bound_mut.InstCombine.diff | 79 ----- ...ay_len.array_bound_mut.SimplifyLocals.diff | 93 ----- ...lower_array_len.array_len.InstCombine.diff | 27 -- ...er_array_len.array_len.SimplifyLocals.diff | 22 -- ...ay_len.array_len_by_value.InstCombine.diff | 26 -- ...len.array_len_by_value.SimplifyLocals.diff | 22 -- src/test/mir-opt/lower_array_len.rs | 11 +- ...y_len_e2e.array_bound.PreCodegen.after.mir | 49 +++ ...n_e2e.array_bound_mut.PreCodegen.after.mir | 62 ++++ ...ray_len_e2e.array_len.PreCodegen.after.mir | 11 + ...2e.array_len_by_value.PreCodegen.after.mir | 11 + src/test/mir-opt/lower_array_len_e2e.rs | 39 +++ ...r_intrinsics.align_of.LowerIntrinsics.diff | 2 +- ...trinsics.discriminant.LowerIntrinsics.diff | 20 +- ...wer_intrinsics.forget.LowerIntrinsics.diff | 2 +- ..._intrinsics.non_const.LowerIntrinsics.diff | 2 +- src/test/mir-opt/lower_intrinsics.rs | 31 +- ...er_intrinsics.size_of.LowerIntrinsics.diff | 2 +- ...ntrinsics.unreachable.LowerIntrinsics.diff | 2 +- ...r_intrinsics.wrapping.LowerIntrinsics.diff | 6 +- ...intrinsics_e2e.f_u64.PreCodegen.after.mir} | 38 +-- ...ntrinsics_e2e.f_unit.PreCodegen.after.mir} | 34 +- src/test/mir-opt/lower_intrinsics_e2e.rs | 32 ++ ...s.bar.MatchBranchSimplification.32bit.diff | 4 +- ...s.bar.MatchBranchSimplification.64bit.diff | 4 +- ...s.foo.MatchBranchSimplification.32bit.diff | 45 ++- ...s.foo.MatchBranchSimplification.64bit.diff | 45 ++- ...e_branches.foo.PreCodegen.before.32bit.mir | 10 - ...e_branches.foo.PreCodegen.before.64bit.mir | 10 - ...ed_if.MatchBranchSimplification.32bit.diff | 101 +++++- ...ed_if.MatchBranchSimplification.64bit.diff | 101 +++++- src/test/mir-opt/matches_reduce_branches.rs | 3 +- src/test/mir-opt/matches_u8.rs | 2 + ...t_switch.identity.SeparateConstSwitch.diff | 4 +- src/test/mir-opt/separate_const_switch.rs | 4 - src/test/mir-opt/simplify-arm-identity.rs | 3 + src/test/mir-opt/simplify-arm.rs | 3 + ...ocals-removes-unused-discriminant-reads.rs | 2 +- .../simplify_arm.id.SimplifyArmIdentity.diff | 46 --- .../simplify_arm.id.SimplifyBranchSame.diff | 46 --- ...ify_arm.id_result.SimplifyArmIdentity.diff | 58 ---- ...lify_arm.id_result.SimplifyBranchSame.diff | 58 ---- ...entity.main.SimplifyArmIdentity.32bit.diff | 61 ---- ...entity.main.SimplifyArmIdentity.64bit.diff | 61 ---- ...minant_reads.map.SimplifyLocals.32bit.diff | 17 +- ...minant_reads.map.SimplifyLocals.64bit.diff | 17 +- src/test/mir-opt/simplify_try.rs | 30 -- .../try_identity_e2e.new.PreCodegen.after.mir | 96 ++++++ .../try_identity_e2e.old.PreCodegen.after.mir | 53 +++ src/test/mir-opt/try_identity_e2e.rs | 34 ++ 58 files changed, 742 insertions(+), 1509 deletions(-) delete mode 100644 src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff delete mode 100644 src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff delete mode 100644 src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff delete mode 100644 src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff delete mode 100644 src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff delete mode 100644 src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff delete mode 100644 src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff delete mode 100644 src/test/mir-opt/lower_array_len.array_len.InstCombine.diff delete mode 100644 src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff delete mode 100644 src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff delete mode 100644 src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff create mode 100644 src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir create mode 100644 src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir create mode 100644 src/test/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir create mode 100644 src/test/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir create mode 100644 src/test/mir-opt/lower_array_len_e2e.rs rename src/test/mir-opt/{lower_intrinsics.f_u64.PreCodegen.before.mir => lower_intrinsics_e2e.f_u64.PreCodegen.after.mir} (68%) rename src/test/mir-opt/{lower_intrinsics.f_unit.PreCodegen.before.mir => lower_intrinsics_e2e.f_unit.PreCodegen.after.mir} (68%) create mode 100644 src/test/mir-opt/lower_intrinsics_e2e.rs delete mode 100644 src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.32bit.mir delete mode 100644 src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.64bit.mir delete mode 100644 src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff delete mode 100644 src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff delete mode 100644 src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff delete mode 100644 src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff delete mode 100644 src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff delete mode 100644 src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff delete mode 100644 src/test/mir-opt/simplify_try.rs create mode 100644 src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir create mode 100644 src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir create mode 100644 src/test/mir-opt/try_identity_e2e.rs diff --git a/src/test/mir-opt/early_otherwise_branch_68867.rs b/src/test/mir-opt/early_otherwise_branch_68867.rs index ca298e9211d48..a6a56f3a95d18 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.rs +++ b/src/test/mir-opt/early_otherwise_branch_68867.rs @@ -1,4 +1,6 @@ -// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts +// unit-test: EarlyOtherwiseBranch + +// FIXME: This test was broken by the derefer change. // example from #68867 type CSSFloat = f32; @@ -11,7 +13,6 @@ pub enum ViewportPercentageLength { } // EMIT_MIR early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff -// EMIT_MIR early_otherwise_branch_68867.try_sum EarlyOtherwiseBranch.before SimplifyConstCondition-final.after #[no_mangle] pub extern "C" fn try_sum( x: &ViewportPercentageLength, diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff deleted file mode 100644 index 8b37fb79f411b..0000000000000 --- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff +++ /dev/null @@ -1,322 +0,0 @@ -- // MIR for `try_sum` before EarlyOtherwiseBranch -+ // MIR for `try_sum` after SimplifyConstCondition-final - - fn try_sum(_1: &ViewportPercentageLength, _2: &ViewportPercentageLength) -> Result { - debug x => _1; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+1:5: +1:6 - debug other => _2; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+2:5: +2:10 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:+3:6: +3:42 - let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +11:6 - let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16 - let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23 - let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:21: +6:30 - let mut _8: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:21: +7:30 - let mut _9: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:23: +8:34 - let mut _10: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:23: +9:34 - let mut _11: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:11: +6:18 - let _12: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17 - let _13: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29 - let mut _14: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49 - let mut _15: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41 - let mut _16: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49 - let _17: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17 - let _18: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29 - let mut _19: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49 - let mut _20: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41 - let mut _21: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49 - let _22: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19 - let _23: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33 - let mut _24: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55 - let mut _25: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47 - let mut _26: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55 - let _27: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19 - let _28: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33 - let mut _29: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55 - let mut _30: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47 - let mut _31: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55 - let mut _32: !; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:14: +10:28 - let mut _33: (); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 - let mut _34: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _35: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _36: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _37: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _38: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _39: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _40: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _41: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _42: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _43: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _44: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _45: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - let mut _46: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - scope 1 { -- debug one => _12; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17 -- debug other => _13; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29 -+ debug one => _15; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17 -+ debug other => _16; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29 - } - scope 2 { -- debug one => _17; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17 -- debug other => _18; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29 -+ debug one => _20; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17 -+ debug other => _21; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29 - } - scope 3 { -- debug one => _22; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19 -- debug other => _23; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33 -+ debug one => _25; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19 -+ debug other => _26; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33 - } - scope 4 { -- debug one => _27; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19 -- debug other => _28; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33 -+ debug one => _30; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19 -+ debug other => _31; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33 - } - - bb0: { -- StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +11:6 -- StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 -- StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16 -- _5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +11:6 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16 -+ (_4.0: &ViewportPercentageLength) = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16 - StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23 - _6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23 - Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 -- (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24 -- StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24 - _34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - _11 = discriminant((*_34)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24 - } - - bb1: { - _35 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - _7 = discriminant((*_35)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24 - } - - bb2: { - StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 - nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 - Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 - nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 - discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 - StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28 -- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7 -- StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2 - return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 - } - - bb3: { - _36 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - _8 = discriminant((*_36)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24 - } - - bb4: { - _37 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - _9 = discriminant((*_37)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24 - } - - bb5: { - _38 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - _10 = discriminant((*_38)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24 - } - - bb6: { -- StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17 - _39 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17 -- _12 = (((*_39) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17 -- StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29 -+ _15 = (((*_39) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29 - _40 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29 -- _13 = (((*_40) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29 -- StorageLive(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49 -- StorageLive(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41 -- _15 = _12; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41 -- StorageLive(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49 -- _16 = _13; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49 -- _14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49 -- StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49 -- StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49 -- Deinit(_3); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 -- ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 -- discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 -- StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 -- StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 -- StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 -+ _16 = (((*_40) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49 -+ ((((_0 as Ok).0: ViewportPercentageLength) as Vw).0: f32) = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49 -+ Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 -+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 - goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 - } - - bb7: { -- StorageLive(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17 - _41 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17 -- _17 = (((*_41) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17 -- StorageLive(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29 -+ _20 = (((*_41) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29 - _42 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29 -- _18 = (((*_42) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29 -- StorageLive(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49 -- StorageLive(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41 -- _20 = _17; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41 -- StorageLive(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49 -- _21 = _18; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49 -- _19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49 -- StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49 -- StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49 -- Deinit(_3); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 -- ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 -- discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 -- StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 -- StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 -- StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 -+ _21 = (((*_42) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49 -+ ((((_0 as Ok).0: ViewportPercentageLength) as Vh).0: f32) = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49 -+ Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 -+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 - goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 - } - - bb8: { -- StorageLive(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19 - _43 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19 -- _22 = (((*_43) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19 -- StorageLive(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33 -+ _25 = (((*_43) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33 - _44 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33 -- _23 = (((*_44) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33 -- StorageLive(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55 -- StorageLive(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47 -- _25 = _22; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47 -- StorageLive(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55 -- _26 = _23; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55 -- _24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55 -- StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55 -- StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55 -- Deinit(_3); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 -- ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 -- discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 -- StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 -- StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 -- StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 -+ _26 = (((*_44) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55 -+ ((((_0 as Ok).0: ViewportPercentageLength) as Vmin).0: f32) = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55 -+ Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 -+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 - goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 - } - - bb9: { -- StorageLive(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19 - _45 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19 -- _27 = (((*_45) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19 -- StorageLive(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33 -+ _30 = (((*_45) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33 - _46 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33 -- _28 = (((*_46) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33 -- StorageLive(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55 -- StorageLive(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47 -- _30 = _27; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47 -- StorageLive(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55 -- _31 = _28; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55 -- _29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55 -- StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55 -- StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55 -- Deinit(_3); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 -- ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 -- discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 -- StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 -- StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 -- StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 -+ _31 = (((*_46) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55 -+ ((((_0 as Ok).0: ViewportPercentageLength) as Vmax).0: f32) = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55 -+ Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 -+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 - goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 - } - - bb10: { - Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7 -- ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7 - discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7 -- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7 -- StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2 - return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 - } - - bb11: { - unreachable; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 - } - } - diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index 50a58d4792a8d..6bc025bb5b204 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -80,7 +80,7 @@ StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24 _34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 _11 = discriminant((*_34)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24 + switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24 } bb1: { @@ -91,14 +91,14 @@ bb2: { StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 - nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 + Deinit(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 - nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 + ((_0 as Err).0: ()) = move _33; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28 StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2 - return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 + goto -> bb11; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 } bb3: { @@ -221,11 +221,11 @@ discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7 StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2 - return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 + goto -> bb11; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 } bb11: { - unreachable; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 + return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 } } diff --git a/src/test/mir-opt/issue-73223.rs b/src/test/mir-opt/issue-73223.rs index 703b876123133..9e731c4090879 100644 --- a/src/test/mir-opt/issue-73223.rs +++ b/src/test/mir-opt/issue-73223.rs @@ -10,4 +10,3 @@ fn main() { // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR issue_73223.main.SimplifyArmIdentity.diff -// EMIT_MIR issue_73223.main.PreCodegen.diff diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff deleted file mode 100644 index be8e86a832cb6..0000000000000 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff +++ /dev/null @@ -1,117 +0,0 @@ -- // MIR for `main` before PreCodegen -+ // MIR for `main` after PreCodegen - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - let _3: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _14: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _19: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 1 { - debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14 - let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - scope 3 { - debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14 - let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 4 { - debug left_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug right_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 5 { - debug kind => _13; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - } - } - } - scope 2 { - debug v => _3; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _1 = _3; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 - StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - StorageLive(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _6 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _7 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_5.0: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_5.1: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _8 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _9 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _10 = Not(move _11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb1: { - StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = _8; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _14 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } - } - - bb2: { - StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 - return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 - } - } - diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff deleted file mode 100644 index be8e86a832cb6..0000000000000 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ /dev/null @@ -1,117 +0,0 @@ -- // MIR for `main` before PreCodegen -+ // MIR for `main` after PreCodegen - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - let _3: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _14: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _19: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 1 { - debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14 - let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - scope 3 { - debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14 - let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 4 { - debug left_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug right_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 5 { - debug kind => _13; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - } - } - } - scope 2 { - debug v => _3; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _1 = _3; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 - StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - StorageLive(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _6 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _7 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_5.0: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_5.1: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _8 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _9 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _10 = Not(move _11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb1: { - StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = _8; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _14 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } - } - - bb2: { - StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 - return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 - } - } - diff --git a/src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff deleted file mode 100644 index 2589c9f282f33..0000000000000 --- a/src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff +++ /dev/null @@ -1,66 +0,0 @@ -- // MIR for `array_bound` before InstCombine -+ // MIR for `array_bound` after InstCombine - - fn array_bound(_1: usize, _2: &[u8; N]) -> u8 { - debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:36: +0:41 - debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:+0:50: +0:55 - let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:+0:70: +0:72 - let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 - let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - let mut _11: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - - bb0: { - StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - _4 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -+ _7 = _2; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - _11 = _7; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21 -- _5 = Len((*_11)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -+ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - } - - bb1: { - StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 - _8 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -- _9 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ _9 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - } - - bb2: { - _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6 - goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6 - } - - bb3: { - _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:11 - goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6 - } - - bb4: { - StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+5:5: +5:6 - return; // scope 0 at $DIR/lower_array_len.rs:+6:2: +6:2 - } - } - diff --git a/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff deleted file mode 100644 index 8312db6b37b35..0000000000000 --- a/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff +++ /dev/null @@ -1,70 +0,0 @@ -- // MIR for `array_bound` before SimplifyLocals -+ // MIR for `array_bound` after SimplifyLocals - - fn array_bound(_1: usize, _2: &[u8; N]) -> u8 { - debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:36: +0:41 - debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:+0:50: +0:55 - let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:+0:70: +0:72 - let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -- let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- let mut _11: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -+ let _6: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -+ let mut _7: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ let mut _8: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - - bb0: { - StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - _4 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21 - _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - } - - bb1: { -- StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -- _8 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -- _9 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -+ _6 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -+ _7 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - } - - bb2: { -- _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6 -+ _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6 - goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6 - } - - bb3: { - _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:11 - goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6 - } - - bb4: { - StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+5:5: +5:6 - return; // scope 0 at $DIR/lower_array_len.rs:+6:2: +6:2 - } - } - diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff deleted file mode 100644 index 401d4bac61e00..0000000000000 --- a/src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff +++ /dev/null @@ -1,79 +0,0 @@ -- // MIR for `array_bound_mut` before InstCombine -+ // MIR for `array_bound_mut` after InstCombine - - fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 { - debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:40: +0:45 - debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:+0:54: +0:59 - let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:+0:78: +0:80 - let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 - let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - let _11: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16 - let mut _12: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 - let mut _13: bool; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 - let mut _14: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - - bb0: { - StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - _4 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - _14 = _7; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21 -- _5 = Len((*_14)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -+ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 - StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - } - - bb1: { - StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 - _8 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -- _9 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ _9 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - } - - bb2: { - _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6 - goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6 - } - - bb3: { - StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16 - _11 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16 -- _12 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 -+ _12 = const N; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 - _13 = Lt(_11, _12); // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 - assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> bb4; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 - } - - bb4: { - (*_2)[_11] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:22 - StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+4:22: +4:23 - _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+6:9: +6:11 - goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6 - } - - bb5: { - StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+7:5: +7:6 - return; // scope 0 at $DIR/lower_array_len.rs:+8:2: +8:2 - } - } - diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff deleted file mode 100644 index 4f241d7c9064b..0000000000000 --- a/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff +++ /dev/null @@ -1,93 +0,0 @@ -- // MIR for `array_bound_mut` before SimplifyLocals -+ // MIR for `array_bound_mut` after SimplifyLocals - - fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 { - debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:40: +0:45 - debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:+0:54: +0:59 - let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:+0:78: +0:80 - let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -- let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- let _11: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16 -- let mut _12: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 -- let mut _13: bool; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 -- let mut _14: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -+ let _6: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -+ let mut _7: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ let mut _8: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ let _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16 -+ let mut _10: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 -+ let mut _11: bool; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 - - bb0: { - StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - _4 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13 - StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21 - _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27 -- StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27 - switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27 - } - - bb1: { -- StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -- _8 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -- _9 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -+ _6 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20 -+ _7 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 - } - - bb2: { -- _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -- StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6 -+ _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21 -+ StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6 - goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6 - } - - bb3: { -- StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16 -- _11 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16 -- _12 = const N; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 -- _13 = Lt(const 0_usize, _12); // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 -+ StorageLive(_9); // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16 -+ _9 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16 -+ _10 = const N; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 -+ _11 = Lt(const 0_usize, _10); // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 -+ assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17 - } - - bb4: { -- (*_2)[_11] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:22 -- StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+4:22: +4:23 -+ (*_2)[_9] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:22 -+ StorageDead(_9); // scope 0 at $DIR/lower_array_len.rs:+4:22: +4:23 - _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+6:9: +6:11 - goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6 - } - - bb5: { - StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+7:5: +7:6 - return; // scope 0 at $DIR/lower_array_len.rs:+8:2: +8:2 - } - } - diff --git a/src/test/mir-opt/lower_array_len.array_len.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_len.InstCombine.diff deleted file mode 100644 index 26f45be17be6f..0000000000000 --- a/src/test/mir-opt/lower_array_len.array_len.InstCombine.diff +++ /dev/null @@ -1,27 +0,0 @@ -- // MIR for `array_len` before InstCombine -+ // MIR for `array_len` after InstCombine - - fn array_len(_1: &[u8; N]) -> usize { - debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:34: +0:37 - let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:52: +0:57 - let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - - bb0: { - StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- _3 = &(*_1); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -+ _3 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - _4 = _3; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8 -- _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -+ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14 - return; // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff deleted file mode 100644 index 09d571d20a369..0000000000000 --- a/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff +++ /dev/null @@ -1,22 +0,0 @@ -- // MIR for `array_len` before SimplifyLocals -+ // MIR for `array_len` after SimplifyLocals - - fn array_len(_1: &[u8; N]) -> usize { - debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:34: +0:37 - let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:52: +0:57 -- let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - - bb0: { -- StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8 - _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14 - return; // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff deleted file mode 100644 index 843da758deb1c..0000000000000 --- a/src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `array_len_by_value` before InstCombine -+ // MIR for `array_len_by_value` after InstCombine - - fn array_len_by_value(_1: [u8; N]) -> usize { - debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:43: +0:46 - let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:60: +0:65 - let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - - bb0: { - StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - _3 = &_1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - _4 = _3; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8 -- _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -+ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14 - return; // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff deleted file mode 100644 index dc1c00b69c138..0000000000000 --- a/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff +++ /dev/null @@ -1,22 +0,0 @@ -- // MIR for `array_len_by_value` before SimplifyLocals -+ // MIR for `array_len_by_value` after SimplifyLocals - - fn array_len_by_value(_1: [u8; N]) -> usize { - debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:43: +0:46 - let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:60: +0:65 -- let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 - - bb0: { -- StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8 - _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14 -- StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14 - return; // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/lower_array_len.rs b/src/test/mir-opt/lower_array_len.rs index fc12ee75fcfcd..ea0224b21d72d 100644 --- a/src/test/mir-opt/lower_array_len.rs +++ b/src/test/mir-opt/lower_array_len.rs @@ -1,8 +1,7 @@ -// compile-flags: -Z mir-opt-level=4 +// unit-test: NormalizeArrayLen +// compile-flags: -Zmir-enable-passes=+LowerSliceLenCalls // EMIT_MIR lower_array_len.array_bound.NormalizeArrayLen.diff -// EMIT_MIR lower_array_len.array_bound.SimplifyLocals.diff -// EMIT_MIR lower_array_len.array_bound.InstCombine.diff pub fn array_bound(index: usize, slice: &[u8; N]) -> u8 { if index < slice.len() { slice[index] @@ -12,8 +11,6 @@ pub fn array_bound(index: usize, slice: &[u8; N]) -> u8 { } // EMIT_MIR lower_array_len.array_bound_mut.NormalizeArrayLen.diff -// EMIT_MIR lower_array_len.array_bound_mut.SimplifyLocals.diff -// EMIT_MIR lower_array_len.array_bound_mut.InstCombine.diff pub fn array_bound_mut(index: usize, slice: &mut [u8; N]) -> u8 { if index < slice.len() { slice[index] @@ -25,15 +22,11 @@ pub fn array_bound_mut(index: usize, slice: &mut [u8; N]) -> u8 } // EMIT_MIR lower_array_len.array_len.NormalizeArrayLen.diff -// EMIT_MIR lower_array_len.array_len.SimplifyLocals.diff -// EMIT_MIR lower_array_len.array_len.InstCombine.diff pub fn array_len(arr: &[u8; N]) -> usize { arr.len() } // EMIT_MIR lower_array_len.array_len_by_value.NormalizeArrayLen.diff -// EMIT_MIR lower_array_len.array_len_by_value.SimplifyLocals.diff -// EMIT_MIR lower_array_len.array_len_by_value.InstCombine.diff pub fn array_len_by_value(arr: [u8; N]) -> usize { arr.len() } diff --git a/src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir new file mode 100644 index 0000000000000..2c6c93cb1d83b --- /dev/null +++ b/src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir @@ -0,0 +1,49 @@ +// MIR for `array_bound` after PreCodegen + +fn array_bound(_1: usize, _2: &[u8; N]) -> u8 { + debug index => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:36: +0:41 + debug slice => _2; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:50: +0:55 + let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:70: +0:72 + let mut _3: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27 + let mut _4: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13 + let mut _5: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27 + let _6: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20 + let mut _7: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + let mut _8: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27 + StorageLive(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13 + _4 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13 + StorageLive(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27 + _5 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27 + _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27 + StorageDead(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27 + StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27 + switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27 + } + + bb1: { + StorageLive(_6); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20 + _6 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20 + _7 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + } + + bb2: { + _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + StorageDead(_6); // scope 0 at $DIR/lower_array_len_e2e.rs:+3:5: +3:6 + goto -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6 + } + + bb3: { + _0 = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:11 + goto -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6 + } + + bb4: { + StorageDead(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+5:5: +5:6 + return; // scope 0 at $DIR/lower_array_len_e2e.rs:+6:2: +6:2 + } +} diff --git a/src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir new file mode 100644 index 0000000000000..aee3a8242cdda --- /dev/null +++ b/src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir @@ -0,0 +1,62 @@ +// MIR for `array_bound_mut` after PreCodegen + +fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 { + debug index => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:40: +0:45 + debug slice => _2; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:54: +0:59 + let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:78: +0:80 + let mut _3: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27 + let mut _4: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13 + let mut _5: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27 + let _6: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20 + let mut _7: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + let mut _8: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + let _9: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16 + let mut _10: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17 + let mut _11: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27 + StorageLive(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13 + _4 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13 + StorageLive(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27 + _5 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27 + _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27 + StorageDead(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27 + StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27 + switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27 + } + + bb1: { + StorageLive(_6); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20 + _6 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20 + _7 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + } + + bb2: { + _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21 + StorageDead(_6); // scope 0 at $DIR/lower_array_len_e2e.rs:+3:5: +3:6 + goto -> bb5; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6 + } + + bb3: { + StorageLive(_9); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16 + _9 = const 0_usize; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16 + _10 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17 + _11 = Lt(const 0_usize, _10); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17 + assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17 + } + + bb4: { + (*_2)[_9] = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:22 + StorageDead(_9); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:22: +4:23 + _0 = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+6:9: +6:11 + goto -> bb5; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6 + } + + bb5: { + StorageDead(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+7:5: +7:6 + return; // scope 0 at $DIR/lower_array_len_e2e.rs:+8:2: +8:2 + } +} diff --git a/src/test/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir new file mode 100644 index 0000000000000..4b19f67955889 --- /dev/null +++ b/src/test/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir @@ -0,0 +1,11 @@ +// MIR for `array_len` after PreCodegen + +fn array_len(_1: &[u8; N]) -> usize { + debug arr => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:34: +0:37 + let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:52: +0:57 + + bb0: { + _0 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14 + return; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2 + } +} diff --git a/src/test/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir new file mode 100644 index 0000000000000..4dc0ba9a268ea --- /dev/null +++ b/src/test/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir @@ -0,0 +1,11 @@ +// MIR for `array_len_by_value` after PreCodegen + +fn array_len_by_value(_1: [u8; N]) -> usize { + debug arr => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:43: +0:46 + let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:60: +0:65 + + bb0: { + _0 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14 + return; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2 + } +} diff --git a/src/test/mir-opt/lower_array_len_e2e.rs b/src/test/mir-opt/lower_array_len_e2e.rs new file mode 100644 index 0000000000000..49b35d509f029 --- /dev/null +++ b/src/test/mir-opt/lower_array_len_e2e.rs @@ -0,0 +1,39 @@ +// compile-flags: -Z mir-opt-level=4 + +// EMIT_MIR lower_array_len_e2e.array_bound.PreCodegen.after.mir +pub fn array_bound(index: usize, slice: &[u8; N]) -> u8 { + if index < slice.len() { + slice[index] + } else { + 42 + } +} + +// EMIT_MIR lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir +pub fn array_bound_mut(index: usize, slice: &mut [u8; N]) -> u8 { + if index < slice.len() { + slice[index] + } else { + slice[0] = 42; + + 42 + } +} + +// EMIT_MIR lower_array_len_e2e.array_len.PreCodegen.after.mir +pub fn array_len(arr: &[u8; N]) -> usize { + arr.len() +} + +// EMIT_MIR lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir +pub fn array_len_by_value(arr: [u8; N]) -> usize { + arr.len() +} + +fn main() { + let _ = array_bound(3, &[0, 1, 2, 3]); + let mut tmp = [0, 1, 2, 3, 4]; + let _ = array_bound_mut(3, &mut [0, 1, 2, 3]); + let _ = array_len(&[0]); + let _ = array_len_by_value([0, 2]); +} diff --git a/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff index 5c635e2220ed7..3389db733b992 100644 --- a/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff @@ -7,7 +7,7 @@ bb0: { - _0 = std::intrinsics::min_align_of::() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:19:5: 19:40 +- // + span: $DIR/lower_intrinsics.rs:21:5: 21:40 - // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::}, val: Value() } + _0 = AlignOf(T); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42 + goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42 diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff index 8a80de32f3ae3..f92ff9faf9796 100644 --- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff @@ -31,7 +31,7 @@ _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 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:74:5: 74:41 +- // + span: $DIR/lower_intrinsics.rs:49:5: 49:41 - // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> ::Discriminant {discriminant_value::}, val: Value() } + _2 = discriminant((*_3)); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45 + goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45 @@ -46,13 +46,13 @@ StorageLive(_7); // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44 _19 = const discriminant::::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44 // mir::Constant - // + span: $DIR/lower_intrinsics.rs:75:42: 75:44 + // + span: $DIR/lower_intrinsics.rs:50:42: 50:44 // + 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 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:75:5: 75:41 +- // + span: $DIR/lower_intrinsics.rs:50:5: 50:41 - // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> ::Discriminant {discriminant_value::}, val: Value() } + _5 = discriminant((*_6)); // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45 + goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45 @@ -67,13 +67,13 @@ StorageLive(_11); // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45 _18 = const discriminant::::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45 // mir::Constant - // + span: $DIR/lower_intrinsics.rs:76:42: 76:45 + // + span: $DIR/lower_intrinsics.rs:51:42: 51:45 // + 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 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:76:5: 76:41 +- // + span: $DIR/lower_intrinsics.rs:51:5: 51:41 - // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value() } + _9 = discriminant((*_10)); // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46 + goto -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46 @@ -88,13 +88,13 @@ StorageLive(_15); // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47 _17 = const discriminant::::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47 // mir::Constant - // + span: $DIR/lower_intrinsics.rs:77:42: 77:47 + // + span: $DIR/lower_intrinsics.rs:52:42: 52:47 // + 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 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:77:5: 77:41 +- // + span: $DIR/lower_intrinsics.rs:52:5: 52:41 - // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> ::Discriminant {discriminant_value::}, val: Value() } + _13 = discriminant((*_14)); // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48 + goto -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48 @@ -105,11 +105,15 @@ StorageDead(_15); // scope 0 at $DIR/lower_intrinsics.rs:+4:48: +4:49 StorageDead(_13); // scope 0 at $DIR/lower_intrinsics.rs:+4:48: +4:49 _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:+0:30: +5:2 - drop(_1) -> bb5; // scope 0 at $DIR/lower_intrinsics.rs:+5:1: +5:2 + drop(_1) -> [return: bb5, unwind: bb6]; // scope 0 at $DIR/lower_intrinsics.rs:+5:1: +5:2 } bb5: { return; // scope 0 at $DIR/lower_intrinsics.rs:+5:2: +5:2 } + + bb6 (cleanup): { + resume; // scope 0 at $DIR/lower_intrinsics.rs:+0:1: +5:2 + } } diff --git a/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff index e6a2f6512f55a..4cbbc02c94333 100644 --- a/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff @@ -11,7 +11,7 @@ _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 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:24:5: 24:29 +- // + span: $DIR/lower_intrinsics.rs:26:5: 26:29 - // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::}, val: Value() } + _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32 + goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32 diff --git a/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff index 1ab2f2a0a0468..d8cd5f59a3532 100644 --- a/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff @@ -13,7 +13,7 @@ StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+2:9: +2:18 _1 = std::intrinsics::size_of::; // scope 0 at $DIR/lower_intrinsics.rs:+2:21: +2:51 // mir::Constant - // + span: $DIR/lower_intrinsics.rs:62:21: 62:51 + // + span: $DIR/lower_intrinsics.rs:37:21: 37:51 // + 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 diff --git a/src/test/mir-opt/lower_intrinsics.rs b/src/test/mir-opt/lower_intrinsics.rs index eab51b65f1a19..195543d42bb5b 100644 --- a/src/test/mir-opt/lower_intrinsics.rs +++ b/src/test/mir-opt/lower_intrinsics.rs @@ -1,4 +1,6 @@ -// compile-flags: -Cpanic=abort +// unit-test: LowerIntrinsics +// ignore-wasm32 compiled with panic=abort by default + #![feature(core_intrinsics)] #![crate_type = "lib"] @@ -29,33 +31,6 @@ pub fn unreachable() -> ! { unsafe { core::intrinsics::unreachable() }; } -// EMIT_MIR lower_intrinsics.f_unit.PreCodegen.before.mir -pub fn f_unit() { - f_dispatch(()); -} - - -// EMIT_MIR lower_intrinsics.f_u64.PreCodegen.before.mir -pub fn f_u64() { - f_dispatch(0u64); -} - -#[inline(always)] -pub fn f_dispatch(t: T) { - if std::mem::size_of::() == 0 { - f_zst(t); - } else { - f_non_zst(t); - } -} - -#[inline(never)] -pub fn f_zst(_t: T) { -} - -#[inline(never)] -pub fn f_non_zst(_t: T) {} - // EMIT_MIR lower_intrinsics.non_const.LowerIntrinsics.diff pub fn non_const() -> usize { // Check that lowering works with non-const operand as a func. diff --git a/src/test/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff index 11b27976b551c..cf0ab73a5d4b1 100644 --- a/src/test/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff @@ -7,7 +7,7 @@ bb0: { - _0 = std::intrinsics::size_of::() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:14:5: 14:35 +- // + span: $DIR/lower_intrinsics.rs:16:5: 16:35 - // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::}, val: Value() } + _0 = SizeOf(T); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37 + goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37 diff --git a/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff index ac077e85b04f3..6f17d44516de1 100644 --- a/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff @@ -14,7 +14,7 @@ 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 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:29:14: 29:43 +- // + span: $DIR/lower_intrinsics.rs:31:14: 31:43 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value() } + unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45 } diff --git a/src/test/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff index e0a5416b22b5f..22ef75fd80460 100644 --- a/src/test/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff @@ -32,7 +32,7 @@ _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 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:7:14: 7:44 +- // + span: $DIR/lower_intrinsics.rs:9:14: 9:44 - // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_add::}, val: Value() } + _3 = Add(move _4, move _5); // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50 + goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50 @@ -48,7 +48,7 @@ _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 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:8:14: 8:44 +- // + span: $DIR/lower_intrinsics.rs:10:14: 10:44 - // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_sub::}, val: Value() } + _6 = Sub(move _7, move _8); // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50 + goto -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50 @@ -64,7 +64,7 @@ _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 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:9:14: 9:44 +- // + span: $DIR/lower_intrinsics.rs:11:14: 11:44 - // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_mul::}, val: Value() } + _9 = Mul(move _10, move _11); // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50 + goto -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50 diff --git a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir similarity index 68% rename from src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir rename to src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir index 2a9a099a38d9c..8e185323e1a84 100644 --- a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir +++ b/src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir @@ -1,32 +1,32 @@ -// MIR for `f_u64` before PreCodegen +// MIR for `f_u64` after PreCodegen fn f_u64() -> () { - let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:16: +0:16 - let mut _1: u64; // in scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21 - scope 1 (inlined f_dispatch::) { // at $DIR/lower_intrinsics.rs:40:5: 40:21 - debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:44:22: 44:23 - let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21 - let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20 - scope 2 (inlined std::mem::size_of::) { // at $DIR/lower_intrinsics.rs:45:8: 45:32 + let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics_e2e.rs:+0:16: +0:16 + let mut _1: u64; // in scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21 + scope 1 (inlined f_dispatch::) { // at $DIR/lower_intrinsics_e2e.rs:15:5: 15:21 + debug t => _1; // in scope 1 at $DIR/lower_intrinsics_e2e.rs:19:22: 19:23 + let _2: (); // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21 + let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20 + scope 2 (inlined std::mem::size_of::) { // at $DIR/lower_intrinsics_e2e.rs:20:8: 20:32 } } bb0: { - StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21 - _1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21 - StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21 - StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20 - _3 = move _1; // scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20 - _2 = f_non_zst::(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21 + StorageLive(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21 + _1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21 + StorageLive(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21 + StorageLive(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20 + _3 = move _1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20 + _2 = f_non_zst::(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21 // mir::Constant - // + span: $DIR/lower_intrinsics.rs:48:9: 48:18 + // + span: $DIR/lower_intrinsics_e2e.rs:23:9: 23:18 // + literal: Const { ty: fn(u64) {f_non_zst::}, val: Value() } } bb1: { - StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:48:20: 48:21 - StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:48:21: 48:22 - StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21 - return; // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2 + StorageDead(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:20: 23:21 + StorageDead(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:21: 23:22 + StorageDead(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21 + return; // scope 0 at $DIR/lower_intrinsics_e2e.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir similarity index 68% rename from src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir rename to src/test/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir index 5783822f6b544..a5b396ca0bc7f 100644 --- a/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir +++ b/src/test/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir @@ -1,30 +1,30 @@ -// MIR for `f_unit` before PreCodegen +// MIR for `f_unit` after PreCodegen fn f_unit() -> () { - let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:17: +0:17 - let mut _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:+1:16: +1:18 - scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19 - debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:44:22: 44:23 - let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17 - let mut _3: (); // in scope 1 at $DIR/lower_intrinsics.rs:46:15: 46:16 - scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:45:8: 45:32 + let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics_e2e.rs:+0:17: +0:17 + let mut _1: (); // in scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:16: +1:18 + scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics_e2e.rs:9:5: 9:19 + debug t => _1; // in scope 1 at $DIR/lower_intrinsics_e2e.rs:19:22: 19:23 + let _2: (); // in scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17 + let mut _3: (); // in scope 1 at $DIR/lower_intrinsics_e2e.rs:21:15: 21:16 + scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics_e2e.rs:20:8: 20:32 } } bb0: { - StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:16: +1:18 - StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17 - StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:46:15: 46:16 - _2 = f_zst::<()>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17 + StorageLive(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:16: +1:18 + StorageLive(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17 + StorageLive(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:15: 21:16 + _2 = f_zst::<()>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17 // mir::Constant - // + span: $DIR/lower_intrinsics.rs:46:9: 46:14 + // + span: $DIR/lower_intrinsics_e2e.rs:21:9: 21:14 // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value() } } bb1: { - StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:46:16: 46:17 - StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:46:17: 46:18 - StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:18: +1:19 - return; // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2 + StorageDead(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:16: 21:17 + StorageDead(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:17: 21:18 + StorageDead(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:18: +1:19 + return; // scope 0 at $DIR/lower_intrinsics_e2e.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/lower_intrinsics_e2e.rs b/src/test/mir-opt/lower_intrinsics_e2e.rs new file mode 100644 index 0000000000000..872ef59b08183 --- /dev/null +++ b/src/test/mir-opt/lower_intrinsics_e2e.rs @@ -0,0 +1,32 @@ +// Checks that we do not have any branches in the MIR for the two tested functions. + +// compile-flags: -Cpanic=abort +#![feature(core_intrinsics)] +#![crate_type = "lib"] + +// EMIT_MIR lower_intrinsics_e2e.f_unit.PreCodegen.after.mir +pub fn f_unit() { + f_dispatch(()); +} + + +// EMIT_MIR lower_intrinsics_e2e.f_u64.PreCodegen.after.mir +pub fn f_u64() { + f_dispatch(0u64); +} + +#[inline(always)] +pub fn f_dispatch(t: T) { + if std::mem::size_of::() == 0 { + f_zst(t); + } else { + f_non_zst(t); + } +} + +#[inline(never)] +pub fn f_zst(_t: T) { +} + +#[inline(never)] +pub fn f_non_zst(_t: T) {} diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff index 2005c10efa93b..f9eeb1ea5b960 100644 --- a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff @@ -41,7 +41,7 @@ - _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22 - _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22 - _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21 -- nop; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 +- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 - goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 - } - @@ -54,7 +54,7 @@ + _3 = Eq(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21 _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22 _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21 -- nop; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 + Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 - goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 - } - diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff index 2005c10efa93b..f9eeb1ea5b960 100644 --- a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff @@ -41,7 +41,7 @@ - _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22 - _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22 - _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21 -- nop; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 +- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 - goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 - } - @@ -54,7 +54,7 @@ + _3 = Eq(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21 _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22 _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21 -- nop; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 + Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 - goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 - } - diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff index b7862e5678f23..0b40b3be8bdd4 100644 --- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff @@ -4,26 +4,51 @@ fn foo(_1: Option<()>) -> () { debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11 let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25 - let mut _2: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26 -+ let mut _3: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26 ++ let mut _4: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL bb0: { - _2 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20 -- switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- } -- -- bb1: { + StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _3 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20 +- switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ StorageLive(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ _4 = move _3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ _2 = Eq(_4, const 0_isize); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ StorageDead(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + } + + bb1: { +- _2 = const false; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb2: { +- _2 = const true; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb3: { -+ StorageLive(_3); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ _3 = move _2; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ StorageDead(_3); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- } +- +- bb4: { + Deinit(_0); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11 +- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 ++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 + } + +- bb5: { ++ bb2: { + _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:+3:6: +3:6 +- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 ++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 + } + +- bb6: { ++ bb3: { + StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+3:5: +3:6 return; // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff index b7862e5678f23..0b40b3be8bdd4 100644 --- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff @@ -4,26 +4,51 @@ fn foo(_1: Option<()>) -> () { debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11 let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25 - let mut _2: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26 -+ let mut _3: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26 ++ let mut _4: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL bb0: { - _2 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20 -- switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- } -- -- bb1: { + StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _3 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20 +- switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ StorageLive(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ _4 = move _3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ _2 = Eq(_4, const 0_isize); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ StorageDead(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + } + + bb1: { +- _2 = const false; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb2: { +- _2 = const true; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb3: { -+ StorageLive(_3); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ _3 = move _2; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ StorageDead(_3); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- } +- +- bb4: { + Deinit(_0); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11 +- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 ++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 + } + +- bb5: { ++ bb2: { + _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:+3:6: +3:6 +- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 ++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 + } + +- bb6: { ++ bb3: { + StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+3:5: +3:6 return; // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.32bit.mir b/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.32bit.mir deleted file mode 100644 index a36ec8de4a391..0000000000000 --- a/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.32bit.mir +++ /dev/null @@ -1,10 +0,0 @@ -// MIR for `foo` before PreCodegen - -fn foo(_1: Option<()>) -> () { - debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11 - let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25 - - bb0: { - return; // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2 - } -} diff --git a/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.64bit.mir b/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.64bit.mir deleted file mode 100644 index a36ec8de4a391..0000000000000 --- a/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.64bit.mir +++ /dev/null @@ -1,10 +0,0 @@ -// MIR for `foo` before PreCodegen - -fn foo(_1: Option<()>) -> () { - debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11 - let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25 - - bb0: { - return; // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2 - } -} diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff index 672c6b34e94b6..b8c7722cd3713 100644 --- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff @@ -4,36 +4,107 @@ fn match_nested_if() -> bool { let mut _0: bool; // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:29 let _1: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 - let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -+ let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 + let mut _2: (); // in scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 + let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 + let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 + let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 + let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ let mut _8: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 ++ let mut _9: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 ++ let mut _10: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 scope 1 { debug val => _1; // in scope 1 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 } bb0: { StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 - StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 - _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 + StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 + Deinit(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 + StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 + StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 + StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 + StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 + _6 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 +- switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 - } - - bb1: { -+ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -+ _3 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 - StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52 -- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 +- _5 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:31: +2:35 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 - } - - bb2: { -- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52 -- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 +- _5 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 - } - - bb3: { -+ _1 = Ne(_3, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 -+ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ _7 = move _6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ _5 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50 ++ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 + StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52 +- switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 +- } +- +- bb4: { +- _4 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:55: +2:59 +- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 +- } +- +- bb5: { +- _4 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74 +- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 +- } +- +- bb6: { ++ StorageLive(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 ++ _8 = move _5; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 ++ _4 = Ne(_8, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74 ++ StorageDead(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 + StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:75: +2:76 +- switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 +- } +- +- bb7: { +- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+3:13: +3:17 +- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 +- } +- +- bb8: { +- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18 +- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 +- } +- +- bb9: { +- switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 +- } +- +- bb10: { ++ StorageLive(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 ++ _9 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 ++ _3 = Ne(_9, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18 ++ StorageDead(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 ++ StorageLive(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 ++ _10 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 + StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 + StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 +- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 +- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 +- } +- +- bb11: { +- StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 +- StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 +- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 +- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 +- } +- +- bb12: { ++ _1 = Ne(_10, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 ++ StorageDead(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 + StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+11:6: +11:7 _0 = _1; // scope 1 at $DIR/matches_reduce_branches.rs:+12:5: +12:8 StorageDead(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+13:1: +13:2 return; // scope 0 at $DIR/matches_reduce_branches.rs:+13:2: +13:2 diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff index 672c6b34e94b6..b8c7722cd3713 100644 --- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff @@ -4,36 +4,107 @@ fn match_nested_if() -> bool { let mut _0: bool; // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:29 let _1: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 - let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -+ let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 + let mut _2: (); // in scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 + let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 + let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 + let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 + let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ let mut _8: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 ++ let mut _9: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 ++ let mut _10: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 scope 1 { debug val => _1; // in scope 1 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 } bb0: { StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 - StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 - _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 + StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 + Deinit(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 + StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 + StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 + StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 + StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 + _6 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 +- switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 - } - - bb1: { -+ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -+ _3 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 - StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52 -- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 +- _5 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:31: +2:35 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 - } - - bb2: { -- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52 -- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 +- _5 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 - } - - bb3: { -+ _1 = Ne(_3, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 -+ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ _7 = move _6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 ++ _5 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50 ++ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 + StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52 +- switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 +- } +- +- bb4: { +- _4 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:55: +2:59 +- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 +- } +- +- bb5: { +- _4 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74 +- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 +- } +- +- bb6: { ++ StorageLive(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 ++ _8 = move _5; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 ++ _4 = Ne(_8, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74 ++ StorageDead(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 + StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:75: +2:76 +- switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 +- } +- +- bb7: { +- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+3:13: +3:17 +- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 +- } +- +- bb8: { +- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18 +- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 +- } +- +- bb9: { +- switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 +- } +- +- bb10: { ++ StorageLive(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 ++ _9 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 ++ _3 = Ne(_9, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18 ++ StorageDead(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 ++ StorageLive(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 ++ _10 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 + StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 + StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 +- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 +- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 +- } +- +- bb11: { +- StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 +- StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 +- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 +- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 +- } +- +- bb12: { ++ _1 = Ne(_10, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 ++ StorageDead(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 + StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+11:6: +11:7 _0 = _1; // scope 1 at $DIR/matches_reduce_branches.rs:+12:5: +12:8 StorageDead(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+13:1: +13:2 return; // scope 0 at $DIR/matches_reduce_branches.rs:+13:2: +13:2 diff --git a/src/test/mir-opt/matches_reduce_branches.rs b/src/test/mir-opt/matches_reduce_branches.rs index 51be3884d48dd..c122b4c69d15a 100644 --- a/src/test/mir-opt/matches_reduce_branches.rs +++ b/src/test/mir-opt/matches_reduce_branches.rs @@ -1,6 +1,7 @@ +// unit-test: MatchBranchSimplification + // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR matches_reduce_branches.foo.MatchBranchSimplification.diff -// EMIT_MIR matches_reduce_branches.foo.PreCodegen.before.mir // EMIT_MIR matches_reduce_branches.bar.MatchBranchSimplification.diff // EMIT_MIR matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/matches_u8.rs b/src/test/mir-opt/matches_u8.rs index 78373be48b685..2c748b02a8b76 100644 --- a/src/test/mir-opt/matches_u8.rs +++ b/src/test/mir-opt/matches_u8.rs @@ -1,3 +1,5 @@ +// unit-test: MatchBranchSimplification + // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff // EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index b8c554d3ea6b0..f25b3ce724be2 100644 --- a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -15,7 +15,7 @@ scope 1 { debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10 scope 2 { - scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10 + scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { // at $DIR/separate_const_switch.rs:25:8: 25:10 debug residual => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL let _16: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL let mut _17: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL @@ -34,7 +34,7 @@ scope 4 { } } - scope 5 (inlined as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10 + scope 5 (inlined as Try>::branch) { // at $DIR/separate_const_switch.rs:25:8: 25:10 debug self => _4; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL let mut _10: isize; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL let _11: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL diff --git a/src/test/mir-opt/separate_const_switch.rs b/src/test/mir-opt/separate_const_switch.rs index 5d82acf4d6090..c809e5629cc15 100644 --- a/src/test/mir-opt/separate_const_switch.rs +++ b/src/test/mir-opt/separate_const_switch.rs @@ -4,8 +4,6 @@ use std::ops::ControlFlow; // EMIT_MIR separate_const_switch.too_complex.SeparateConstSwitch.diff -// EMIT_MIR separate_const_switch.too_complex.ConstProp.diff -// EMIT_MIR separate_const_switch.too_complex.PreCodegen.after.mir fn too_complex(x: Result) -> Option { // The pass should break the outer match into // two blocks that only have one parent each. @@ -23,8 +21,6 @@ fn too_complex(x: Result) -> Option { } // EMIT_MIR separate_const_switch.identity.SeparateConstSwitch.diff -// EMIT_MIR separate_const_switch.identity.ConstProp.diff -// EMIT_MIR separate_const_switch.identity.PreCodegen.after.mir fn identity(x: Result) -> Result { Ok(x?) } diff --git a/src/test/mir-opt/simplify-arm-identity.rs b/src/test/mir-opt/simplify-arm-identity.rs index bedc86bbacb8c..cf6ff57aa96de 100644 --- a/src/test/mir-opt/simplify-arm-identity.rs +++ b/src/test/mir-opt/simplify-arm-identity.rs @@ -4,6 +4,9 @@ // compile-flags: -Zmir-opt-level=3 // EMIT_MIR_FOR_EACH_BIT_WIDTH +// This pass is broken since deaggregation changed +// ignore-test + enum Src { Foo(u8), Bar, diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify-arm.rs index f7dcaa13449ea..c247872e2af46 100644 --- a/src/test/mir-opt/simplify-arm.rs +++ b/src/test/mir-opt/simplify-arm.rs @@ -6,6 +6,9 @@ // EMIT_MIR simplify_arm.id_try.SimplifyArmIdentity.diff // EMIT_MIR simplify_arm.id_try.SimplifyBranchSame.diff +// This pass is broken since deaggregation changed +// ignore-test + fn id(o: Option) -> Option { match o { Some(v) => Some(v), diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs index 84f57deccf7e0..62a15df04b144 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs +++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs @@ -1,4 +1,4 @@ -// compile-flags: -Zunsound-mir-opts +// unit-test: SimplifyLocals fn map(x: Option>) -> Option> { match x { diff --git a/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff deleted file mode 100644 index 9c3ad4b4df912..0000000000000 --- a/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff +++ /dev/null @@ -1,46 +0,0 @@ -- // MIR for `id` before SimplifyArmIdentity -+ // MIR for `id` after SimplifyArmIdentity - - fn id(_1: Option) -> Option { - debug o => _1; // in scope 0 at $DIR/simplify-arm.rs:+0:7: +0:8 - let mut _0: std::option::Option; // return place in scope 0 at $DIR/simplify-arm.rs:+0:25: +0:35 - let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:16 - let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15 - let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:25: +2:26 - scope 1 { - debug v => _3; // in scope 1 at $DIR/simplify-arm.rs:+2:14: +2:15 - } - - bb0: { - _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12 - switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12 - } - - bb1: { - Deinit(_0); // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21 - discriminant(_0) = 0; // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21 - } - - bb2: { - unreachable; // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12 - } - - bb3: { - StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15 - _3 = ((_1 as Some).0: u8); // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15 - StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26 - _4 = _3; // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26 - Deinit(_0); // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27 - ((_0 as Some).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27 - discriminant(_0) = 1; // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27 - StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:+2:26: +2:27 - StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27 - } - - bb4: { - return; // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff deleted file mode 100644 index 7b3a699365773..0000000000000 --- a/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff +++ /dev/null @@ -1,46 +0,0 @@ -- // MIR for `id` before SimplifyBranchSame -+ // MIR for `id` after SimplifyBranchSame - - fn id(_1: Option) -> Option { - debug o => _1; // in scope 0 at $DIR/simplify-arm.rs:+0:7: +0:8 - let mut _0: std::option::Option; // return place in scope 0 at $DIR/simplify-arm.rs:+0:25: +0:35 - let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:16 - let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15 - let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:25: +2:26 - scope 1 { - debug v => _3; // in scope 1 at $DIR/simplify-arm.rs:+2:14: +2:15 - } - - bb0: { - _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12 - switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12 - } - - bb1: { - Deinit(_0); // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21 - discriminant(_0) = 0; // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21 - } - - bb2: { - unreachable; // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12 - } - - bb3: { - StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15 - _3 = ((_1 as Some).0: u8); // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15 - StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26 - _4 = _3; // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26 - Deinit(_0); // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27 - ((_0 as Some).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27 - discriminant(_0) = 1; // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27 - StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:+2:26: +2:27 - StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27 - } - - bb4: { - return; // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff deleted file mode 100644 index 31d8453cec015..0000000000000 --- a/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff +++ /dev/null @@ -1,58 +0,0 @@ -- // MIR for `id_result` before SimplifyArmIdentity -+ // MIR for `id_result` after SimplifyArmIdentity - - fn id_result(_1: Result) -> Result { - debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:+0:14: +0:15 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:+0:37: +0:52 - let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:14 - let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13 - let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:21: +2:22 - let _5: i32; // in scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14 - let mut _6: i32; // in scope 0 at $DIR/simplify-arm.rs:+3:23: +3:24 - scope 1 { - debug x => _3; // in scope 1 at $DIR/simplify-arm.rs:+2:12: +2:13 - } - scope 2 { - debug y => _5; // in scope 2 at $DIR/simplify-arm.rs:+3:13: +3:14 - } - - bb0: { - _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12 - switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12 - } - - bb1: { - StorageLive(_5); // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14 - _5 = ((_1 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14 - StorageLive(_6); // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24 - _6 = _5; // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24 - Deinit(_0); // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25 - ((_0 as Err).0: i32) = move _6; // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25 - discriminant(_0) = 1; // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25 - StorageDead(_6); // scope 2 at $DIR/simplify-arm.rs:+3:24: +3:25 - StorageDead(_5); // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25 - } - - bb2: { - unreachable; // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12 - } - - bb3: { - StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13 - _3 = ((_1 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13 - StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22 - _4 = _3; // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22 - Deinit(_0); // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23 - ((_0 as Ok).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23 - discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23 - StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:+2:22: +2:23 - StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23 - } - - bb4: { - return; // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff deleted file mode 100644 index 3692ebf747bd2..0000000000000 --- a/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff +++ /dev/null @@ -1,58 +0,0 @@ -- // MIR for `id_result` before SimplifyBranchSame -+ // MIR for `id_result` after SimplifyBranchSame - - fn id_result(_1: Result) -> Result { - debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:+0:14: +0:15 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:+0:37: +0:52 - let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:14 - let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13 - let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:21: +2:22 - let _5: i32; // in scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14 - let mut _6: i32; // in scope 0 at $DIR/simplify-arm.rs:+3:23: +3:24 - scope 1 { - debug x => _3; // in scope 1 at $DIR/simplify-arm.rs:+2:12: +2:13 - } - scope 2 { - debug y => _5; // in scope 2 at $DIR/simplify-arm.rs:+3:13: +3:14 - } - - bb0: { - _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12 - switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12 - } - - bb1: { - StorageLive(_5); // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14 - _5 = ((_1 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14 - StorageLive(_6); // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24 - _6 = _5; // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24 - Deinit(_0); // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25 - ((_0 as Err).0: i32) = move _6; // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25 - discriminant(_0) = 1; // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25 - StorageDead(_6); // scope 2 at $DIR/simplify-arm.rs:+3:24: +3:25 - StorageDead(_5); // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25 - } - - bb2: { - unreachable; // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12 - } - - bb3: { - StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13 - _3 = ((_1 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13 - StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22 - _4 = _3; // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22 - Deinit(_0); // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23 - ((_0 as Ok).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23 - discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23 - StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:+2:22: +2:23 - StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23 - } - - bb4: { - return; // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff deleted file mode 100644 index 118f5dd0abb43..0000000000000 --- a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff +++ /dev/null @@ -1,61 +0,0 @@ -- // MIR for `main` before SimplifyArmIdentity -+ // MIR for `main` after SimplifyArmIdentity - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +0:11 - let _1: Src; // in scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10 - let mut _2: Dst; // in scope 0 at $DIR/simplify-arm-identity.rs:+2:18: +5:6 - let mut _3: isize; // in scope 0 at $DIR/simplify-arm-identity.rs:+3:9: +3:20 - let mut _5: u8; // in scope 0 at $DIR/simplify-arm-identity.rs:+3:33: +3:34 - scope 1 { - debug e => _1; // in scope 1 at $DIR/simplify-arm-identity.rs:+1:9: +1:10 - let _4: u8; // in scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19 - scope 2 { - } - scope 3 { - debug x => _4; // in scope 3 at $DIR/simplify-arm-identity.rs:+3:18: +3:19 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10 - Deinit(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29 - ((_1 as Foo).0: u8) = const 0_u8; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29 - discriminant(_1) = 0; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29 - StorageLive(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +5:6 - _3 = const 0_isize; // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25 - goto -> bb3; // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +2:25 - } - - bb1: { - Deinit(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32 - ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32 - discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32 - goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32 - } - - bb2: { - unreachable; // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25 - } - - bb3: { - StorageLive(_4); // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19 - _4 = ((_1 as Foo).0: u8); // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19 - StorageLive(_5); // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34 - _5 = _4; // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34 - Deinit(_2); // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35 - ((_2 as Foo).0: u8) = move _5; // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35 - discriminant(_2) = 0; // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35 - StorageDead(_5); // scope 3 at $DIR/simplify-arm-identity.rs:+3:34: +3:35 - StorageDead(_4); // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35 - goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35 - } - - bb4: { - StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+5:6: +5:7 - nop; // scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +6:2 - StorageDead(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+6:1: +6:2 - return; // scope 0 at $DIR/simplify-arm-identity.rs:+6:2: +6:2 - } - } - diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff deleted file mode 100644 index 118f5dd0abb43..0000000000000 --- a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff +++ /dev/null @@ -1,61 +0,0 @@ -- // MIR for `main` before SimplifyArmIdentity -+ // MIR for `main` after SimplifyArmIdentity - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +0:11 - let _1: Src; // in scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10 - let mut _2: Dst; // in scope 0 at $DIR/simplify-arm-identity.rs:+2:18: +5:6 - let mut _3: isize; // in scope 0 at $DIR/simplify-arm-identity.rs:+3:9: +3:20 - let mut _5: u8; // in scope 0 at $DIR/simplify-arm-identity.rs:+3:33: +3:34 - scope 1 { - debug e => _1; // in scope 1 at $DIR/simplify-arm-identity.rs:+1:9: +1:10 - let _4: u8; // in scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19 - scope 2 { - } - scope 3 { - debug x => _4; // in scope 3 at $DIR/simplify-arm-identity.rs:+3:18: +3:19 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10 - Deinit(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29 - ((_1 as Foo).0: u8) = const 0_u8; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29 - discriminant(_1) = 0; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29 - StorageLive(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +5:6 - _3 = const 0_isize; // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25 - goto -> bb3; // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +2:25 - } - - bb1: { - Deinit(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32 - ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32 - discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32 - goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32 - } - - bb2: { - unreachable; // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25 - } - - bb3: { - StorageLive(_4); // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19 - _4 = ((_1 as Foo).0: u8); // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19 - StorageLive(_5); // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34 - _5 = _4; // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34 - Deinit(_2); // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35 - ((_2 as Foo).0: u8) = move _5; // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35 - discriminant(_2) = 0; // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35 - StorageDead(_5); // scope 3 at $DIR/simplify-arm-identity.rs:+3:34: +3:35 - StorageDead(_4); // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35 - goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35 - } - - bb4: { - StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+5:6: +5:7 - nop; // scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +6:2 - StorageDead(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+6:1: +6:2 - return; // scope 0 at $DIR/simplify-arm-identity.rs:+6:2: +6:2 - } - } - diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff index d8e0657c6ebc6..51d26b08b2a1c 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff @@ -5,24 +5,32 @@ debug x => _1; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:8: +0:9 let mut _0: std::option::Option>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:31: +0:46 let mut _2: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:9: +2:13 -- let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 -- let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 + let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 - let mut _5: bool; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 - let mut _6: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 - let mut _7: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 scope 1 { - debug x => ((_0 as Some).0: std::boxed::Box<()>); // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + debug x => _3; // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 } bb0: { +- _5 = const false; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 +- _5 = const true; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 _2 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12 } bb1: { - ((_0 as Some).0: std::boxed::Box<()>) = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + StorageLive(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 + _4 = move _3; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 Deinit(_0); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 + ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 discriminant(_0) = 1; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 + StorageDead(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 + StorageDead(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 goto -> bb4; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 } @@ -37,6 +45,7 @@ } bb4: { +- _6 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 return; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff index d8e0657c6ebc6..51d26b08b2a1c 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff @@ -5,24 +5,32 @@ debug x => _1; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:8: +0:9 let mut _0: std::option::Option>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:31: +0:46 let mut _2: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:9: +2:13 -- let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 -- let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 + let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 - let mut _5: bool; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 - let mut _6: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 - let mut _7: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 scope 1 { - debug x => ((_0 as Some).0: std::boxed::Box<()>); // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + debug x => _3; // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 } bb0: { +- _5 = const false; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 +- _5 = const true; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 _2 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12 } bb1: { - ((_0 as Some).0: std::boxed::Box<()>) = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 + StorageLive(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 + _4 = move _3; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 Deinit(_0); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 + ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 discriminant(_0) = 1; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 + StorageDead(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 + StorageDead(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 goto -> bb4; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 } @@ -37,6 +45,7 @@ } bb4: { +- _6 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 return; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs deleted file mode 100644 index 15e351e7d5016..0000000000000 --- a/src/test/mir-opt/simplify_try.rs +++ /dev/null @@ -1,30 +0,0 @@ -// compile-flags: -Zunsound-mir-opts -// EMIT_MIR simplify_try.try_identity.SimplifyArmIdentity.diff -// EMIT_MIR simplify_try.try_identity.SimplifyBranchSame.after.mir -// EMIT_MIR simplify_try.try_identity.SimplifyLocals.after.mir -// EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff - - -fn into_result(r: Result) -> Result { - r -} - -fn from_error(e: E) -> Result { - Err(e) -} - -// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, -// so the relevant desugar is copied inline in order to keep the test testing the same thing. -// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR -// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. -fn try_identity(x: Result) -> Result { - let y = match into_result(x) { - Err(e) => return from_error(From::from(e)), - Ok(v) => v, - }; - Ok(y) -} - -fn main() { - let _ = try_identity(Ok(0)); -} diff --git a/src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir b/src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir new file mode 100644 index 0000000000000..330929c58c914 --- /dev/null +++ b/src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir @@ -0,0 +1,96 @@ +// MIR for `new` after PreCodegen + +fn new(_1: Result) -> Result { + debug x => _1; // in scope 0 at $DIR/try_identity_e2e.rs:+0:14: +0:15 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/try_identity_e2e.rs:+0:34: +0:46 + let mut _2: T; // in scope 0 at $DIR/try_identity_e2e.rs:+2:9: +10:10 + let mut _3: std::ops::ControlFlow; // in scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 + let mut _4: isize; // in scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:22 + let _5: T; // in scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21 + let mut _6: T; // in scope 0 at $DIR/try_identity_e2e.rs:+4:48: +4:49 + let _7: E; // in scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22 + let mut _8: E; // in scope 0 at $DIR/try_identity_e2e.rs:+5:46: +5:47 + let mut _9: isize; // in scope 0 at $DIR/try_identity_e2e.rs:+8:13: +8:37 + let _10: T; // in scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36 + let _11: E; // in scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33 + let mut _12: E; // in scope 0 at $DIR/try_identity_e2e.rs:+9:49: +9:50 + scope 1 { + debug v => _5; // in scope 1 at $DIR/try_identity_e2e.rs:+4:20: +4:21 + } + scope 2 { + debug e => _7; // in scope 2 at $DIR/try_identity_e2e.rs:+5:21: +5:22 + } + scope 3 { + debug v => _10; // in scope 3 at $DIR/try_identity_e2e.rs:+8:35: +8:36 + } + scope 4 { + debug e => _11; // in scope 4 at $DIR/try_identity_e2e.rs:+9:32: +9:33 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +10:10 + StorageLive(_3); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 + _4 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20 + switchInt(move _4) -> [0_isize: bb2, 1_isize: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20 + } + + bb1: { + StorageLive(_7); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22 + _7 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22 + StorageLive(_8); // scope 2 at $DIR/try_identity_e2e.rs:+5:46: +5:47 + _8 = move _7; // scope 2 at $DIR/try_identity_e2e.rs:+5:46: +5:47 + Deinit(_3); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48 + ((_3 as Break).0: E) = move _8; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48 + discriminant(_3) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48 + StorageDead(_8); // scope 2 at $DIR/try_identity_e2e.rs:+5:47: +5:48 + StorageDead(_7); // scope 0 at $DIR/try_identity_e2e.rs:+5:47: +5:48 + _9 = discriminant(_3); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 + switchInt(move _9) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10 + } + + bb2: { + StorageLive(_5); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21 + _5 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21 + StorageLive(_6); // scope 1 at $DIR/try_identity_e2e.rs:+4:48: +4:49 + _6 = move _5; // scope 1 at $DIR/try_identity_e2e.rs:+4:48: +4:49 + Deinit(_3); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50 + ((_3 as Continue).0: T) = move _6; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50 + discriminant(_3) = 0; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50 + StorageDead(_6); // scope 1 at $DIR/try_identity_e2e.rs:+4:49: +4:50 + StorageDead(_5); // scope 0 at $DIR/try_identity_e2e.rs:+4:49: +4:50 + _9 = discriminant(_3); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 + switchInt(move _9) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10 + } + + bb3: { + StorageLive(_11); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33 + _11 = move ((_3 as Break).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33 + StorageLive(_12); // scope 4 at $DIR/try_identity_e2e.rs:+9:49: +9:50 + _12 = move _11; // scope 4 at $DIR/try_identity_e2e.rs:+9:49: +9:50 + Deinit(_0); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51 + ((_0 as Err).0: E) = move _12; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51 + discriminant(_0) = 1; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51 + StorageDead(_12); // scope 4 at $DIR/try_identity_e2e.rs:+9:50: +9:51 + StorageDead(_11); // scope 0 at $DIR/try_identity_e2e.rs:+9:50: +9:51 + StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+11:5: +11:6 + StorageDead(_3); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2 + return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2 + } + + bb4: { + unreachable; // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 + } + + bb5: { + StorageLive(_10); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36 + _10 = move ((_3 as Continue).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36 + _2 = move _10; // scope 3 at $DIR/try_identity_e2e.rs:+8:41: +8:42 + StorageDead(_10); // scope 0 at $DIR/try_identity_e2e.rs:+8:41: +8:42 + Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6 + ((_0 as Ok).0: T) = move _2; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6 + discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6 + StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+11:5: +11:6 + StorageDead(_3); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2 + return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2 + } +} diff --git a/src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir b/src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir new file mode 100644 index 0000000000000..18d3e0fb2639d --- /dev/null +++ b/src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir @@ -0,0 +1,53 @@ +// MIR for `old` after PreCodegen + +fn old(_1: Result) -> Result { + debug x => _1; // in scope 0 at $DIR/try_identity_e2e.rs:+0:14: +0:15 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/try_identity_e2e.rs:+0:34: +0:46 + let mut _2: T; // in scope 0 at $DIR/try_identity_e2e.rs:+2:9: +5:10 + let mut _3: isize; // in scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:18 + let _4: T; // in scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17 + let _5: E; // in scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18 + let mut _6: E; // in scope 0 at $DIR/try_identity_e2e.rs:+4:34: +4:35 + scope 1 { + debug v => _4; // in scope 1 at $DIR/try_identity_e2e.rs:+3:16: +3:17 + } + scope 2 { + debug e => _5; // in scope 2 at $DIR/try_identity_e2e.rs:+4:17: +4:18 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +5:10 + _3 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +2:16 + switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +2:16 + } + + bb1: { + StorageLive(_5); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18 + _5 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18 + StorageLive(_6); // scope 2 at $DIR/try_identity_e2e.rs:+4:34: +4:35 + _6 = move _5; // scope 2 at $DIR/try_identity_e2e.rs:+4:34: +4:35 + Deinit(_0); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36 + ((_0 as Err).0: E) = move _6; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36 + discriminant(_0) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36 + StorageDead(_6); // scope 2 at $DIR/try_identity_e2e.rs:+4:35: +4:36 + StorageDead(_5); // scope 0 at $DIR/try_identity_e2e.rs:+4:35: +4:36 + StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+6:5: +6:6 + return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2 + } + + bb2: { + unreachable; // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +2:16 + } + + bb3: { + StorageLive(_4); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17 + _4 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17 + _2 = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+3:22: +3:23 + StorageDead(_4); // scope 0 at $DIR/try_identity_e2e.rs:+3:22: +3:23 + Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6 + ((_0 as Ok).0: T) = move _2; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6 + discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6 + StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+6:5: +6:6 + return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2 + } +} diff --git a/src/test/mir-opt/try_identity_e2e.rs b/src/test/mir-opt/try_identity_e2e.rs new file mode 100644 index 0000000000000..00cb80f5035be --- /dev/null +++ b/src/test/mir-opt/try_identity_e2e.rs @@ -0,0 +1,34 @@ +// Track the status of MIR optimizations simplifying `Ok(res?)` for both the old and new desugarings +// of that syntax. + +use std::ops::ControlFlow; + +// EMIT_MIR try_identity_e2e.new.PreCodegen.after.mir +fn new(x: Result) -> Result { + Ok( + match { + match x { + Ok(v) => ControlFlow::Continue(v), + Err(e) => ControlFlow::Break(e), + } + } { + ControlFlow::Continue(v) => v, + ControlFlow::Break(e) => return Err(e), + } + ) +} + +// EMIT_MIR try_identity_e2e.old.PreCodegen.after.mir +fn old(x: Result) -> Result { + Ok( + match x { + Ok(v) => v, + Err(e) => return Err(e), + } + ) +} + +fn main() { + let _ = new::<(), ()>(Ok(())); + let _ = old::<(), ()>(Ok(())); +}