From 8ddd9662233d468052f5592d048d6939b4ddae55 Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 8 Mar 2024 20:56:09 +0800 Subject: [PATCH 01/51] Rename `UninhabitedEnumBranching` to `UnreachableEnumBranching` --- compiler/rustc_mir_transform/src/lib.rs | 7 ++-- compiler/rustc_mir_transform/src/simplify.rs | 6 +-- ...ching.rs => unreachable_enum_branching.rs} | 12 +++--- ...Cfg-after-unreachable-enum-branching.diff} | 4 +- .../simplify_duplicate_unreachable_blocks.rs | 4 +- ...fallthrough.UnreachableEnumBranching.diff} | 4 +- ...fallthrough.UnreachableEnumBranching.diff} | 4 +- .../uninhabited_fallthrough_elimination.rs | 4 +- ...UnreachableEnumBranching.panic-abort.diff} | 4 +- ...nreachableEnumBranching.panic-unwind.diff} | 4 +- ...UnreachableEnumBranching.panic-abort.diff} | 4 +- ...nreachableEnumBranching.panic-unwind.diff} | 4 +- ...UnreachableEnumBranching.panic-abort.diff} | 4 +- ...nreachableEnumBranching.panic-unwind.diff} | 4 +- ...UnreachableEnumBranching.panic-abort.diff} | 4 +- ...nreachableEnumBranching.panic-unwind.diff} | 4 +- ...UnreachableEnumBranching.panic-abort.diff} | 4 +- ...nreachableEnumBranching.panic-unwind.diff} | 4 +- ...UnreachableEnumBranching.panic-abort.diff} | 4 +- ...nreachableEnumBranching.panic-unwind.diff} | 4 +- ...UnreachableEnumBranching.panic-abort.diff} | 6 +-- ...nreachableEnumBranching.panic-unwind.diff} | 6 +-- ...UnreachableEnumBranching.panic-abort.diff} | 6 +-- ...nreachableEnumBranching.panic-unwind.diff} | 6 +-- ...UnreachableEnumBranching.panic-abort.diff} | 6 +-- ...nreachableEnumBranching.panic-unwind.diff} | 6 +-- ...ching.rs => unreachable_enum_branching.rs} | 40 +++++++++---------- ...UnreachableEnumBranching.panic-abort.diff} | 4 +- ...nreachableEnumBranching.panic-unwind.diff} | 4 +- 29 files changed, 89 insertions(+), 88 deletions(-) rename compiler/rustc_mir_transform/src/{uninhabited_enum_branching.rs => unreachable_enum_branching.rs} (93%) rename tests/mir-opt/{simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff => simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff} (79%) rename tests/mir-opt/{uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff => uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff} (83%) rename tests/mir-opt/{uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff => uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff} (83%) rename tests/mir-opt/{uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff} (95%) rename tests/mir-opt/{uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff} (95%) rename tests/mir-opt/{uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-abort.diff} (85%) rename tests/mir-opt/{uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-unwind.diff} (85%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff} (89%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff} (89%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-abort.diff} (87%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-unwind.diff} (87%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff} (89%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff} (89%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff} (88%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff} (88%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff} (84%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff} (84%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff} (87%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff} (87%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff} (85%) rename tests/mir-opt/{uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff} (86%) rename tests/mir-opt/{uninhabited_enum_branching.rs => unreachable_enum_branching.rs} (80%) rename tests/mir-opt/{uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff => unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff} (90%) rename tests/mir-opt/{uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff => unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff} (90%) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index cd9b98e4f32c..08d4b5fc3954 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -109,7 +109,7 @@ pub mod simplify; mod simplify_branches; mod simplify_comparison_integral; mod sroa; -mod uninhabited_enum_branching; +mod unreachable_enum_branching; mod unreachable_prop; use rustc_const_eval::transform::check_consts::{self, ConstCx}; @@ -579,9 +579,10 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &remove_zsts::RemoveZsts, &remove_unneeded_drops::RemoveUnneededDrops, // Type instantiation may create uninhabited enums. - &uninhabited_enum_branching::UninhabitedEnumBranching, + // Also eliminates some unreachable branches based on variants of enums. + &unreachable_enum_branching::UnreachableEnumBranching, &unreachable_prop::UnreachablePropagation, - &o1(simplify::SimplifyCfg::AfterUninhabitedEnumBranching), + &o1(simplify::SimplifyCfg::AfterUnreachableEnumBranching), // Inlining may have introduced a lot of redundant code and a large move pattern. // Now, we need to shrink the generated MIR. diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 8c8818bd68e6..7c26f8369e46 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -41,7 +41,7 @@ pub enum SimplifyCfg { ElaborateDrops, Final, MakeShim, - AfterUninhabitedEnumBranching, + AfterUnreachableEnumBranching, } impl SimplifyCfg { @@ -54,8 +54,8 @@ impl SimplifyCfg { SimplifyCfg::ElaborateDrops => "SimplifyCfg-elaborate-drops", SimplifyCfg::Final => "SimplifyCfg-final", SimplifyCfg::MakeShim => "SimplifyCfg-make_shim", - SimplifyCfg::AfterUninhabitedEnumBranching => { - "SimplifyCfg-after-uninhabited-enum-branching" + SimplifyCfg::AfterUnreachableEnumBranching => { + "SimplifyCfg-after-unreachable-enum-branching" } } } diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs similarity index 93% rename from compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs rename to compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 57fe46ad75ae..38e72e527e00 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -1,4 +1,4 @@ -//! A pass that eliminates branches on uninhabited enum variants. +//! A pass that eliminates branches on uninhabited or unreachable enum variants. use crate::MirPass; use rustc_data_structures::fx::FxHashSet; @@ -11,7 +11,7 @@ use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_target::abi::{Abi, Variants}; -pub struct UninhabitedEnumBranching; +pub struct UnreachableEnumBranching; fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option { if let TerminatorKind::SwitchInt { discr: Operand::Move(p), .. } = terminator { @@ -71,13 +71,13 @@ fn variant_discriminants<'tcx>( } } -impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { +impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - trace!("UninhabitedEnumBranching starting for {:?}", body.source); + trace!("UnreachableEnumBranching starting for {:?}", body.source); let mut unreachable_targets = Vec::new(); let mut patch = MirPatch::new(body); @@ -121,9 +121,9 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { } let otherwise_is_empty_unreachable = body.basic_blocks[targets.otherwise()].is_empty_unreachable(); - // After resolving https://github.com/llvm/llvm-project/issues/78578, - // we can remove the limit on the number of successors. fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool { + // After resolving https://github.com/llvm/llvm-project/issues/78578, + // We can remove this check. let mut successors = basic_blocks[bb].terminator().successors(); let Some(first_successor) = successors.next() else { return true }; if successors.next().is_some() { diff --git a/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff b/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff similarity index 79% rename from tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff rename to tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff index 35c0a4d45dfb..c94a8267e7b3 100644 --- a/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff +++ b/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff @@ -1,5 +1,5 @@ -- // MIR for `assert_nonzero_nonmax` before SimplifyCfg-after-uninhabited-enum-branching -+ // MIR for `assert_nonzero_nonmax` after SimplifyCfg-after-uninhabited-enum-branching +- // MIR for `assert_nonzero_nonmax` before SimplifyCfg-after-unreachable-enum-branching ++ // MIR for `assert_nonzero_nonmax` after SimplifyCfg-after-unreachable-enum-branching fn assert_nonzero_nonmax(_1: u8) -> u8 { let mut _0: u8; diff --git a/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs b/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs index d94e61118556..6300dafb8e20 100644 --- a/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs +++ b/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs @@ -4,9 +4,9 @@ use std::intrinsics::mir::*; -//@ unit-test: SimplifyCfg-after-uninhabited-enum-branching +//@ unit-test: SimplifyCfg-after-unreachable-enum-branching -// EMIT_MIR simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff +// EMIT_MIR simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff #[custom_mir(dialect = "runtime", phase = "post-cleanup")] pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { mir!( diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff similarity index 83% rename from tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff rename to tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff index daff4f9c85b0..098b620dfaab 100644 --- a/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff @@ -1,5 +1,5 @@ -- // MIR for `eliminate_fallthrough` before UninhabitedEnumBranching -+ // MIR for `eliminate_fallthrough` after UninhabitedEnumBranching +- // MIR for `eliminate_fallthrough` before UnreachableEnumBranching ++ // MIR for `eliminate_fallthrough` after UnreachableEnumBranching fn eliminate_fallthrough(_1: S) -> u32 { debug s => _1; diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff similarity index 83% rename from tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff rename to tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff index 28a8c251d956..995e32b033f2 100644 --- a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff @@ -1,5 +1,5 @@ -- // MIR for `keep_fallthrough` before UninhabitedEnumBranching -+ // MIR for `keep_fallthrough` after UninhabitedEnumBranching +- // MIR for `keep_fallthrough` before UnreachableEnumBranching ++ // MIR for `keep_fallthrough` after UnreachableEnumBranching fn keep_fallthrough(_1: S) -> u32 { debug s => _1; diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.rs b/tests/mir-opt/uninhabited_fallthrough_elimination.rs index 7dd41aea5ed1..537935d8ae43 100644 --- a/tests/mir-opt/uninhabited_fallthrough_elimination.rs +++ b/tests/mir-opt/uninhabited_fallthrough_elimination.rs @@ -9,7 +9,7 @@ enum S { use S::*; -// EMIT_MIR uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff +// EMIT_MIR uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff fn keep_fallthrough(s: S) -> u32 { match s { A(_) => 1, @@ -18,7 +18,7 @@ fn keep_fallthrough(s: S) -> u32 { } } -// EMIT_MIR uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff +// EMIT_MIR uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff fn eliminate_fallthrough(s: S) -> u32 { match s { C => 1, diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff similarity index 95% rename from tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff index 1b7517c8d010..e5dab5d52a6b 100644 --- a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `byref` before UninhabitedEnumBranching -+ // MIR for `byref` after UninhabitedEnumBranching +- // MIR for `byref` before UnreachableEnumBranching ++ // MIR for `byref` after UnreachableEnumBranching fn byref() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff similarity index 95% rename from tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff index 1b7517c8d010..e5dab5d52a6b 100644 --- a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `byref` before UninhabitedEnumBranching -+ // MIR for `byref` after UninhabitedEnumBranching +- // MIR for `byref` before UnreachableEnumBranching ++ // MIR for `byref` after UnreachableEnumBranching fn byref() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-abort.diff similarity index 85% rename from tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-abort.diff index f9a43480917e..ea6cdbfbe661 100644 --- a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `custom_discriminant` before UninhabitedEnumBranching -+ // MIR for `custom_discriminant` after UninhabitedEnumBranching +- // MIR for `custom_discriminant` before UnreachableEnumBranching ++ // MIR for `custom_discriminant` after UnreachableEnumBranching fn custom_discriminant() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-unwind.diff similarity index 85% rename from tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-unwind.diff index f9a43480917e..ea6cdbfbe661 100644 --- a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `custom_discriminant` before UninhabitedEnumBranching -+ // MIR for `custom_discriminant` after UninhabitedEnumBranching +- // MIR for `custom_discriminant` before UnreachableEnumBranching ++ // MIR for `custom_discriminant` after UnreachableEnumBranching fn custom_discriminant() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff similarity index 89% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff index 383fde4d787b..02b9f02f4c0e 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `otherwise_t1` before UninhabitedEnumBranching -+ // MIR for `otherwise_t1` after UninhabitedEnumBranching +- // MIR for `otherwise_t1` before UnreachableEnumBranching ++ // MIR for `otherwise_t1` after UnreachableEnumBranching fn otherwise_t1() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff similarity index 89% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff index 383fde4d787b..02b9f02f4c0e 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `otherwise_t1` before UninhabitedEnumBranching -+ // MIR for `otherwise_t1` after UninhabitedEnumBranching +- // MIR for `otherwise_t1` before UnreachableEnumBranching ++ // MIR for `otherwise_t1` after UnreachableEnumBranching fn otherwise_t1() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-abort.diff similarity index 87% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-abort.diff index 3a2dc19db71c..a6d6e0861b1b 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `otherwise_t2` before UninhabitedEnumBranching -+ // MIR for `otherwise_t2` after UninhabitedEnumBranching +- // MIR for `otherwise_t2` before UnreachableEnumBranching ++ // MIR for `otherwise_t2` after UnreachableEnumBranching fn otherwise_t2() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-unwind.diff similarity index 87% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-unwind.diff index 3a2dc19db71c..a6d6e0861b1b 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `otherwise_t2` before UninhabitedEnumBranching -+ // MIR for `otherwise_t2` after UninhabitedEnumBranching +- // MIR for `otherwise_t2` before UnreachableEnumBranching ++ // MIR for `otherwise_t2` after UnreachableEnumBranching fn otherwise_t2() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff similarity index 89% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff index 5dc1e2b73f6a..d3376442376d 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `otherwise_t3` before UninhabitedEnumBranching -+ // MIR for `otherwise_t3` after UninhabitedEnumBranching +- // MIR for `otherwise_t3` before UnreachableEnumBranching ++ // MIR for `otherwise_t3` after UnreachableEnumBranching fn otherwise_t3() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff similarity index 89% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff index 5dc1e2b73f6a..d3376442376d 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `otherwise_t3` before UninhabitedEnumBranching -+ // MIR for `otherwise_t3` after UninhabitedEnumBranching +- // MIR for `otherwise_t3` before UnreachableEnumBranching ++ // MIR for `otherwise_t3` after UnreachableEnumBranching fn otherwise_t3() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff similarity index 88% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff index 1352dda49715..8f0d5b7cd99c 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `otherwise_t4` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4` after UninhabitedEnumBranching +- // MIR for `otherwise_t4` before UnreachableEnumBranching ++ // MIR for `otherwise_t4` after UnreachableEnumBranching fn otherwise_t4() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff similarity index 88% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff index 1352dda49715..8f0d5b7cd99c 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `otherwise_t4` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4` after UninhabitedEnumBranching +- // MIR for `otherwise_t4` before UnreachableEnumBranching ++ // MIR for `otherwise_t4` after UnreachableEnumBranching fn otherwise_t4() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff similarity index 84% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff index 40dd961fbac4..b1ecd0085829 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff @@ -1,7 +1,7 @@ -- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching +- // MIR for `otherwise_t4_unreachable_default` before UnreachableEnumBranching ++ // MIR for `otherwise_t4_unreachable_default` after UnreachableEnumBranching - fn otherwise_t4_uninhabited_default() -> () { + fn otherwise_t4_unreachable_default() -> () { let mut _0: (); let _1: &str; let mut _2: Test4; diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff similarity index 84% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff index 40dd961fbac4..b1ecd0085829 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff @@ -1,7 +1,7 @@ -- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching +- // MIR for `otherwise_t4_unreachable_default` before UnreachableEnumBranching ++ // MIR for `otherwise_t4_unreachable_default` after UnreachableEnumBranching - fn otherwise_t4_uninhabited_default() -> () { + fn otherwise_t4_unreachable_default() -> () { let mut _0: (); let _1: &str; let mut _2: Test4; diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff similarity index 87% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff index ac39f6be6c63..28c6d4fb6759 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff @@ -1,7 +1,7 @@ -- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching +- // MIR for `otherwise_t4_unreachable_default_2` before UnreachableEnumBranching ++ // MIR for `otherwise_t4_unreachable_default_2` after UnreachableEnumBranching - fn otherwise_t4_uninhabited_default_2() -> () { + fn otherwise_t4_unreachable_default_2() -> () { let mut _0: (); let _1: &str; let mut _2: Test4; diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff similarity index 87% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff index ac39f6be6c63..28c6d4fb6759 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff @@ -1,7 +1,7 @@ -- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching +- // MIR for `otherwise_t4_unreachable_default_2` before UnreachableEnumBranching ++ // MIR for `otherwise_t4_unreachable_default_2` after UnreachableEnumBranching - fn otherwise_t4_uninhabited_default_2() -> () { + fn otherwise_t4_unreachable_default_2() -> () { let mut _0: (); let _1: &str; let mut _2: Test4; diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff similarity index 85% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff index 8180428a6f45..f36a7efd80d4 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff @@ -1,7 +1,7 @@ -- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching -+ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching +- // MIR for `otherwise_t5_unreachable_default` before UnreachableEnumBranching ++ // MIR for `otherwise_t5_unreachable_default` after UnreachableEnumBranching - fn otherwise_t5_uninhabited_default() -> () { + fn otherwise_t5_unreachable_default() -> () { let mut _0: (); let _1: &str; let mut _2: Test5; diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff similarity index 86% rename from tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff index b13d5816aed9..20e31c24c84b 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff @@ -1,7 +1,7 @@ -- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching -+ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching +- // MIR for `otherwise_t5_unreachable_default` before UnreachableEnumBranching ++ // MIR for `otherwise_t5_unreachable_default` after UnreachableEnumBranching - fn otherwise_t5_uninhabited_default() -> () { + fn otherwise_t5_unreachable_default() -> () { let mut _0: (); let _1: &str; let mut _2: Test5; diff --git a/tests/mir-opt/uninhabited_enum_branching.rs b/tests/mir-opt/unreachable_enum_branching.rs similarity index 80% rename from tests/mir-opt/uninhabited_enum_branching.rs rename to tests/mir-opt/unreachable_enum_branching.rs index 6de001be9791..156b23657b7a 100644 --- a/tests/mir-opt/uninhabited_enum_branching.rs +++ b/tests/mir-opt/unreachable_enum_branching.rs @@ -1,4 +1,4 @@ -//@ unit-test: UninhabitedEnumBranching +//@ unit-test: UnreachableEnumBranching // EMIT_MIR_FOR_EACH_PANIC_STRATEGY enum Empty {} @@ -45,7 +45,7 @@ struct Plop { test3: Test3, } -// EMIT_MIR uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff +// EMIT_MIR unreachable_enum_branching.simple.UnreachableEnumBranching.diff fn simple() { // CHECK-LABEL: fn simple( // CHECK: [[discr:_.*]] = discriminant( @@ -59,7 +59,7 @@ fn simple() { }; } -// EMIT_MIR uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff +// EMIT_MIR unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.diff fn custom_discriminant() { // CHECK-LABEL: fn custom_discriminant( // CHECK: [[discr:_.*]] = discriminant( @@ -72,7 +72,7 @@ fn custom_discriminant() { }; } -// EMIT_MIR uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.diff +// EMIT_MIR unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.diff fn otherwise_t1() { // CHECK-LABEL: fn otherwise_t1( // CHECK: [[discr:_.*]] = discriminant( @@ -86,7 +86,7 @@ fn otherwise_t1() { }; } -// EMIT_MIR uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.diff +// EMIT_MIR unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.diff fn otherwise_t2() { // CHECK-LABEL: fn otherwise_t2( // CHECK: [[discr:_.*]] = discriminant( @@ -99,7 +99,7 @@ fn otherwise_t2() { }; } -// EMIT_MIR uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.diff +// EMIT_MIR unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.diff fn otherwise_t3() { // CHECK-LABEL: fn otherwise_t3( // CHECK: [[discr:_.*]] = discriminant( @@ -116,9 +116,9 @@ fn otherwise_t3() { }; } -// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.diff -fn otherwise_t4_uninhabited_default() { - // CHECK-LABEL: fn otherwise_t4_uninhabited_default( +// EMIT_MIR unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.diff +fn otherwise_t4_unreachable_default() { + // CHECK-LABEL: fn otherwise_t4_unreachable_default( // CHECK: [[discr:_.*]] = discriminant( // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]]; // CHECK: [[unreachable]]: { @@ -131,9 +131,9 @@ fn otherwise_t4_uninhabited_default() { }; } -// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.diff -fn otherwise_t4_uninhabited_default_2() { - // CHECK-LABEL: fn otherwise_t4_uninhabited_default_2( +// EMIT_MIR unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.diff +fn otherwise_t4_unreachable_default_2() { + // CHECK-LABEL: fn otherwise_t4_unreachable_default_2( // CHECK: [[discr:_.*]] = discriminant( // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: [[unreachable:bb.*]]]; // CHECK: [[unreachable]]: { @@ -147,7 +147,7 @@ fn otherwise_t4_uninhabited_default_2() { }; } -// EMIT_MIR uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.diff +// EMIT_MIR unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.diff fn otherwise_t4() { // CHECK-LABEL: fn otherwise_t4( // CHECK: [[discr:_.*]] = discriminant( @@ -162,9 +162,9 @@ fn otherwise_t4() { }; } -// EMIT_MIR uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.diff -fn otherwise_t5_uninhabited_default() { - // CHECK-LABEL: fn otherwise_t5_uninhabited_default( +// EMIT_MIR unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.diff +fn otherwise_t5_unreachable_default() { + // CHECK-LABEL: fn otherwise_t5_unreachable_default( // CHECK: [[discr:_.*]] = discriminant( // CHECK: switchInt(move [[discr]]) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]]; // CHECK: [[unreachable]]: { @@ -177,7 +177,7 @@ fn otherwise_t5_uninhabited_default() { }; } -// EMIT_MIR uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff +// EMIT_MIR unreachable_enum_branching.byref.UnreachableEnumBranching.diff fn byref() { // CHECK-LABEL: fn byref( let plop = Plop { xx: 51, test3: Test3::C }; @@ -210,9 +210,9 @@ fn main() { otherwise_t1(); otherwise_t2(); otherwise_t3(); - otherwise_t4_uninhabited_default(); - otherwise_t4_uninhabited_default_2(); + otherwise_t4_unreachable_default(); + otherwise_t4_unreachable_default_2(); otherwise_t4(); - otherwise_t5_uninhabited_default::(); + otherwise_t5_unreachable_default::(); byref(); } diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff similarity index 90% rename from tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff rename to tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff index 674d3a25504a..a85fc0da9923 100644 --- a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `simple` before UninhabitedEnumBranching -+ // MIR for `simple` after UninhabitedEnumBranching +- // MIR for `simple` before UnreachableEnumBranching ++ // MIR for `simple` after UnreachableEnumBranching fn simple() -> () { let mut _0: (); diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff similarity index 90% rename from tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff rename to tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff index 674d3a25504a..a85fc0da9923 100644 --- a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `simple` before UninhabitedEnumBranching -+ // MIR for `simple` after UninhabitedEnumBranching +- // MIR for `simple` before UnreachableEnumBranching ++ // MIR for `simple` after UnreachableEnumBranching fn simple() -> () { let mut _0: (); From df33e02f4096d6d919b95754595295ceed3a40ae Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 8 Mar 2024 22:01:36 +0800 Subject: [PATCH 02/51] Add comments for `UnreachableEnumBranching` --- .../src/unreachable_enum_branching.rs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 38e72e527e00..f32a1db7e395 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -96,8 +96,10 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { ); let mut allowed_variants = if let Ok(layout) = layout { + // Find allowed variants based on uninhabited. variant_discriminants(&layout, discriminant_ty, tcx) } else if let Some(variant_range) = discriminant_ty.variant_range(tcx) { + // If there are some generics, we can still get the allowed variants. variant_range .map(|variant| { discriminant_ty.discriminant_for_variant(tcx, variant).unwrap().val @@ -124,6 +126,23 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool { // After resolving https://github.com/llvm/llvm-project/issues/78578, // We can remove this check. + // The main issue here is that `early-tailduplication` causes compile time overhead + // and potential performance problems. + // Simply put, when encounter a switch (indirect branch) statement, + // `early-tailduplication` tries to duplicate the switch branch statement with BB + // into (each) predecessors. This makes CFG very complex. + // We can understand it as it transforms the following code + // ```rust + // match a { ... many cases }; + // match b { ... many cases }; + // ``` + // into + // ```rust + // match a { ... many match b { goto BB cases } } + // ... BB cases + // ``` + // Abandon this transformation when it is possible (the best effort) + // to encounter the problem. let mut successors = basic_blocks[bb].terminator().successors(); let Some(first_successor) = successors.next() else { return true }; if successors.next().is_some() { @@ -136,6 +155,24 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { }; true } + // If and only if there is a variant that does not have a branch set, + // change the current of otherwise as the variant branch and set otherwise to unreachable. + // It transforms following code + // ```rust + // match c { + // Ordering::Less => 1, + // Ordering::Equal => 2, + // _ => 3, + // } + // ``` + // to + // ```rust + // match c { + // Ordering::Less => 1, + // Ordering::Equal => 2, + // Ordering::Greater => 3, + // } + // ``` let otherwise_is_last_variant = !otherwise_is_empty_unreachable && allowed_variants.len() == 1 && check_successors(&body.basic_blocks, targets.otherwise()); @@ -150,6 +187,7 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { let mut targets = targets.clone(); if replace_otherwise_to_unreachable { if otherwise_is_last_variant { + // We have checked that `allowed_variants` has only one element. #[allow(rustc::potential_query_instability)] let last_variant = *allowed_variants.iter().next().unwrap(); targets.add_target(last_variant, targets.otherwise()); From a10d157f981bcb617e586d7b72d3342fe0acc57e Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 8 Mar 2024 21:55:22 +0800 Subject: [PATCH 03/51] Addition of parentheses to clarify precedence --- compiler/rustc_mir_transform/src/unreachable_enum_branching.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index f32a1db7e395..52bd0bea37d2 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -177,7 +177,7 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { && allowed_variants.len() == 1 && check_successors(&body.basic_blocks, targets.otherwise()); let replace_otherwise_to_unreachable = otherwise_is_last_variant - || !otherwise_is_empty_unreachable && allowed_variants.is_empty(); + || (!otherwise_is_empty_unreachable && allowed_variants.is_empty()); if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable { continue; From f8656ef6e9f4d5f2a05c1a76af21bd201eebd123 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 9 Mar 2024 11:45:29 +0800 Subject: [PATCH 04/51] Update `unreachable_enum_default_branch.rs` --- .../enum/uninhabited_enum_default_branch.rs | 24 ----------- .../enum/unreachable_enum_default_branch.rs | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 24 deletions(-) delete mode 100644 tests/codegen/enum/uninhabited_enum_default_branch.rs create mode 100644 tests/codegen/enum/unreachable_enum_default_branch.rs diff --git a/tests/codegen/enum/uninhabited_enum_default_branch.rs b/tests/codegen/enum/uninhabited_enum_default_branch.rs deleted file mode 100644 index 5f318f18dec6..000000000000 --- a/tests/codegen/enum/uninhabited_enum_default_branch.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ compile-flags: -O - -#![crate_type = "lib"] - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct Int(u32); - -const A: Int = Int(201); -const B: Int = Int(270); -const C: Int = Int(153); - -// CHECK-LABEL: @foo( -// CHECK-SAME: [[TMP0:%.*]]) -// CHECK-NEXT: start: -// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -201 -// CHECK-NEXT: icmp ult i32 [[TMP1]], 70 -// CHECK-NEXT: icmp eq i32 [[TMP0]], 153 -// CHECK-NEXT: [[SPEC_SELECT:%.*]] = or i1 -// CHECK-NEXT: ret i1 [[SPEC_SELECT]] -#[no_mangle] -pub fn foo(x: Int) -> bool { - (x >= A && x <= B) - || x == C -} diff --git a/tests/codegen/enum/unreachable_enum_default_branch.rs b/tests/codegen/enum/unreachable_enum_default_branch.rs new file mode 100644 index 000000000000..dae01cfb055e --- /dev/null +++ b/tests/codegen/enum/unreachable_enum_default_branch.rs @@ -0,0 +1,43 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Int(u32); + +const A: Int = Int(201); +const B: Int = Int(270); +const C: Int = Int(153); + +// The code is from https://github.com/rust-lang/rust/issues/119520. +// This code will basically turn into `matches!(x.partial_cmp(&A), Some(Greater | Equal))`. +// The otherwise branch must be `Less`. +// CHECK-LABEL: @implicit_match( +// CHECK-SAME: [[TMP0:%.*]]) +// CHECK-NEXT: start: +// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -201 +// CHECK-NEXT: icmp ult i32 [[TMP1]], 70 +// CHECK-NEXT: icmp eq i32 [[TMP0]], 153 +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = or i1 +// CHECK-NEXT: ret i1 [[SPEC_SELECT]] +#[no_mangle] +pub fn implicit_match(x: Int) -> bool { + (x >= A && x <= B) + || x == C +} + +// The code is from https://github.com/rust-lang/rust/issues/110097. +// We expect it to generate the same optimized code as a full match. +// CHECK-LABEL: @if_let( +// CHECK-NEXT: start: +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret +#[no_mangle] +pub fn if_let(val: Result) -> Result { + if let Ok(x) = val { + Ok(x) + } else { + Err(()) + } +} From 102bda49b1889cf7c42d9338b797d301f54256a5 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 9 Mar 2024 11:58:36 +0800 Subject: [PATCH 05/51] Remove restrictions on small enum statements such as `Order`, `Option` or `Result` `early-tailduplication` is only a problem when there are a significant number of branches. --- .../rustc_mir_transform/src/unreachable_enum_branching.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 52bd0bea37d2..66b6235eb938 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -175,7 +175,10 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { // ``` let otherwise_is_last_variant = !otherwise_is_empty_unreachable && allowed_variants.len() == 1 - && check_successors(&body.basic_blocks, targets.otherwise()); + // Despite the LLVM issue, we hope that small enum can still be transformed. + // This is valuable for both `a <= b` and `if let Some/Ok(v)`. + && (targets.all_targets().len() <= 3 + || check_successors(&body.basic_blocks, targets.otherwise())); let replace_otherwise_to_unreachable = otherwise_is_last_variant || (!otherwise_is_empty_unreachable && allowed_variants.is_empty()); From ec313d1edb83c7b020e590bcbafa8cd19c94e0e9 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 9 Mar 2024 14:43:38 +0800 Subject: [PATCH 06/51] Update the test case for `SimplifyCfg-after-unreachable-enum-branching` --- ...Cfg-after-unreachable-enum-branching.diff} | 22 +++++--- tests/mir-opt/simplify_dead_blocks.rs | 52 +++++++++++++++++++ .../simplify_duplicate_unreachable_blocks.rs | 31 ----------- 3 files changed, 67 insertions(+), 38 deletions(-) rename tests/mir-opt/{simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff => simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff} (57%) create mode 100644 tests/mir-opt/simplify_dead_blocks.rs delete mode 100644 tests/mir-opt/simplify_duplicate_unreachable_blocks.rs diff --git a/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff b/tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff similarity index 57% rename from tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff rename to tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff index c94a8267e7b3..4400cfaef810 100644 --- a/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff +++ b/tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff @@ -5,19 +5,27 @@ let mut _0: u8; bb0: { -- switchInt(_1) -> [0: bb1, 255: bb2, otherwise: bb3]; -+ switchInt(_1) -> [0: bb1, 255: bb1, otherwise: bb2]; +- switchInt(_1) -> [0: bb3, 1: bb2, 255: bb3, otherwise: bb4]; ++ switchInt(_1) -> [0: bb2, 1: bb1, 255: bb2, otherwise: bb3]; } bb1: { +- _0 = const 1_u8; +- return; +- } +- +- bb2: { + _0 = const 2_u8; + return; + } + +- bb3: { ++ bb2: { unreachable; } - bb2: { -- unreachable; -- } -- -- bb3: { +- bb4: { ++ bb3: { _0 = _1; return; } diff --git a/tests/mir-opt/simplify_dead_blocks.rs b/tests/mir-opt/simplify_dead_blocks.rs new file mode 100644 index 000000000000..d4de85622d41 --- /dev/null +++ b/tests/mir-opt/simplify_dead_blocks.rs @@ -0,0 +1,52 @@ +//@ unit-test: SimplifyCfg-after-unreachable-enum-branching +#![feature(custom_mir, core_intrinsics)] +#![crate_type = "lib"] + +use std::intrinsics::mir::*; + +// Check that we correctly cleaned up the dead BB. +// EMIT_MIR simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { + // CHECK-LABEL: fn assert_nonzero_nonmax( + // CHECK: bb0: { + // CHECK-NEXT: switchInt({{.*}}) -> [0: [[unreachable:bb.*]], 1: [[retblock2:bb.*]], 255: [[unreachable:bb.*]], otherwise: [[retblock:bb.*]]]; + // CHECK-NEXT: } + // CHECK-NOT: _0 = const 1_u8; + // CHECK: [[retblock2]]: { + // CHECK-NEXT: _0 = const 2_u8; + // CHECK-NEXT: return; + // CHECK-NEXT: } + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + // CHECK-NEXT: } + // CHECK: [[retblock]]: { + // CHECK-NEXT: _0 = _1; + // CHECK-NEXT: return; + // CHECK-NEXT: } + mir!( + { + match x { + 0 => unreachable, + 1 => retblock2, + u8::MAX => unreachable, + _ => retblock, + } + } + deadRetblock1 = { + RET = 1; + Return() + } + retblock2 = { + RET = 2; + Return() + } + unreachable = { + Unreachable() + } + retblock = { + RET = x; + Return() + } + ) +} diff --git a/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs b/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs deleted file mode 100644 index 6300dafb8e20..000000000000 --- a/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs +++ /dev/null @@ -1,31 +0,0 @@ -// skip-filecheck -#![feature(custom_mir, core_intrinsics)] -#![crate_type = "lib"] - -use std::intrinsics::mir::*; - -//@ unit-test: SimplifyCfg-after-unreachable-enum-branching - -// EMIT_MIR simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff -#[custom_mir(dialect = "runtime", phase = "post-cleanup")] -pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { - mir!( - { - match x { - 0 => unreachable1, - u8::MAX => unreachable2, - _ => retblock, - } - } - unreachable1 = { - Unreachable() - } - unreachable2 = { - Unreachable() - } - retblock = { - RET = x; - Return() - } - ) -} From 3311283f90dd62dcd322d6730f0dd09b3ee6d7fd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 12 Mar 2024 15:10:01 -0700 Subject: [PATCH 07/51] Get wasm32-wasip2 compiling with its custom pal implementation The ordering of targets in `pal/mod.rs` did not end up using the wasip2 implementation, so after reordering that I've edited the implementation to compile correctly. --- library/std/src/sys/pal/mod.rs | 6 +++--- library/std/src/sys/pal/wasip2/mod.rs | 6 ------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs index 7c87deed3715..8c75ac652998 100644 --- a/library/std/src/sys/pal/mod.rs +++ b/library/std/src/sys/pal/mod.rs @@ -37,12 +37,12 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "hermit")] { mod hermit; pub use self::hermit::*; - } else if #[cfg(target_os = "wasi")] { - mod wasi; - pub use self::wasi::*; } else if #[cfg(all(target_os = "wasi", target_env = "p2"))] { mod wasip2; pub use self::wasip2::*; + } else if #[cfg(target_os = "wasi")] { + mod wasi; + pub use self::wasi::*; } else if #[cfg(target_family = "wasm")] { mod wasm; pub use self::wasm::*; diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index d1d444d7b798..4f164a3ec183 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -10,8 +10,6 @@ pub mod alloc; #[path = "../wasi/args.rs"] pub mod args; -#[path = "../unix/cmath.rs"] -pub mod cmath; #[path = "../wasi/env.rs"] pub mod env; #[path = "../wasi/fd.rs"] @@ -28,10 +26,6 @@ pub mod io; pub mod net; #[path = "../wasi/os.rs"] pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; -#[path = "../unix/path.rs"] -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] From 5af8187325210e3006874b1457fa6ec69293f0e9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 12 Mar 2024 15:10:40 -0700 Subject: [PATCH 08/51] Provide `cabi_realloc` on `wasm32-wasip2` by default This commit provides a component model intrinsic in the standard library by default on the `wasm32-wasip2` target. This intrinsic is not required by the component model itself but is quite common to use, for example it's needed if a wasm module receives a string or a list. The intention of this commit is to provide an overridable definition in the standard library through a weak definition of this function. That means that downstream crates can provide their own customized and more specific versions if they'd like, but the standard library's version should suffice for general-purpose use. --- .../std/src/sys/pal/wasip2/cabi_realloc.rs | 65 +++++++++++++++++++ library/std/src/sys/pal/wasip2/mod.rs | 2 + 2 files changed, 67 insertions(+) create mode 100644 library/std/src/sys/pal/wasip2/cabi_realloc.rs diff --git a/library/std/src/sys/pal/wasip2/cabi_realloc.rs b/library/std/src/sys/pal/wasip2/cabi_realloc.rs new file mode 100644 index 000000000000..820063173d65 --- /dev/null +++ b/library/std/src/sys/pal/wasip2/cabi_realloc.rs @@ -0,0 +1,65 @@ +//! This module contains a canonical definition of the `cabi_realloc` function +//! for the component model. +//! +//! The component model's canonical ABI for representing datatypes in memory +//! makes use of this function when transferring lists and strings, for example. +//! This function behaves like C's `realloc` but also takes alignment into +//! account. +//! +//! Components are notably not required to export this function, but nearly +//! all components end up doing so currently. This definition in the standard +//! library removes the need for all compilations to define this themselves. +//! +//! More information about the canonical ABI can be found at +//! +//! +//! Note that the name of this function is not standardized in the canonical ABI +//! at this time. Instead it's a convention of the "componentization process" +//! where a core wasm module is converted to a component to use this name. +//! Additionally this is not the only possible definition of this function, so +//! this is defined as a "weak" symbol. This means that other definitions are +//! allowed to overwrite it if they are present in a compilation. + +use crate::alloc::{self, Layout}; +use crate::ptr; + +#[used] +static FORCE_CODEGEN_OF_CABI_REALLOC: unsafe extern "C" fn( + *mut u8, + usize, + usize, + usize, +) -> *mut u8 = cabi_realloc; + +#[linkage = "weak"] +#[no_mangle] +pub unsafe extern "C" fn cabi_realloc( + old_ptr: *mut u8, + old_len: usize, + align: usize, + new_len: usize, +) -> *mut u8 { + let layout; + let ptr = if old_len == 0 { + if new_len == 0 { + return ptr::without_provenance_mut(align); + } + layout = Layout::from_size_align_unchecked(new_len, align); + alloc::alloc(layout) + } else { + debug_assert_ne!(new_len, 0, "non-zero old_len requires non-zero new_len!"); + layout = Layout::from_size_align_unchecked(old_len, align); + alloc::realloc(old_ptr, layout, new_len) + }; + if ptr.is_null() { + // Print a nice message in debug mode, but in release mode don't + // pull in so many dependencies related to printing so just emit an + // `unreachable` instruction. + if cfg!(debug_assertions) { + alloc::handle_alloc_error(layout); + } else { + super::abort_internal(); + } + } + return ptr; +} diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index 4f164a3ec183..94aa458d2f90 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -66,3 +66,5 @@ pub use helpers::decode_error_kind; use helpers::err2io; pub use helpers::hashmap_random_keys; pub use helpers::is_interrupted; + +mod cabi_realloc; From df933640571861bcc2854431823cd9d4803b9f88 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Sun, 25 Feb 2024 16:36:26 +0000 Subject: [PATCH 09/51] Added ability to report on generic argument mismatch better Needs some checking over and some tests have altered that need sanity checking, but overall this is starting to get somewhere now. --- compiler/rustc_errors/src/lib.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 388 +++++++++++++++++- compiler/rustc_lint_defs/src/lib.rs | 33 ++ .../extra_arguments.stderr | 14 +- .../invalid_arguments.stderr | 20 +- tests/ui/argument-suggestions/too-long.stderr | 24 +- tests/ui/async-await/coroutine-desc.stderr | 31 +- .../coerce-reborrow-multi-arg-fail.stderr | 11 +- tests/ui/coercion/coerce-to-bang.stderr | 10 +- tests/ui/fn/fn-item-type.stderr | 55 ++- ...generic-mismatch-reporting-issue-116615.rs | 12 + ...ric-mismatch-reporting-issue-116615.stderr | 75 ++++ tests/ui/never_type/issue-96335.stderr | 1 + tests/ui/parser/issues/issue-93282.stderr | 2 +- tests/ui/span/issue-34264.stderr | 2 +- .../tuple/add-tuple-within-arguments.stderr | 4 +- ...call-return-type-due-to-generic-arg.stderr | 2 +- 17 files changed, 611 insertions(+), 75 deletions(-) create mode 100644 tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.rs create mode 100644 tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.stderr diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 723f13dbe8d3..b88b5bcd7ea5 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -50,7 +50,7 @@ pub use rustc_error_messages::{ fallback_fluent_bundle, fluent_bundle, DelayDm, DiagMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage, }; -pub use rustc_lint_defs::{pluralize, Applicability}; +pub use rustc_lint_defs::{a_or_an, display_list_with_comma_and, pluralize, Applicability}; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; pub use rustc_span::ErrorGuaranteed; pub use snippet::Style; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 1fa1da93018a..b65ac134fbc1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -17,7 +17,8 @@ use itertools::Itertools; use rustc_ast as ast; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ - codes::*, pluralize, Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, + a_or_an, codes::*, display_list_with_comma_and, pluralize, Applicability, Diag, + DiagnosticBuilder, ErrorGuaranteed, MultiSpan, StashKey, }; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; @@ -423,11 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "expected formal_input_tys to be the same size as expected_input_tys" ); let formal_and_expected_inputs = IndexVec::from_iter( - formal_input_tys - .iter() - .copied() - .zip_eq(expected_input_tys.iter().copied()) - .map(|vars| self.resolve_vars_if_possible(vars)), + formal_input_tys.iter().copied().zip_eq(expected_input_tys.iter().copied()), ); self.set_tainted_by_errors(self.report_arg_errors( @@ -642,6 +639,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx]; + let formal_input_ty = self.resolve_vars_if_possible(formal_input_ty); + let expected_input_ty = self.resolve_vars_if_possible(expected_input_ty); // If either is an error type, we defy the usual convention and consider them to *not* be // coercible. This prevents our error message heuristic from trying to pass errors into // every argument. @@ -714,7 +713,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Do we have as many extra provided arguments as the tuple's length? // If so, we might have just forgotten to wrap some args in a tuple. if let Some(ty::Tuple(tys)) = - formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind()) + formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| self.resolve_vars_if_possible(tys.1).kind()) // If the tuple is unit, we're not actually wrapping any arguments. && !tys.is_empty() && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len() @@ -733,7 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()), ), ) { - if !self.can_coerce(provided_ty, *expected_ty) { + if !self.can_coerce(provided_ty, self.resolve_vars_if_possible(*expected_ty)) { satisfied = false; break; } @@ -752,10 +751,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if tys.len() == 1 { // A tuple wrap suggestion actually occurs within, // so don't do anything special here. + let (formal_ty, expected_ty) = + formal_and_expected_inputs[mismatch_idx.into()]; + let formal_ty = self.resolve_vars_if_possible(formal_ty); + let expected_ty = self.resolve_vars_if_possible(expected_ty); err = self.err_ctxt().report_and_explain_type_error( mk_trace( *lo, - formal_and_expected_inputs[mismatch_idx.into()], + (formal_ty, expected_ty), provided_arg_tys[mismatch_idx.into()].0, ), terr, @@ -795,6 +798,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr, None, Some(mismatch_idx), + &matched_inputs, + &formal_and_expected_inputs, is_method, ); suggest_confusable(&mut err); @@ -837,8 +842,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; }; let (provided_ty, provided_span) = provided_arg_tys[*provided_idx]; - let trace = - mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty); + let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx]; + let formal_ty = self.resolve_vars_if_possible(formal_ty); + let expected_ty = self.resolve_vars_if_possible(expected_ty); + let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty); if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) { let mut err = self.err_ctxt().report_and_explain_type_error(trace, *e); suggest_confusable(&mut err); @@ -866,6 +873,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ] = &errors[..] { let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx]; + let formal_ty = self.resolve_vars_if_possible(formal_ty); + let expected_ty = self.resolve_vars_if_possible(expected_ty); let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx]; let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty); let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err); @@ -881,6 +890,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(full_call_span, format!("arguments to this {call_name} are incorrect")); + self.label_generic_mismatches( + &mut err, + fn_def_id, + &matched_inputs, + &provided_arg_tys, + &formal_and_expected_inputs, + ); + if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind && provided_idx.as_usize() == expected_idx.as_usize() { @@ -909,6 +926,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr, Some(expected_ty), Some(expected_idx.as_usize()), + &matched_inputs, + &formal_and_expected_inputs, is_method, ); suggest_confusable(&mut err); @@ -984,6 +1003,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match error { Error::Invalid(provided_idx, expected_idx, compatibility) => { let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx]; + let formal_ty = self.resolve_vars_if_possible(formal_ty); + let expected_ty = self.resolve_vars_if_possible(expected_ty); let (provided_ty, provided_span) = provided_arg_tys[provided_idx]; if let Compatibility::Incompatible(error) = compatibility { let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty); @@ -1088,6 +1109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &missing_idxs[..] { &[expected_idx] => { let (_, input_ty) = formal_and_expected_inputs[expected_idx]; + let input_ty = self.resolve_vars_if_possible(input_ty); let span = if let Some((_, arg_span)) = provided_arg_tys.get(expected_idx.to_provided_idx()) { @@ -1110,6 +1132,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &[first_idx, second_idx] => { let (_, first_expected_ty) = formal_and_expected_inputs[first_idx]; let (_, second_expected_ty) = formal_and_expected_inputs[second_idx]; + let first_expected_ty = + self.resolve_vars_if_possible(first_expected_ty); + let second_expected_ty = + self.resolve_vars_if_possible(second_expected_ty); let span = if let (Some((_, first_span)), Some((_, second_span))) = ( provided_arg_tys.get(first_idx.to_provided_idx()), provided_arg_tys.get(second_idx.to_provided_idx()), @@ -1136,8 +1162,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } &[first_idx, second_idx, third_idx] => { let (_, first_expected_ty) = formal_and_expected_inputs[first_idx]; + let first_expected_ty = + self.resolve_vars_if_possible(first_expected_ty); let (_, second_expected_ty) = formal_and_expected_inputs[second_idx]; + let second_expected_ty = + self.resolve_vars_if_possible(second_expected_ty); let (_, third_expected_ty) = formal_and_expected_inputs[third_idx]; + let third_expected_ty = + self.resolve_vars_if_possible(third_expected_ty); let span = if let (Some((_, first_span)), Some((_, third_span))) = ( provided_arg_tys.get(first_idx.to_provided_idx()), provided_arg_tys.get(third_idx.to_provided_idx()), @@ -1197,6 +1229,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) => { let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx]; let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx]; + let first_expected_ty = self.resolve_vars_if_possible(first_expected_ty); let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) { format!(", found `{first_provided_ty}`") } else { @@ -1209,6 +1242,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx]; let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx]; + let second_provided_ty = self.resolve_vars_if_possible(second_provided_ty); let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) { format!(", found `{second_provided_ty}`") } else { @@ -1227,6 +1261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Error::Permutation(args) => { for (dst_arg, dest_input) in args { let (_, expected_ty) = formal_and_expected_inputs[dst_arg]; + let expected_ty = self.resolve_vars_if_possible(expected_ty); let (provided_ty, provided_span) = provided_arg_tys[dest_input]; let provided_ty_name = if !has_error_or_infer([provided_ty]) { format!(", found `{provided_ty}`") @@ -1247,6 +1282,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + self.label_generic_mismatches( + &mut err, + fn_def_id, + &matched_inputs, + &provided_arg_tys, + &formal_and_expected_inputs, + ); + // Incorporate the argument changes in the removal suggestion. // When a type is *missing*, and the rest are additional, we want to suggest these with a // multipart suggestion, but in order to do so we need to figure out *where* the arg that @@ -1282,6 +1325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // To suggest a multipart suggestion when encountering `foo(1, "")` where the def // was `fn foo(())`. let (_, expected_ty) = formal_and_expected_inputs[expected_idx]; + let expected_ty = self.resolve_vars_if_possible(expected_ty); suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx))); } } @@ -1294,7 +1338,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Call out where the function is defined - self.label_fn_like(&mut err, fn_def_id, callee_ty, call_expr, None, None, is_method); + self.label_fn_like( + &mut err, + fn_def_id, + callee_ty, + call_expr, + None, + None, + &matched_inputs, + &formal_and_expected_inputs, + is_method, + ); // And add a suggestion block for all of the parameters let suggestion_text = match suggestion_text { @@ -1348,6 +1402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { // Propose a placeholder of the correct type let (_, expected_ty) = formal_and_expected_inputs[expected_idx]; + let expected_ty = self.resolve_vars_if_possible(expected_ty); ty_to_snippet(expected_ty, expected_idx) }; suggestion += &suggestion_text; @@ -2054,6 +2109,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Option>, // A specific argument should be labeled, instead of all of them expected_idx: Option, + matched_inputs: &IndexVec>, + formal_and_expected_inputs: &IndexVec, Ty<'tcx>)>, is_method: bool, ) { let Some(mut def_id) = callable_def_id else { @@ -2145,21 +2202,200 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let mut spans: MultiSpan = def_span.into(); - let params = self + let param_generics: Vec>> = self + .tcx + .hir() + .get_if_local(def_id) + .and_then(|node| node.fn_decl()) + .into_iter() + .flat_map(|decl| decl.inputs) + .skip(if is_method { 1 } else { 0 }) + .map(|param| { + if let hir::TyKind::Path(QPath::Resolved( + _, + hir::Path { res: Res::Def(_, res_def_id), .. }, + )) = param.kind + { + self.tcx + .hir() + .get_if_local(def_id) + .and_then(|node| node.generics()) + .into_iter() + .flat_map(|generics| generics.params) + .find(|gen| &gen.def_id.to_def_id() == res_def_id) + } else { + None + } + }) + .collect(); + + let params: Vec<&hir::Param<'_>> = self .tcx .hir() .get_if_local(def_id) .and_then(|node| node.body_id()) .into_iter() .flat_map(|id| self.tcx.hir().body(id).params) - .skip(if is_method { 1 } else { 0 }); + .skip(if is_method { 1 } else { 0 }) + .collect(); - for (_, param) in params - .into_iter() - .enumerate() - .filter(|(idx, _)| expected_idx.map_or(true, |expected_idx| expected_idx == *idx)) - { - spans.push_span_label(param.span, ""); + if params.len() == param_generics.len() { + let mut generics_map: Vec<(usize, &hir::GenericParam<'_>)> = Vec::new(); + // This is a map from the index of the generic to the index of the parameter and the + // parameter + let mut matched_params_map: Vec<(usize, usize, &hir::Param<'_>)> = Vec::new(); + let mut unmatched_params_map: Vec<(usize, &hir::Param<'_>)> = Vec::new(); + + for (idx, (param, generic)) in + params.iter().zip_eq(param_generics.iter()).enumerate() + { + if matched_inputs[idx.into()].is_none() { + spans.push_span_label(param.span, ""); + continue; + } + + let Some(generic) = generic else { + spans.push_span_label(param.span, ""); + continue; + }; + + let mut found_unmatched_generic_params = vec![]; + + for unmatching_idx in idx + 1..params.len() { + if matched_inputs[unmatching_idx.into()].is_none() + && let Some(unmatched_idx_param_generic) = + param_generics[unmatching_idx] + && unmatched_idx_param_generic.name.ident() == generic.name.ident() + { + found_unmatched_generic_params.push(params[unmatching_idx]); + } + } + + if found_unmatched_generic_params.is_empty() { + continue; + } + + let generics_idx = generics_map + .iter() + .filter(|x| x.1.name.ident() == generic.name.ident()) + .next() + .map(|x| x.0); + + let generics_idx = generics_idx.unwrap_or_else(|| { + let generics_map_len = generics_map.len(); + generics_map.push((generics_map_len, generic)); + generics_map_len + }); + matched_params_map.push((generics_idx, idx, param)); + if unmatched_params_map.iter().filter(|x| x.0 == generics_idx).count() > 0 { + // Already processed the unmatched params + continue; + } + for unmatched_param in &found_unmatched_generic_params { + unmatched_params_map.push((generics_idx, unmatched_param)); + } + } + + for (generic_idx, generic) in &generics_map { + let matched_params: Vec<(usize, &hir::Param<'_>)> = matched_params_map + .iter() + .filter(|x| x.0 == *generic_idx) + .map(|x| (x.1, x.2)) + .collect(); + let unmatched_params: Vec<&hir::Param<'_>> = unmatched_params_map + .iter() + .filter(|x| x.0 == *generic_idx) + .map(|x| x.1) + .collect(); + + let all_param_idents: Vec = matched_params + .iter() + .map(|x| &x.1) + .chain(unmatched_params.iter()) + .map(|x| { + if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind { + format!("`{ident}`") + } else { + "{unknown}".to_string() + } + }) + .collect(); + + spans.push_span_label( + generic.span, + format!( + "{} all reference this parameter {}", + display_list_with_comma_and(&all_param_idents), + generic.name.ident().name, + ), + ); + + for unmatched_param in &unmatched_params { + let idents: Vec = matched_params + .iter() + .map(|x| { + if let hir::PatKind::Binding(_, _, ident, _) = x.1.pat.kind { + format!("`{ident}`") + } else { + "{unknown}".to_string() + } + }) + .collect(); + + let matched_ty = matched_params + .iter() + .next() + .map(|x| formal_and_expected_inputs[x.0.into()]); + + if let Some(matched_ty) = matched_ty { + let matched_ty = + self.resolve_vars_if_possible(matched_ty.0).sort_string(self.tcx); + spans.push_span_label( + unmatched_param.span, + format!( + "this parameter needs to match the {} type of {}", + matched_ty, + display_list_with_comma_and(&idents) + ), + ); + } else { + spans.push_span_label( + unmatched_param.span, + format!( + "this parameter needs to match the type of {}", + display_list_with_comma_and(&idents) + ), + ); + } + } + + for matched_param in &matched_params { + let idents: Vec = unmatched_params + .iter() + .map(|x| { + if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind { + format!("`{ident}`") + } else { + "{unknown}".to_string() + } + }) + .collect(); + + spans.push_span_label( + matched_param.1.span, + format!( + "{} needs to match the type of this parameter", + display_list_with_comma_and(&idents) + ), + ); + } + } + } else { + for (_, param) in params.iter().enumerate().filter(|(idx, _)| { + expected_idx.map_or(true, |expected_idx| expected_idx == *idx) + }) { + spans.push_span_label(param.span, ""); + } } err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id))); @@ -2225,6 +2461,118 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } + + fn label_generic_mismatches( + &self, + err: &mut DiagnosticBuilder<'_>, + callable_def_id: Option, + matched_inputs: &IndexVec>, + provided_arg_tys: &IndexVec, Span)>, + formal_and_expected_inputs: &IndexVec, Ty<'tcx>)>, + ) { + let Some(def_id) = callable_def_id else { + return; + }; + + for (matched_idx, matched_arg) in matched_inputs.iter_enumerated() { + let Some(matched_input) = matched_arg else { + continue; + }; + + let (_, matched_arg_span) = provided_arg_tys[*matched_input]; + let (matched_formal_ty, _) = formal_and_expected_inputs[matched_idx]; + let ty::Infer(ty::TyVar(a)) = matched_formal_ty.kind() else { + continue; + }; + + let mut formal_ty_idxs_matched: Vec = vec![]; + let mut expected_ty_matched = None; + for (input_idx, (formal_ty, expected_ty)) in formal_and_expected_inputs + .iter_enumerated() + // Only care about args after the matched one we're checking. + // + // NB: Incompatible should always come after their matching generics. + // e.g. if we have a function fn f(a: T, b: T, c: T) and we call it with + // f(1, 2, 3.0) then the first will force T to be an integer, the second + // then matches and the third is the incompatible argument. + .filter(|(idx, _)| *idx > matched_idx) + { + if let ty::Infer(ty::TyVar(b)) = formal_ty.kind() { + if self.root_var(*a) == self.root_var(*b) { + formal_ty_idxs_matched.push(input_idx.into()); + if expected_ty_matched.is_none() { + expected_ty_matched = Some(expected_ty); + } + } + } + } + + let Some(expected_ty) = expected_ty_matched else { + continue; + }; + + let params = self + .tcx + .hir() + .get_if_local(def_id) + .and_then(|node| node.body_id()) + .into_iter() + .flat_map(|id| self.tcx.hir().body(id).params); + + let mut all_pats_matched: Vec = vec![]; + let mut incompatible_pats_matched: Vec = vec![]; + for (idx, param) in params + .into_iter() + .enumerate() + .filter(|(idx, _)| formal_ty_idxs_matched.contains(idx)) + { + let ident = if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind { + format!("`{ident}`") + } else { + format!("`idx:{idx}`") + }; + if matched_inputs[idx.into()].is_none() { + incompatible_pats_matched.push(ident.clone()); + } + all_pats_matched.push(ident); + } + + let expected_display_type = + self.resolve_vars_if_possible(*expected_ty).sort_string(self.tcx); + let label = if all_pats_matched.len() == 0 { + format!( + "expected all arguments to be {} because they need to match the type of this parameter", + expected_display_type + ) + } else if all_pats_matched.len() == incompatible_pats_matched.len() { + format!( + "expected {} {} to be {} {} because {} to match the type of this parameter", + format!("argument{}", pluralize!(incompatible_pats_matched.len())), + display_list_with_comma_and(&incompatible_pats_matched), + a_or_an(&expected_display_type), + expected_display_type, + if all_pats_matched.len() == 1 { + "that argument needs" + } else { + "those arguments need" + } + ) + } else { + format!( + "expected {} {} to be {} {} because the {} {} {} to match the type of this parameter", + format!("argument{}", pluralize!(incompatible_pats_matched.len())), + display_list_with_comma_and(&incompatible_pats_matched), + a_or_an(&expected_display_type), + expected_display_type, + format!("argument{}", pluralize!(all_pats_matched.len())), + display_list_with_comma_and(&all_pats_matched), + format!("need{}", pluralize!(if all_pats_matched.len() == 1 { 0 } else { 1 })), + ) + }; + + err.span_label(matched_arg_span, label); + } + } } struct FindClosureArg<'tcx> { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7f200a7b623d..6279c402fc80 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -39,6 +39,39 @@ macro_rules! pluralize { }; } +/// Grammatical tool for displaying messages to end users in a nice form. +/// +/// Returns "an" if the given string starts with a vowel, and "a" otherwise. +pub fn a_or_an(s: &str) -> &'static str { + let mut chars = s.chars(); + let Some(mut first_alpha_char) = chars.next() else { + return "a"; + }; + if first_alpha_char == '`' { + let Some(next) = chars.next() else { + return "a"; + }; + first_alpha_char = next; + } + if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) { + "an" + } else { + "a" + } +} + +/// Grammatical tool for displaying messages to end users in a nice form. +/// +/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c" +pub fn display_list_with_comma_and(v: &[T]) -> String { + match v.len() { + 0 => "".to_string(), + 1 => v[0].to_string(), + 2 => format!("{} and {}", v[0], v[1]), + _ => format!("{}, {}", v[0], display_list_with_comma_and(&v[1..])), + } +} + /// Indicates the confidence in the correctness of a suggestion. /// /// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr index 5ad8e35920a1..4cbe9124deec 100644 --- a/tests/ui/argument-suggestions/extra_arguments.stderr +++ b/tests/ui/argument-suggestions/extra_arguments.stderr @@ -45,7 +45,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ ----- + | ^^^^^^^ error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:23:3 @@ -60,7 +60,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ ----- + | ^^^^^^^ error[E0061]: this function takes 1 argument but 3 arguments were supplied --> $DIR/extra_arguments.rs:24:3 @@ -74,7 +74,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ ----- + | ^^^^^^^ help: remove the extra arguments | LL - one_arg(1, "", 1.0); @@ -319,7 +319,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ ----- + | ^^^^^^^ error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:54:3 @@ -334,7 +334,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ ----- + | ^^^^^^^ error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:55:3 @@ -349,7 +349,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ ----- + | ^^^^^^^ error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:60:3 @@ -364,7 +364,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ ----- + | ^^^^^^^ error: aborting due to 22 previous errors diff --git a/tests/ui/argument-suggestions/invalid_arguments.stderr b/tests/ui/argument-suggestions/invalid_arguments.stderr index d26f33d098be..61a46b067f5b 100644 --- a/tests/ui/argument-suggestions/invalid_arguments.stderr +++ b/tests/ui/argument-suggestions/invalid_arguments.stderr @@ -24,7 +24,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:6:4 | LL | fn two_arg_same(_a: i32, _b: i32) {} - | ^^^^^^^^^^^^ ------- + | ^^^^^^^^^^^^ ------- ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:17:16 @@ -38,7 +38,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:6:4 | LL | fn two_arg_same(_a: i32, _b: i32) {} - | ^^^^^^^^^^^^ ------- + | ^^^^^^^^^^^^ ------- ------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:18:3 @@ -66,7 +66,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:7:4 | LL | fn two_arg_diff(_a: i32, _b: f32) {} - | ^^^^^^^^^^^^ ------- + | ^^^^^^^^^^^^ ------- ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:20:16 @@ -80,7 +80,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:7:4 | LL | fn two_arg_diff(_a: i32, _b: f32) {} - | ^^^^^^^^^^^^ ------- + | ^^^^^^^^^^^^ ------- ------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:21:3 @@ -108,7 +108,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:8:4 | LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} - | ^^^^^^^^^^^^^^ ------- + | ^^^^^^^^^^^^^^ ------- ------- -------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:25:21 @@ -122,7 +122,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:8:4 | LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} - | ^^^^^^^^^^^^^^ ------- + | ^^^^^^^^^^^^^^ ------- ------- -------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:26:26 @@ -136,7 +136,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:8:4 | LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} - | ^^^^^^^^^^^^^^ -------- + | ^^^^^^^^^^^^^^ ------- ------- -------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:28:3 @@ -207,7 +207,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:9:4 | LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} - | ^^^^^^^^^^^^^^^^ ------- + | ^^^^^^^^^^^^^^^^ ------- ------- -------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:35:23 @@ -221,7 +221,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:9:4 | LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} - | ^^^^^^^^^^^^^^^^ ------- + | ^^^^^^^^^^^^^^^^ ------- ------- -------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:36:26 @@ -235,7 +235,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:9:4 | LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} - | ^^^^^^^^^^^^^^^^ -------- + | ^^^^^^^^^^^^^^^^ ------- ------- -------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:38:3 diff --git a/tests/ui/argument-suggestions/too-long.stderr b/tests/ui/argument-suggestions/too-long.stderr index 04ee9275cb36..9400f2a02a82 100644 --- a/tests/ui/argument-suggestions/too-long.stderr +++ b/tests/ui/argument-suggestions/too-long.stderr @@ -11,9 +11,31 @@ note: method defined here | LL | fn foo( | ^^^ -... +LL | &self, +LL | a: i32, + | ------ +LL | b: i32, + | ------ +LL | c: i32, + | ------ +LL | d: i32, + | ------ +LL | e: i32, + | ------ LL | f: i32, | ------ +LL | g: i32, + | ------ +LL | h: i32, + | ------ +LL | i: i32, + | ------ +LL | j: i32, + | ------ +LL | k: i32, + | ------ +LL | l: i32, + | ------ help: consider dereferencing the borrow | LL | qux.foo(a, b, c, d, e, *f, g, h, i, j, k, l); diff --git a/tests/ui/async-await/coroutine-desc.stderr b/tests/ui/async-await/coroutine-desc.stderr index e4cb0915a109..5ad54bc5b8e3 100644 --- a/tests/ui/async-await/coroutine-desc.stderr +++ b/tests/ui/async-await/coroutine-desc.stderr @@ -5,6 +5,7 @@ LL | fun(async {}, async {}); | --- -------- ^^^^^^^^ expected `async` block, found a different `async` block | | | | | the expected `async` block + | | expected argument `f2` to be an `async` block because that argument needs to match the type of this parameter | arguments to this function are incorrect | = note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:17}` @@ -13,14 +14,19 @@ note: function defined here --> $DIR/coroutine-desc.rs:8:4 | LL | fn fun>(f1: F, f2: F) {} - | ^^^ ----- + | ^^^ - ----- ----- + | | | | + | | | this parameter needs to match the `async` block type of `f1` + | | `f2` needs to match the type of this parameter + | `f1` and `f2` all reference this parameter F error[E0308]: mismatched types --> $DIR/coroutine-desc.rs:12:16 | LL | fun(one(), two()); - | --- ^^^^^ expected future, found a different future - | | + | --- ----- ^^^^^ expected future, found a different future + | | | + | | expected argument `f2` to be a future because that argument needs to match the type of this parameter | arguments to this function are incorrect | = help: consider `await`ing on both `Future`s @@ -29,15 +35,20 @@ note: function defined here --> $DIR/coroutine-desc.rs:8:4 | LL | fn fun>(f1: F, f2: F) {} - | ^^^ ----- + | ^^^ - ----- ----- + | | | | + | | | this parameter needs to match the future type of `f1` + | | `f2` needs to match the type of this parameter + | `f1` and `f2` all reference this parameter F error[E0308]: mismatched types --> $DIR/coroutine-desc.rs:14:26 | LL | fun((async || {})(), (async || {})()); - | --- -- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body - | | | - | | the expected `async` closure body + | --- --------------- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body + | | | | + | | | the expected `async` closure body + | | expected argument `f2` to be an `async` closure body because that argument needs to match the type of this parameter | arguments to this function are incorrect | = note: expected `async` closure body `{async closure body@$DIR/coroutine-desc.rs:14:19: 14:21}` @@ -46,7 +57,11 @@ note: function defined here --> $DIR/coroutine-desc.rs:8:4 | LL | fn fun>(f1: F, f2: F) {} - | ^^^ ----- + | ^^^ - ----- ----- + | | | | + | | | this parameter needs to match the `async` closure body type of `f1` + | | `f2` needs to match the type of this parameter + | `f1` and `f2` all reference this parameter F error: aborting due to 3 previous errors diff --git a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr index 498ef33d52ec..b67f91ff8e28 100644 --- a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr +++ b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr @@ -2,8 +2,9 @@ error[E0308]: mismatched types --> $DIR/coerce-reborrow-multi-arg-fail.rs:4:18 | LL | test(&mut 7, &7); - | ---- ^^ types differ in mutability - | | + | ---- ------ ^^ types differ in mutability + | | | + | | expected argument `_b` to be an `&mut {integer}` because that argument needs to match the type of this parameter | arguments to this function are incorrect | = note: expected mutable reference `&mut {integer}` @@ -12,7 +13,11 @@ note: function defined here --> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4 | LL | fn test(_a: T, _b: T) {} - | ^^^^ ----- + | ^^^^ - ----- ----- + | | | | + | | | this parameter needs to match the `&mut {integer}` type of `_a` + | | `_b` needs to match the type of this parameter + | `_a` and `_b` all reference this parameter T error: aborting due to 1 previous error diff --git a/tests/ui/coercion/coerce-to-bang.stderr b/tests/ui/coercion/coerce-to-bang.stderr index 3c737358adc7..4c21eef5c291 100644 --- a/tests/ui/coercion/coerce-to-bang.stderr +++ b/tests/ui/coercion/coerce-to-bang.stderr @@ -12,7 +12,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ ---- + | ^^^ -------- ---- -------- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:18:13 @@ -28,7 +28,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ ---- + | ^^^ -------- ---- -------- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:26:12 @@ -44,7 +44,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ ---- + | ^^^ -------- ---- -------- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:36:12 @@ -60,7 +60,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ ---- + | ^^^ -------- ---- -------- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:45:12 @@ -76,7 +76,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ ---- + | ^^^ -------- ---- -------- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:50:21 diff --git a/tests/ui/fn/fn-item-type.stderr b/tests/ui/fn/fn-item-type.stderr index da90b8b81c85..24c7a3cb4828 100644 --- a/tests/ui/fn/fn-item-type.stderr +++ b/tests/ui/fn/fn-item-type.stderr @@ -2,8 +2,9 @@ error[E0308]: mismatched types --> $DIR/fn-item-type.rs:22:19 | LL | eq(foo::, bar::); - | -- ^^^^^^^^^ expected fn item, found a different fn item - | | + | -- --------- ^^^^^^^^^ expected fn item, found a different fn item + | | | + | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn(_) -> _ {foo::}` @@ -13,15 +14,20 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ ---- + | ^^ - ---- ---- + | | | | + | | | this parameter needs to match the fn item type of `x` + | | `y` needs to match the type of this parameter + | `x` and `y` all reference this parameter T = help: consider casting both fn items to fn pointers using `as fn(isize) -> isize` error[E0308]: mismatched types --> $DIR/fn-item-type.rs:29:19 | LL | eq(foo::, foo::); - | -- ^^^^^^^^^ expected `u8`, found `i8` - | | + | -- --------- ^^^^^^^^^ expected `u8`, found `i8` + | | | + | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn(_) -> _ {foo::}` @@ -31,15 +37,20 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ ---- + | ^^ - ---- ---- + | | | | + | | | this parameter needs to match the fn item type of `x` + | | `y` needs to match the type of this parameter + | `x` and `y` all reference this parameter T = help: consider casting both fn items to fn pointers using `as fn(isize) -> isize` error[E0308]: mismatched types --> $DIR/fn-item-type.rs:34:23 | LL | eq(bar::, bar::>); - | -- ^^^^^^^^^^^^^^ expected `String`, found `Vec` - | | + | -- ------------- ^^^^^^^^^^^^^^ expected `String`, found `Vec` + | | | + | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn(_) -> _ {bar::}` @@ -49,15 +60,20 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ ---- + | ^^ - ---- ---- + | | | | + | | | this parameter needs to match the fn item type of `x` + | | `y` needs to match the type of this parameter + | `x` and `y` all reference this parameter T = help: consider casting both fn items to fn pointers using `as fn(isize) -> isize` error[E0308]: mismatched types --> $DIR/fn-item-type.rs:40:26 | LL | eq(::foo, ::foo); - | -- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16` - | | + | -- ---------------- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16` + | | | + | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn() {::foo}` @@ -67,15 +83,20 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ ---- + | ^^ - ---- ---- + | | | | + | | | this parameter needs to match the fn item type of `x` + | | `y` needs to match the type of this parameter + | `x` and `y` all reference this parameter T = help: consider casting both fn items to fn pointers using `as fn()` error[E0308]: mismatched types --> $DIR/fn-item-type.rs:45:19 | LL | eq(foo::, bar:: as fn(isize) -> isize); - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer - | | + | -- --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer + | | | + | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn(_) -> _ {foo::}` @@ -85,7 +106,11 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ ---- + | ^^ - ---- ---- + | | | | + | | | this parameter needs to match the fn item type of `x` + | | `y` needs to match the type of this parameter + | `x` and `y` all reference this parameter T error: aborting due to 5 previous errors diff --git a/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.rs b/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.rs new file mode 100644 index 000000000000..9a38b948e8ea --- /dev/null +++ b/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.rs @@ -0,0 +1,12 @@ +fn foo(a: T, b: T) {} +fn foo_multi_same(a: T, b: T, c: T, d: T, e: T, f: i32) {} +fn foo_multi_generics(a: T, b: T, c: T, d: T, e: T, f: S, g: S) {} + +fn main() { + foo(1, 2.); + //~^ ERROR mismatched types + foo_multi_same("a", "b", false, true, (), 32); + //~^ ERROR arguments to this function are incorrect + foo_multi_generics("a", "b", "c", true, false, 32, 2.); + //~^ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.stderr b/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.stderr new file mode 100644 index 000000000000..a4f55ce06ac7 --- /dev/null +++ b/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.stderr @@ -0,0 +1,75 @@ +error[E0308]: mismatched types + --> $DIR/generic-mismatch-reporting-issue-116615.rs:6:12 + | +LL | foo(1, 2.); + | --- - ^^ expected integer, found floating-point number + | | | + | | expected argument `b` to be an integer because that argument needs to match the type of this parameter + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/generic-mismatch-reporting-issue-116615.rs:1:4 + | +LL | fn foo(a: T, b: T) {} + | ^^^ - ---- ---- + | | | | + | | | this parameter needs to match the integer type of `a` + | | `b` needs to match the type of this parameter + | `a` and `b` all reference this parameter T + +error[E0308]: arguments to this function are incorrect + --> $DIR/generic-mismatch-reporting-issue-116615.rs:8:5 + | +LL | foo_multi_same("a", "b", false, true, (), 32); + | ^^^^^^^^^^^^^^ --- --- ----- ---- -- expected `&str`, found `()` + | | | | | + | | | | expected `&str`, found `bool` + | | | expected `&str`, found `bool` + | | expected arguments `c`, `d` and `e` to be an `&str` because those arguments need to match the type of this parameter + | expected arguments `c`, `d` and `e` to be an `&str` because the arguments `b`, `c`, `d` and `e` need to match the type of this parameter + | +note: function defined here + --> $DIR/generic-mismatch-reporting-issue-116615.rs:2:4 + | +LL | fn foo_multi_same(a: T, b: T, c: T, d: T, e: T, f: i32) {} + | ^^^^^^^^^^^^^^ - ---- ---- ---- ---- ---- ------ + | | | | | | | + | | | | | | this parameter needs to match the `&str` type of `a` and `b` + | | | | | this parameter needs to match the `&str` type of `a` and `b` + | | | | this parameter needs to match the `&str` type of `a` and `b` + | | | `c`, `d` and `e` needs to match the type of this parameter + | | `c`, `d` and `e` needs to match the type of this parameter + | `a`, `b`, `c`, `d` and `e` all reference this parameter T + +error[E0308]: arguments to this function are incorrect + --> $DIR/generic-mismatch-reporting-issue-116615.rs:10:5 + | +LL | foo_multi_generics("a", "b", "c", true, false, 32, 2.); + | ^^^^^^^^^^^^^^^^^^ --- --- --- ---- ----- -- -- expected integer, found floating-point number + | | | | | | | + | | | | | | expected argument `g` to be an integer because that argument needs to match the type of this parameter + | | | | | expected `&str`, found `bool` + | | | | expected `&str`, found `bool` + | | | expected arguments `d` and `e` to be an `&str` because those arguments need to match the type of this parameter + | | expected arguments `d` and `e` to be an `&str` because the arguments `c`, `d` and `e` need to match the type of this parameter + | expected arguments `d` and `e` to be an `&str` because the arguments `b`, `c`, `d` and `e` need to match the type of this parameter + | +note: function defined here + --> $DIR/generic-mismatch-reporting-issue-116615.rs:3:4 + | +LL | fn foo_multi_generics(a: T, b: T, c: T, d: T, e: T, f: S, g: S) {} + | ^^^^^^^^^^^^^^^^^^ - - ---- ---- ---- ---- ---- ---- ---- + | | | | | | | | | | + | | | | | | | | | this parameter needs to match the integer type of `f` + | | | | | | | | `g` needs to match the type of this parameter + | | | | | | | this parameter needs to match the `&str` type of `a`, `b` and `c` + | | | | | | this parameter needs to match the `&str` type of `a`, `b` and `c` + | | | | | `d` and `e` needs to match the type of this parameter + | | | | `d` and `e` needs to match the type of this parameter + | | | `d` and `e` needs to match the type of this parameter + | | `a`, `b`, `c`, `d` and `e` all reference this parameter T + | `f` and `g` all reference this parameter S + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/issue-96335.stderr b/tests/ui/never_type/issue-96335.stderr index c3d80a425e05..13cdbe842c9d 100644 --- a/tests/ui/never_type/issue-96335.stderr +++ b/tests/ui/never_type/issue-96335.stderr @@ -21,6 +21,7 @@ LL | 0.....{loop{}1}; | | | | | expected integer, found `RangeTo<{integer}>` | arguments to this function are incorrect + | expected all arguments to be integer because they need to match the type of this parameter | = note: expected type `{integer}` found struct `RangeTo<{integer}>` diff --git a/tests/ui/parser/issues/issue-93282.stderr b/tests/ui/parser/issues/issue-93282.stderr index c6140bb821e4..fc15865e1a72 100644 --- a/tests/ui/parser/issues/issue-93282.stderr +++ b/tests/ui/parser/issues/issue-93282.stderr @@ -43,7 +43,7 @@ note: function defined here --> $DIR/issue-93282.rs:7:4 | LL | fn bar(a: usize, b: usize) -> usize { - | ^^^ -------- + | ^^^ -------- -------- error: aborting due to 4 previous errors diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr index f0dea66f6128..1b9ad3a3f167 100644 --- a/tests/ui/span/issue-34264.stderr +++ b/tests/ui/span/issue-34264.stderr @@ -77,7 +77,7 @@ note: function defined here --> $DIR/issue-34264.rs:3:4 | LL | fn bar(x, y: usize) {} - | ^^^ -------- + | ^^^ - -------- error[E0061]: this function takes 2 arguments but 3 arguments were supplied --> $DIR/issue-34264.rs:10:5 diff --git a/tests/ui/tuple/add-tuple-within-arguments.stderr b/tests/ui/tuple/add-tuple-within-arguments.stderr index 6849128eaddd..8414a51bfd5e 100644 --- a/tests/ui/tuple/add-tuple-within-arguments.stderr +++ b/tests/ui/tuple/add-tuple-within-arguments.stderr @@ -8,7 +8,7 @@ note: function defined here --> $DIR/add-tuple-within-arguments.rs:1:4 | LL | fn foo(s: &str, a: (i32, i32), s2: &str) {} - | ^^^ ------------- + | ^^^ ------- ------------- -------- help: wrap these arguments in parentheses to construct a tuple | LL | foo("hi", (1, 2), "hi"); @@ -28,7 +28,7 @@ note: function defined here --> $DIR/add-tuple-within-arguments.rs:3:4 | LL | fn bar(s: &str, a: (&str,), s2: &str) {} - | ^^^ ---------- + | ^^^ ------- ---------- -------- help: use a trailing comma to create a tuple with one element | LL | bar("hi", ("hi",), "hi"); diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr index fbe6bfeebb14..63a98a55127a 100644 --- a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr +++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr @@ -74,7 +74,7 @@ note: function defined here --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 | LL | fn function(x: T, y: bool) -> T { - | ^^^^^^^^ ---- + | ^^^^^^^^ ---- ------- help: change the type of the numeric literal from `u32` to `u16` | LL | let x: u16 = function(0u16, true); From 8a5245e7dd006e2eb6bf6d3834b05772285efe28 Mon Sep 17 00:00:00 2001 From: Steven Trotter Date: Mon, 26 Feb 2024 21:00:35 +0000 Subject: [PATCH 10/51] Refactored a few bits: - Firstly get all the information about generics matching out of the HIR - Secondly the labelling for the function is more coherent now - Lastly a few error message improvements --- compiler/rustc_errors/src/lib.rs | 35 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 499 ++++++++---------- compiler/rustc_lint_defs/src/lib.rs | 33 -- .../extra_arguments.stderr | 14 +- .../invalid_arguments.stderr | 20 +- tests/ui/argument-suggestions/too-long.stderr | 24 +- tests/ui/async-await/coroutine-desc.stderr | 27 +- .../coerce-reborrow-multi-arg-fail.stderr | 9 +- tests/ui/coercion/coerce-to-bang.stderr | 10 +- tests/ui/fn/fn-item-type.stderr | 45 +- ...generic-mismatch-reporting-issue-116615.rs | 2 + ...ric-mismatch-reporting-issue-116615.stderr | 64 ++- tests/ui/never_type/issue-96335.stderr | 1 - tests/ui/parser/issues/issue-93282.stderr | 2 +- tests/ui/span/issue-34264.stderr | 2 +- .../tuple/add-tuple-within-arguments.stderr | 4 +- ...call-return-type-due-to-generic-arg.stderr | 2 +- 17 files changed, 362 insertions(+), 431 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b88b5bcd7ea5..3098eb20be3a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -50,7 +50,7 @@ pub use rustc_error_messages::{ fallback_fluent_bundle, fluent_bundle, DelayDm, DiagMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage, }; -pub use rustc_lint_defs::{a_or_an, display_list_with_comma_and, pluralize, Applicability}; +pub use rustc_lint_defs::{pluralize, Applicability}; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; pub use rustc_span::ErrorGuaranteed; pub use snippet::Style; @@ -1946,6 +1946,39 @@ pub fn report_ambiguity_error<'a, G: EmissionGuarantee>( } } +/// Grammatical tool for displaying messages to end users in a nice form. +/// +/// Returns "an" if the given string starts with a vowel, and "a" otherwise. +pub fn a_or_an(s: &str) -> &'static str { + let mut chars = s.chars(); + let Some(mut first_alpha_char) = chars.next() else { + return "a"; + }; + if first_alpha_char == '`' { + let Some(next) = chars.next() else { + return "a"; + }; + first_alpha_char = next; + } + if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) { + "an" + } else { + "a" + } +} + +/// Grammatical tool for displaying messages to end users in a nice form. +/// +/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c" +pub fn display_list_with_comma_and(v: &[T]) -> String { + match v.len() { + 0 => "".to_string(), + 1 => v[0].to_string(), + 2 => format!("{} and {}", v[0], v[1]), + _ => format!("{}, {}", v[0], display_list_with_comma_and(&v[1..])), + } +} + #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum TerminalUrl { No, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index b65ac134fbc1..c0d971523548 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -18,7 +18,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ a_or_an, codes::*, display_list_with_comma_and, pluralize, Applicability, Diag, - DiagnosticBuilder, ErrorGuaranteed, MultiSpan, StashKey, + ErrorGuaranteed, MultiSpan, StashKey, }; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; @@ -424,7 +424,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "expected formal_input_tys to be the same size as expected_input_tys" ); let formal_and_expected_inputs = IndexVec::from_iter( - formal_input_tys.iter().copied().zip_eq(expected_input_tys.iter().copied()), + formal_input_tys + .iter() + .copied() + .zip_eq(expected_input_tys.iter().copied()) + .map(|vars| self.resolve_vars_if_possible(vars)), ); self.set_tainted_by_errors(self.report_arg_errors( @@ -639,8 +643,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx]; - let formal_input_ty = self.resolve_vars_if_possible(formal_input_ty); - let expected_input_ty = self.resolve_vars_if_possible(expected_input_ty); // If either is an error type, we defy the usual convention and consider them to *not* be // coercible. This prevents our error message heuristic from trying to pass errors into // every argument. @@ -713,7 +715,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Do we have as many extra provided arguments as the tuple's length? // If so, we might have just forgotten to wrap some args in a tuple. if let Some(ty::Tuple(tys)) = - formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| self.resolve_vars_if_possible(tys.1).kind()) + formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind()) // If the tuple is unit, we're not actually wrapping any arguments. && !tys.is_empty() && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len() @@ -732,7 +734,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()), ), ) { - if !self.can_coerce(provided_ty, self.resolve_vars_if_possible(*expected_ty)) { + if !self.can_coerce(provided_ty, *expected_ty) { satisfied = false; break; } @@ -751,14 +753,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if tys.len() == 1 { // A tuple wrap suggestion actually occurs within, // so don't do anything special here. - let (formal_ty, expected_ty) = - formal_and_expected_inputs[mismatch_idx.into()]; - let formal_ty = self.resolve_vars_if_possible(formal_ty); - let expected_ty = self.resolve_vars_if_possible(expected_ty); err = self.err_ctxt().report_and_explain_type_error( mk_trace( *lo, - (formal_ty, expected_ty), + formal_and_expected_inputs[mismatch_idx.into()], provided_arg_tys[mismatch_idx.into()].0, ), terr, @@ -842,10 +840,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; }; let (provided_ty, provided_span) = provided_arg_tys[*provided_idx]; - let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx]; - let formal_ty = self.resolve_vars_if_possible(formal_ty); - let expected_ty = self.resolve_vars_if_possible(expected_ty); - let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty); + let trace = + mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty); if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) { let mut err = self.err_ctxt().report_and_explain_type_error(trace, *e); suggest_confusable(&mut err); @@ -873,8 +869,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ] = &errors[..] { let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx]; - let formal_ty = self.resolve_vars_if_possible(formal_ty); - let expected_ty = self.resolve_vars_if_possible(expected_ty); let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx]; let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty); let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err); @@ -896,6 +890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &matched_inputs, &provided_arg_tys, &formal_and_expected_inputs, + is_method, ); if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind @@ -1003,8 +998,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match error { Error::Invalid(provided_idx, expected_idx, compatibility) => { let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx]; - let formal_ty = self.resolve_vars_if_possible(formal_ty); - let expected_ty = self.resolve_vars_if_possible(expected_ty); let (provided_ty, provided_span) = provided_arg_tys[provided_idx]; if let Compatibility::Incompatible(error) = compatibility { let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty); @@ -1109,7 +1102,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &missing_idxs[..] { &[expected_idx] => { let (_, input_ty) = formal_and_expected_inputs[expected_idx]; - let input_ty = self.resolve_vars_if_possible(input_ty); let span = if let Some((_, arg_span)) = provided_arg_tys.get(expected_idx.to_provided_idx()) { @@ -1132,10 +1124,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &[first_idx, second_idx] => { let (_, first_expected_ty) = formal_and_expected_inputs[first_idx]; let (_, second_expected_ty) = formal_and_expected_inputs[second_idx]; - let first_expected_ty = - self.resolve_vars_if_possible(first_expected_ty); - let second_expected_ty = - self.resolve_vars_if_possible(second_expected_ty); let span = if let (Some((_, first_span)), Some((_, second_span))) = ( provided_arg_tys.get(first_idx.to_provided_idx()), provided_arg_tys.get(second_idx.to_provided_idx()), @@ -1162,14 +1150,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } &[first_idx, second_idx, third_idx] => { let (_, first_expected_ty) = formal_and_expected_inputs[first_idx]; - let first_expected_ty = - self.resolve_vars_if_possible(first_expected_ty); let (_, second_expected_ty) = formal_and_expected_inputs[second_idx]; - let second_expected_ty = - self.resolve_vars_if_possible(second_expected_ty); let (_, third_expected_ty) = formal_and_expected_inputs[third_idx]; - let third_expected_ty = - self.resolve_vars_if_possible(third_expected_ty); let span = if let (Some((_, first_span)), Some((_, third_span))) = ( provided_arg_tys.get(first_idx.to_provided_idx()), provided_arg_tys.get(third_idx.to_provided_idx()), @@ -1229,7 +1211,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) => { let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx]; let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx]; - let first_expected_ty = self.resolve_vars_if_possible(first_expected_ty); let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) { format!(", found `{first_provided_ty}`") } else { @@ -1242,7 +1223,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx]; let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx]; - let second_provided_ty = self.resolve_vars_if_possible(second_provided_ty); let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) { format!(", found `{second_provided_ty}`") } else { @@ -1261,7 +1241,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Error::Permutation(args) => { for (dst_arg, dest_input) in args { let (_, expected_ty) = formal_and_expected_inputs[dst_arg]; - let expected_ty = self.resolve_vars_if_possible(expected_ty); let (provided_ty, provided_span) = provided_arg_tys[dest_input]; let provided_ty_name = if !has_error_or_infer([provided_ty]) { format!(", found `{provided_ty}`") @@ -1288,6 +1267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &matched_inputs, &provided_arg_tys, &formal_and_expected_inputs, + is_method, ); // Incorporate the argument changes in the removal suggestion. @@ -1325,7 +1305,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // To suggest a multipart suggestion when encountering `foo(1, "")` where the def // was `fn foo(())`. let (_, expected_ty) = formal_and_expected_inputs[expected_idx]; - let expected_ty = self.resolve_vars_if_possible(expected_ty); suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx))); } } @@ -1402,7 +1381,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { // Propose a placeholder of the correct type let (_, expected_ty) = formal_and_expected_inputs[expected_idx]; - let expected_ty = self.resolve_vars_if_possible(expected_ty); ty_to_snippet(expected_ty, expected_idx) }; suggestion += &suggestion_text; @@ -2202,118 +2180,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let mut spans: MultiSpan = def_span.into(); - let param_generics: Vec>> = self - .tcx - .hir() - .get_if_local(def_id) - .and_then(|node| node.fn_decl()) - .into_iter() - .flat_map(|decl| decl.inputs) - .skip(if is_method { 1 } else { 0 }) - .map(|param| { - if let hir::TyKind::Path(QPath::Resolved( - _, - hir::Path { res: Res::Def(_, res_def_id), .. }, - )) = param.kind - { - self.tcx - .hir() - .get_if_local(def_id) - .and_then(|node| node.generics()) - .into_iter() - .flat_map(|generics| generics.params) - .find(|gen| &gen.def_id.to_def_id() == res_def_id) - } else { - None - } - }) - .collect(); + let params_with_generics = self.get_hir_params_with_generics(def_id, is_method); + let mut generics_with_unmatched_params = Vec::new(); - let params: Vec<&hir::Param<'_>> = self - .tcx - .hir() - .get_if_local(def_id) - .and_then(|node| node.body_id()) - .into_iter() - .flat_map(|id| self.tcx.hir().body(id).params) - .skip(if is_method { 1 } else { 0 }) - .collect(); - - if params.len() == param_generics.len() { - let mut generics_map: Vec<(usize, &hir::GenericParam<'_>)> = Vec::new(); - // This is a map from the index of the generic to the index of the parameter and the - // parameter - let mut matched_params_map: Vec<(usize, usize, &hir::Param<'_>)> = Vec::new(); - let mut unmatched_params_map: Vec<(usize, &hir::Param<'_>)> = Vec::new(); - - for (idx, (param, generic)) in - params.iter().zip_eq(param_generics.iter()).enumerate() + let check_for_matched_generics = || { + if matched_inputs.iter().any(|x| x.is_some()) + && params_with_generics.iter().any(|x| x.0.is_some()) { - if matched_inputs[idx.into()].is_none() { - spans.push_span_label(param.span, ""); - continue; - } + for (idx, (generic, _)) in params_with_generics.iter().enumerate() { + // Param has to have a generic and be matched to be relevant + if matched_inputs[idx.into()].is_none() { + continue; + } - let Some(generic) = generic else { - spans.push_span_label(param.span, ""); - continue; - }; + let Some(generic) = generic else { + continue; + }; - let mut found_unmatched_generic_params = vec![]; - - for unmatching_idx in idx + 1..params.len() { - if matched_inputs[unmatching_idx.into()].is_none() - && let Some(unmatched_idx_param_generic) = - param_generics[unmatching_idx] - && unmatched_idx_param_generic.name.ident() == generic.name.ident() - { - found_unmatched_generic_params.push(params[unmatching_idx]); + for unmatching_idx in idx + 1..params_with_generics.len() { + if matched_inputs[unmatching_idx.into()].is_none() + && let Some(unmatched_idx_param_generic) = + params_with_generics[unmatching_idx].0 + && unmatched_idx_param_generic.name.ident() == generic.name.ident() + { + // We found a parameter that didn't match that needed to + return true; + } } } - - if found_unmatched_generic_params.is_empty() { - continue; - } - - let generics_idx = generics_map - .iter() - .filter(|x| x.1.name.ident() == generic.name.ident()) - .next() - .map(|x| x.0); - - let generics_idx = generics_idx.unwrap_or_else(|| { - let generics_map_len = generics_map.len(); - generics_map.push((generics_map_len, generic)); - generics_map_len - }); - matched_params_map.push((generics_idx, idx, param)); - if unmatched_params_map.iter().filter(|x| x.0 == generics_idx).count() > 0 { - // Already processed the unmatched params - continue; - } - for unmatched_param in &found_unmatched_generic_params { - unmatched_params_map.push((generics_idx, unmatched_param)); - } } + false + }; - for (generic_idx, generic) in &generics_map { - let matched_params: Vec<(usize, &hir::Param<'_>)> = matched_params_map - .iter() - .filter(|x| x.0 == *generic_idx) - .map(|x| (x.1, x.2)) - .collect(); - let unmatched_params: Vec<&hir::Param<'_>> = unmatched_params_map - .iter() - .filter(|x| x.0 == *generic_idx) - .map(|x| x.1) - .collect(); + let check_for_matched_generics = check_for_matched_generics(); - let all_param_idents: Vec = matched_params + for (idx, (generic_param, param)) in + params_with_generics.iter().enumerate().filter(|(idx, _)| { + check_for_matched_generics + || expected_idx.map_or(true, |expected_idx| expected_idx == *idx) + }) + { + let Some(generic_param) = generic_param else { + spans.push_span_label(param.span, ""); + continue; + }; + + let other_params_matched: Vec<(usize, &hir::Param<'_>)> = params_with_generics + .iter() + .enumerate() + .filter(|(other_idx, (other_generic_param, _))| { + if *other_idx == idx { + return false; + } + let Some(other_generic_param) = other_generic_param else { + return false; + }; + if matched_inputs[idx.into()].is_none() + && matched_inputs[(*other_idx).into()].is_none() + { + return false; + } + if matched_inputs[idx.into()].is_some() + && matched_inputs[(*other_idx).into()].is_some() + { + return false; + } + other_generic_param.name.ident() == generic_param.name.ident() + }) + .map(|(other_idx, (_, other_param))| (other_idx, *other_param)) + .collect(); + + if !other_params_matched.is_empty() { + let other_param_matched_names: Vec = other_params_matched .iter() - .map(|x| &x.1) - .chain(unmatched_params.iter()) - .map(|x| { - if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind { + .map(|(_, other_param)| { + if let hir::PatKind::Binding(_, _, ident, _) = other_param.pat.kind { format!("`{ident}`") } else { "{unknown}".to_string() @@ -2321,83 +2262,84 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .collect(); - spans.push_span_label( - generic.span, - format!( - "{} all reference this parameter {}", - display_list_with_comma_and(&all_param_idents), - generic.name.ident().name, - ), - ); - - for unmatched_param in &unmatched_params { - let idents: Vec = matched_params - .iter() - .map(|x| { - if let hir::PatKind::Binding(_, _, ident, _) = x.1.pat.kind { - format!("`{ident}`") - } else { - "{unknown}".to_string() - } - }) - .collect(); - - let matched_ty = matched_params - .iter() - .next() - .map(|x| formal_and_expected_inputs[x.0.into()]); - - if let Some(matched_ty) = matched_ty { - let matched_ty = - self.resolve_vars_if_possible(matched_ty.0).sort_string(self.tcx); - spans.push_span_label( - unmatched_param.span, - format!( - "this parameter needs to match the {} type of {}", - matched_ty, - display_list_with_comma_and(&idents) - ), - ); - } else { - spans.push_span_label( - unmatched_param.span, - format!( - "this parameter needs to match the type of {}", - display_list_with_comma_and(&idents) - ), - ); - } - } - - for matched_param in &matched_params { - let idents: Vec = unmatched_params - .iter() - .map(|x| { - if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind { - format!("`{ident}`") - } else { - "{unknown}".to_string() - } - }) - .collect(); + let matched_ty = self + .resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1) + .sort_string(self.tcx); + if matched_inputs[idx.into()].is_some() { spans.push_span_label( - matched_param.1.span, + param.span, format!( - "{} needs to match the type of this parameter", - display_list_with_comma_and(&idents) + "{} {} to match the {} type of this parameter", + display_list_with_comma_and(&other_param_matched_names), + format!( + "need{}", + pluralize!(if other_param_matched_names.len() == 1 { + 0 + } else { + 1 + }) + ), + matched_ty, + ), + ); + } else { + spans.push_span_label( + param.span, + format!( + "this parameter needs to match the {} type of {}", + matched_ty, + display_list_with_comma_and(&other_param_matched_names), ), ); } - } - } else { - for (_, param) in params.iter().enumerate().filter(|(idx, _)| { - expected_idx.map_or(true, |expected_idx| expected_idx == *idx) - }) { + generics_with_unmatched_params.push(generic_param); + } else { spans.push_span_label(param.span, ""); } } + for generic_param in self + .tcx + .hir() + .get_if_local(def_id) + .and_then(|node| node.generics()) + .into_iter() + .flat_map(|x| x.params) + .filter(|x| { + generics_with_unmatched_params.iter().any(|y| x.name.ident() == y.name.ident()) + }) + { + let param_idents_matching: Vec = params_with_generics + .iter() + .filter(|(generic, _)| { + if let Some(generic) = generic { + generic.name.ident() == generic_param.name.ident() + } else { + false + } + }) + .map(|(_, param)| { + if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind { + format!("`{ident}`") + } else { + "{unknown}".to_string() + } + }) + .collect(); + + if !param_idents_matching.is_empty() { + spans.push_span_label( + generic_param.span, + format!( + "{} all reference this parameter {}", + display_list_with_comma_and(¶m_idents_matching), + generic_param.name.ident().name, + ), + ); + } + } + err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id))); } else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id) && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind @@ -2464,115 +2406,112 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn label_generic_mismatches( &self, - err: &mut DiagnosticBuilder<'_>, + err: &mut Diag<'_>, callable_def_id: Option, matched_inputs: &IndexVec>, provided_arg_tys: &IndexVec, Span)>, formal_and_expected_inputs: &IndexVec, Ty<'tcx>)>, + is_method: bool, ) { let Some(def_id) = callable_def_id else { return; }; - for (matched_idx, matched_arg) in matched_inputs.iter_enumerated() { - let Some(matched_input) = matched_arg else { + let params_with_generics = self.get_hir_params_with_generics(def_id, is_method); + + for (idx, (generic_param, _)) in params_with_generics.iter().enumerate() { + if matched_inputs[idx.into()].is_none() { + continue; + } + + let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.into()) else { continue; }; - let (_, matched_arg_span) = provided_arg_tys[*matched_input]; - let (matched_formal_ty, _) = formal_and_expected_inputs[matched_idx]; - let ty::Infer(ty::TyVar(a)) = matched_formal_ty.kind() else { + let Some(generic_param) = generic_param else { continue; }; - let mut formal_ty_idxs_matched: Vec = vec![]; - let mut expected_ty_matched = None; - for (input_idx, (formal_ty, expected_ty)) in formal_and_expected_inputs - .iter_enumerated() - // Only care about args after the matched one we're checking. - // - // NB: Incompatible should always come after their matching generics. - // e.g. if we have a function fn f(a: T, b: T, c: T) and we call it with - // f(1, 2, 3.0) then the first will force T to be an integer, the second - // then matches and the third is the incompatible argument. - .filter(|(idx, _)| *idx > matched_idx) - { - if let ty::Infer(ty::TyVar(b)) = formal_ty.kind() { - if self.root_var(*a) == self.root_var(*b) { - formal_ty_idxs_matched.push(input_idx.into()); - if expected_ty_matched.is_none() { - expected_ty_matched = Some(expected_ty); - } + let mut idxs_matched: Vec = vec![]; + for (other_idx, (_, _)) in params_with_generics.iter().enumerate().filter( + |(other_idx, (other_generic_param, _))| { + if *other_idx == idx { + return false; } - } + let Some(other_generic_param) = other_generic_param else { + return false; + }; + if matched_inputs[(*other_idx).into()].is_some() { + return false; + } + other_generic_param.name.ident() == generic_param.name.ident() + }, + ) { + idxs_matched.push(other_idx.into()); } - let Some(expected_ty) = expected_ty_matched else { + if idxs_matched.is_empty() { continue; - }; - - let params = self - .tcx - .hir() - .get_if_local(def_id) - .and_then(|node| node.body_id()) - .into_iter() - .flat_map(|id| self.tcx.hir().body(id).params); - - let mut all_pats_matched: Vec = vec![]; - let mut incompatible_pats_matched: Vec = vec![]; - for (idx, param) in params - .into_iter() - .enumerate() - .filter(|(idx, _)| formal_ty_idxs_matched.contains(idx)) - { - let ident = if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind { - format!("`{ident}`") - } else { - format!("`idx:{idx}`") - }; - if matched_inputs[idx.into()].is_none() { - incompatible_pats_matched.push(ident.clone()); - } - all_pats_matched.push(ident); } - let expected_display_type = - self.resolve_vars_if_possible(*expected_ty).sort_string(self.tcx); - let label = if all_pats_matched.len() == 0 { + let expected_display_type = self + .resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1) + .sort_string(self.tcx); + let label = if idxs_matched.len() == params_with_generics.len() - 1 { format!( - "expected all arguments to be {} because they need to match the type of this parameter", + "expected all arguments to be this {} type because they need to match the type of this parameter", expected_display_type ) - } else if all_pats_matched.len() == incompatible_pats_matched.len() { - format!( - "expected {} {} to be {} {} because {} to match the type of this parameter", - format!("argument{}", pluralize!(incompatible_pats_matched.len())), - display_list_with_comma_and(&incompatible_pats_matched), - a_or_an(&expected_display_type), - expected_display_type, - if all_pats_matched.len() == 1 { - "that argument needs" - } else { - "those arguments need" - } - ) } else { format!( - "expected {} {} to be {} {} because the {} {} {} to match the type of this parameter", - format!("argument{}", pluralize!(incompatible_pats_matched.len())), - display_list_with_comma_and(&incompatible_pats_matched), + "expected some other arguments to be {} {} type to match the type of this parameter", a_or_an(&expected_display_type), expected_display_type, - format!("argument{}", pluralize!(all_pats_matched.len())), - display_list_with_comma_and(&all_pats_matched), - format!("need{}", pluralize!(if all_pats_matched.len() == 1 { 0 } else { 1 })), ) }; - err.span_label(matched_arg_span, label); + err.span_label(*matched_arg_span, label); } } + + fn get_hir_params_with_generics( + &self, + def_id: DefId, + is_method: bool, + ) -> Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)> { + let fn_node = self.tcx.hir().get_if_local(def_id); + + let generic_params: Vec>> = fn_node + .and_then(|node| node.fn_decl()) + .into_iter() + .flat_map(|decl| decl.inputs) + .skip(if is_method { 1 } else { 0 }) + .map(|param| { + if let hir::TyKind::Path(QPath::Resolved( + _, + hir::Path { res: Res::Def(_, res_def_id), .. }, + )) = param.kind + { + fn_node + .and_then(|node| node.generics()) + .into_iter() + .flat_map(|generics| generics.params) + .find(|gen| &gen.def_id.to_def_id() == res_def_id) + } else { + None + } + }) + .collect(); + + let params: Vec<&hir::Param<'_>> = fn_node + .and_then(|node| node.body_id()) + .into_iter() + .flat_map(|id| self.tcx.hir().body(id).params) + .skip(if is_method { 1 } else { 0 }) + .collect(); + + generic_params.into_iter().zip(params).collect() + } } struct FindClosureArg<'tcx> { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 6279c402fc80..7f200a7b623d 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -39,39 +39,6 @@ macro_rules! pluralize { }; } -/// Grammatical tool for displaying messages to end users in a nice form. -/// -/// Returns "an" if the given string starts with a vowel, and "a" otherwise. -pub fn a_or_an(s: &str) -> &'static str { - let mut chars = s.chars(); - let Some(mut first_alpha_char) = chars.next() else { - return "a"; - }; - if first_alpha_char == '`' { - let Some(next) = chars.next() else { - return "a"; - }; - first_alpha_char = next; - } - if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) { - "an" - } else { - "a" - } -} - -/// Grammatical tool for displaying messages to end users in a nice form. -/// -/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c" -pub fn display_list_with_comma_and(v: &[T]) -> String { - match v.len() { - 0 => "".to_string(), - 1 => v[0].to_string(), - 2 => format!("{} and {}", v[0], v[1]), - _ => format!("{}, {}", v[0], display_list_with_comma_and(&v[1..])), - } -} - /// Indicates the confidence in the correctness of a suggestion. /// /// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr index 4cbe9124deec..5ad8e35920a1 100644 --- a/tests/ui/argument-suggestions/extra_arguments.stderr +++ b/tests/ui/argument-suggestions/extra_arguments.stderr @@ -45,7 +45,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ + | ^^^^^^^ ----- error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:23:3 @@ -60,7 +60,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ + | ^^^^^^^ ----- error[E0061]: this function takes 1 argument but 3 arguments were supplied --> $DIR/extra_arguments.rs:24:3 @@ -74,7 +74,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ + | ^^^^^^^ ----- help: remove the extra arguments | LL - one_arg(1, "", 1.0); @@ -319,7 +319,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ + | ^^^^^^^ ----- error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:54:3 @@ -334,7 +334,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ + | ^^^^^^^ ----- error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:55:3 @@ -349,7 +349,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ + | ^^^^^^^ ----- error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:60:3 @@ -364,7 +364,7 @@ note: function defined here --> $DIR/extra_arguments.rs:2:4 | LL | fn one_arg(_a: T) {} - | ^^^^^^^ + | ^^^^^^^ ----- error: aborting due to 22 previous errors diff --git a/tests/ui/argument-suggestions/invalid_arguments.stderr b/tests/ui/argument-suggestions/invalid_arguments.stderr index 61a46b067f5b..d26f33d098be 100644 --- a/tests/ui/argument-suggestions/invalid_arguments.stderr +++ b/tests/ui/argument-suggestions/invalid_arguments.stderr @@ -24,7 +24,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:6:4 | LL | fn two_arg_same(_a: i32, _b: i32) {} - | ^^^^^^^^^^^^ ------- ------- + | ^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:17:16 @@ -38,7 +38,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:6:4 | LL | fn two_arg_same(_a: i32, _b: i32) {} - | ^^^^^^^^^^^^ ------- ------- + | ^^^^^^^^^^^^ ------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:18:3 @@ -66,7 +66,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:7:4 | LL | fn two_arg_diff(_a: i32, _b: f32) {} - | ^^^^^^^^^^^^ ------- ------- + | ^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:20:16 @@ -80,7 +80,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:7:4 | LL | fn two_arg_diff(_a: i32, _b: f32) {} - | ^^^^^^^^^^^^ ------- ------- + | ^^^^^^^^^^^^ ------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:21:3 @@ -108,7 +108,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:8:4 | LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} - | ^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:25:21 @@ -122,7 +122,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:8:4 | LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} - | ^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:26:26 @@ -136,7 +136,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:8:4 | LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} - | ^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^ -------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:28:3 @@ -207,7 +207,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:9:4 | LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} - | ^^^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:35:23 @@ -221,7 +221,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:9:4 | LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} - | ^^^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^^^ ------- error[E0308]: mismatched types --> $DIR/invalid_arguments.rs:36:26 @@ -235,7 +235,7 @@ note: function defined here --> $DIR/invalid_arguments.rs:9:4 | LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} - | ^^^^^^^^^^^^^^^^ ------- ------- -------- + | ^^^^^^^^^^^^^^^^ -------- error[E0308]: arguments to this function are incorrect --> $DIR/invalid_arguments.rs:38:3 diff --git a/tests/ui/argument-suggestions/too-long.stderr b/tests/ui/argument-suggestions/too-long.stderr index 9400f2a02a82..04ee9275cb36 100644 --- a/tests/ui/argument-suggestions/too-long.stderr +++ b/tests/ui/argument-suggestions/too-long.stderr @@ -11,31 +11,9 @@ note: method defined here | LL | fn foo( | ^^^ -LL | &self, -LL | a: i32, - | ------ -LL | b: i32, - | ------ -LL | c: i32, - | ------ -LL | d: i32, - | ------ -LL | e: i32, - | ------ +... LL | f: i32, | ------ -LL | g: i32, - | ------ -LL | h: i32, - | ------ -LL | i: i32, - | ------ -LL | j: i32, - | ------ -LL | k: i32, - | ------ -LL | l: i32, - | ------ help: consider dereferencing the borrow | LL | qux.foo(a, b, c, d, e, *f, g, h, i, j, k, l); diff --git a/tests/ui/async-await/coroutine-desc.stderr b/tests/ui/async-await/coroutine-desc.stderr index 5ad54bc5b8e3..1f1e303ea4c6 100644 --- a/tests/ui/async-await/coroutine-desc.stderr +++ b/tests/ui/async-await/coroutine-desc.stderr @@ -5,7 +5,7 @@ LL | fun(async {}, async {}); | --- -------- ^^^^^^^^ expected `async` block, found a different `async` block | | | | | the expected `async` block - | | expected argument `f2` to be an `async` block because that argument needs to match the type of this parameter + | | expected all arguments to be this `async` block type because they need to match the type of this parameter | arguments to this function are incorrect | = note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:17}` @@ -14,10 +14,9 @@ note: function defined here --> $DIR/coroutine-desc.rs:8:4 | LL | fn fun>(f1: F, f2: F) {} - | ^^^ - ----- ----- - | | | | - | | | this parameter needs to match the `async` block type of `f1` - | | `f2` needs to match the type of this parameter + | ^^^ - ----- ----- this parameter needs to match the `async` block type of `f1` + | | | + | | `f2` needs to match the `async` block type of this parameter | `f1` and `f2` all reference this parameter F error[E0308]: mismatched types @@ -26,7 +25,7 @@ error[E0308]: mismatched types LL | fun(one(), two()); | --- ----- ^^^^^ expected future, found a different future | | | - | | expected argument `f2` to be a future because that argument needs to match the type of this parameter + | | expected all arguments to be this future type because they need to match the type of this parameter | arguments to this function are incorrect | = help: consider `await`ing on both `Future`s @@ -35,10 +34,9 @@ note: function defined here --> $DIR/coroutine-desc.rs:8:4 | LL | fn fun>(f1: F, f2: F) {} - | ^^^ - ----- ----- - | | | | - | | | this parameter needs to match the future type of `f1` - | | `f2` needs to match the type of this parameter + | ^^^ - ----- ----- this parameter needs to match the future type of `f1` + | | | + | | `f2` needs to match the future type of this parameter | `f1` and `f2` all reference this parameter F error[E0308]: mismatched types @@ -48,7 +46,7 @@ LL | fun((async || {})(), (async || {})()); | --- --------------- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body | | | | | | | the expected `async` closure body - | | expected argument `f2` to be an `async` closure body because that argument needs to match the type of this parameter + | | expected all arguments to be this `async` closure body type because they need to match the type of this parameter | arguments to this function are incorrect | = note: expected `async` closure body `{async closure body@$DIR/coroutine-desc.rs:14:19: 14:21}` @@ -57,10 +55,9 @@ note: function defined here --> $DIR/coroutine-desc.rs:8:4 | LL | fn fun>(f1: F, f2: F) {} - | ^^^ - ----- ----- - | | | | - | | | this parameter needs to match the `async` closure body type of `f1` - | | `f2` needs to match the type of this parameter + | ^^^ - ----- ----- this parameter needs to match the `async` closure body type of `f1` + | | | + | | `f2` needs to match the `async` closure body type of this parameter | `f1` and `f2` all reference this parameter F error: aborting due to 3 previous errors diff --git a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr index b67f91ff8e28..46723c5a297f 100644 --- a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr +++ b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | test(&mut 7, &7); | ---- ------ ^^ types differ in mutability | | | - | | expected argument `_b` to be an `&mut {integer}` because that argument needs to match the type of this parameter + | | expected all arguments to be this `&mut {integer}` type because they need to match the type of this parameter | arguments to this function are incorrect | = note: expected mutable reference `&mut {integer}` @@ -13,10 +13,9 @@ note: function defined here --> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4 | LL | fn test(_a: T, _b: T) {} - | ^^^^ - ----- ----- - | | | | - | | | this parameter needs to match the `&mut {integer}` type of `_a` - | | `_b` needs to match the type of this parameter + | ^^^^ - ----- ----- this parameter needs to match the `&mut {integer}` type of `_a` + | | | + | | `_b` needs to match the `&mut {integer}` type of this parameter | `_a` and `_b` all reference this parameter T error: aborting due to 1 previous error diff --git a/tests/ui/coercion/coerce-to-bang.stderr b/tests/ui/coercion/coerce-to-bang.stderr index 4c21eef5c291..3c737358adc7 100644 --- a/tests/ui/coercion/coerce-to-bang.stderr +++ b/tests/ui/coercion/coerce-to-bang.stderr @@ -12,7 +12,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:18:13 @@ -28,7 +28,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:26:12 @@ -44,7 +44,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:36:12 @@ -60,7 +60,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:45:12 @@ -76,7 +76,7 @@ note: function defined here --> $DIR/coerce-to-bang.rs:3:4 | LL | fn foo(x: usize, y: !, z: usize) { } - | ^^^ -------- ---- -------- + | ^^^ ---- error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:50:21 diff --git a/tests/ui/fn/fn-item-type.stderr b/tests/ui/fn/fn-item-type.stderr index 24c7a3cb4828..76cdbcceac84 100644 --- a/tests/ui/fn/fn-item-type.stderr +++ b/tests/ui/fn/fn-item-type.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | eq(foo::, bar::); | -- --------- ^^^^^^^^^ expected fn item, found a different fn item | | | - | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter + | | expected all arguments to be this fn item type because they need to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn(_) -> _ {foo::}` @@ -14,10 +14,9 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ - ---- ---- - | | | | - | | | this parameter needs to match the fn item type of `x` - | | `y` needs to match the type of this parameter + | ^^ - ---- ---- this parameter needs to match the fn item type of `x` + | | | + | | `y` needs to match the fn item type of this parameter | `x` and `y` all reference this parameter T = help: consider casting both fn items to fn pointers using `as fn(isize) -> isize` @@ -27,7 +26,7 @@ error[E0308]: mismatched types LL | eq(foo::, foo::); | -- --------- ^^^^^^^^^ expected `u8`, found `i8` | | | - | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter + | | expected all arguments to be this fn item type because they need to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn(_) -> _ {foo::}` @@ -37,10 +36,9 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ - ---- ---- - | | | | - | | | this parameter needs to match the fn item type of `x` - | | `y` needs to match the type of this parameter + | ^^ - ---- ---- this parameter needs to match the fn item type of `x` + | | | + | | `y` needs to match the fn item type of this parameter | `x` and `y` all reference this parameter T = help: consider casting both fn items to fn pointers using `as fn(isize) -> isize` @@ -50,7 +48,7 @@ error[E0308]: mismatched types LL | eq(bar::, bar::>); | -- ------------- ^^^^^^^^^^^^^^ expected `String`, found `Vec` | | | - | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter + | | expected all arguments to be this fn item type because they need to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn(_) -> _ {bar::}` @@ -60,10 +58,9 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ - ---- ---- - | | | | - | | | this parameter needs to match the fn item type of `x` - | | `y` needs to match the type of this parameter + | ^^ - ---- ---- this parameter needs to match the fn item type of `x` + | | | + | | `y` needs to match the fn item type of this parameter | `x` and `y` all reference this parameter T = help: consider casting both fn items to fn pointers using `as fn(isize) -> isize` @@ -73,7 +70,7 @@ error[E0308]: mismatched types LL | eq(::foo, ::foo); | -- ---------------- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16` | | | - | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter + | | expected all arguments to be this fn item type because they need to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn() {::foo}` @@ -83,10 +80,9 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ - ---- ---- - | | | | - | | | this parameter needs to match the fn item type of `x` - | | `y` needs to match the type of this parameter + | ^^ - ---- ---- this parameter needs to match the fn item type of `x` + | | | + | | `y` needs to match the fn item type of this parameter | `x` and `y` all reference this parameter T = help: consider casting both fn items to fn pointers using `as fn()` @@ -96,7 +92,7 @@ error[E0308]: mismatched types LL | eq(foo::, bar:: as fn(isize) -> isize); | -- --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer | | | - | | expected argument `y` to be a fn item because that argument needs to match the type of this parameter + | | expected all arguments to be this fn item type because they need to match the type of this parameter | arguments to this function are incorrect | = note: expected fn item `fn(_) -> _ {foo::}` @@ -106,10 +102,9 @@ note: function defined here --> $DIR/fn-item-type.rs:11:4 | LL | fn eq(x: T, y: T) {} - | ^^ - ---- ---- - | | | | - | | | this parameter needs to match the fn item type of `x` - | | `y` needs to match the type of this parameter + | ^^ - ---- ---- this parameter needs to match the fn item type of `x` + | | | + | | `y` needs to match the fn item type of this parameter | `x` and `y` all reference this parameter T error: aborting due to 5 previous errors diff --git a/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.rs b/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.rs index 9a38b948e8ea..2bd10e762d9a 100644 --- a/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.rs +++ b/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.rs @@ -9,4 +9,6 @@ fn main() { //~^ ERROR arguments to this function are incorrect foo_multi_generics("a", "b", "c", true, false, 32, 2.); //~^ ERROR arguments to this function are incorrect + foo_multi_same("a", 1, 2, "d", "e", 32); + //~^ ERROR arguments to this function are incorrect } diff --git a/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.stderr b/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.stderr index a4f55ce06ac7..a845dfabe93b 100644 --- a/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.stderr +++ b/tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.stderr @@ -4,17 +4,16 @@ error[E0308]: mismatched types LL | foo(1, 2.); | --- - ^^ expected integer, found floating-point number | | | - | | expected argument `b` to be an integer because that argument needs to match the type of this parameter + | | expected all arguments to be this integer type because they need to match the type of this parameter | arguments to this function are incorrect | note: function defined here --> $DIR/generic-mismatch-reporting-issue-116615.rs:1:4 | LL | fn foo(a: T, b: T) {} - | ^^^ - ---- ---- - | | | | - | | | this parameter needs to match the integer type of `a` - | | `b` needs to match the type of this parameter + | ^^^ - ---- ---- this parameter needs to match the integer type of `a` + | | | + | | `b` needs to match the integer type of this parameter | `a` and `b` all reference this parameter T error[E0308]: arguments to this function are incorrect @@ -25,8 +24,8 @@ LL | foo_multi_same("a", "b", false, true, (), 32); | | | | | | | | | expected `&str`, found `bool` | | | expected `&str`, found `bool` - | | expected arguments `c`, `d` and `e` to be an `&str` because those arguments need to match the type of this parameter - | expected arguments `c`, `d` and `e` to be an `&str` because the arguments `b`, `c`, `d` and `e` need to match the type of this parameter + | | expected some other arguments to be an `&str` type to match the type of this parameter + | expected some other arguments to be an `&str` type to match the type of this parameter | note: function defined here --> $DIR/generic-mismatch-reporting-issue-116615.rs:2:4 @@ -37,8 +36,8 @@ LL | fn foo_multi_same(a: T, b: T, c: T, d: T, e: T, f: i32) {} | | | | | | this parameter needs to match the `&str` type of `a` and `b` | | | | | this parameter needs to match the `&str` type of `a` and `b` | | | | this parameter needs to match the `&str` type of `a` and `b` - | | | `c`, `d` and `e` needs to match the type of this parameter - | | `c`, `d` and `e` needs to match the type of this parameter + | | | `c`, `d` and `e` need to match the `&str` type of this parameter + | | `c`, `d` and `e` need to match the `&str` type of this parameter | `a`, `b`, `c`, `d` and `e` all reference this parameter T error[E0308]: arguments to this function are incorrect @@ -47,29 +46,52 @@ error[E0308]: arguments to this function are incorrect LL | foo_multi_generics("a", "b", "c", true, false, 32, 2.); | ^^^^^^^^^^^^^^^^^^ --- --- --- ---- ----- -- -- expected integer, found floating-point number | | | | | | | - | | | | | | expected argument `g` to be an integer because that argument needs to match the type of this parameter + | | | | | | expected some other arguments to be an integer type to match the type of this parameter | | | | | expected `&str`, found `bool` | | | | expected `&str`, found `bool` - | | | expected arguments `d` and `e` to be an `&str` because those arguments need to match the type of this parameter - | | expected arguments `d` and `e` to be an `&str` because the arguments `c`, `d` and `e` need to match the type of this parameter - | expected arguments `d` and `e` to be an `&str` because the arguments `b`, `c`, `d` and `e` need to match the type of this parameter + | | | expected some other arguments to be an `&str` type to match the type of this parameter + | | expected some other arguments to be an `&str` type to match the type of this parameter + | expected some other arguments to be an `&str` type to match the type of this parameter | note: function defined here --> $DIR/generic-mismatch-reporting-issue-116615.rs:3:4 | LL | fn foo_multi_generics(a: T, b: T, c: T, d: T, e: T, f: S, g: S) {} - | ^^^^^^^^^^^^^^^^^^ - - ---- ---- ---- ---- ---- ---- ---- - | | | | | | | | | | - | | | | | | | | | this parameter needs to match the integer type of `f` - | | | | | | | | `g` needs to match the type of this parameter + | ^^^^^^^^^^^^^^^^^^ - - ---- ---- ---- ---- ---- ---- ---- this parameter needs to match the integer type of `f` + | | | | | | | | | + | | | | | | | | `g` needs to match the integer type of this parameter | | | | | | | this parameter needs to match the `&str` type of `a`, `b` and `c` | | | | | | this parameter needs to match the `&str` type of `a`, `b` and `c` - | | | | | `d` and `e` needs to match the type of this parameter - | | | | `d` and `e` needs to match the type of this parameter - | | | `d` and `e` needs to match the type of this parameter + | | | | | `d` and `e` need to match the `&str` type of this parameter + | | | | `d` and `e` need to match the `&str` type of this parameter + | | | `d` and `e` need to match the `&str` type of this parameter | | `a`, `b`, `c`, `d` and `e` all reference this parameter T | `f` and `g` all reference this parameter S -error: aborting due to 3 previous errors +error[E0308]: arguments to this function are incorrect + --> $DIR/generic-mismatch-reporting-issue-116615.rs:12:5 + | +LL | foo_multi_same("a", 1, 2, "d", "e", 32); + | ^^^^^^^^^^^^^^ --- - - --- --- expected some other arguments to be an `&str` type to match the type of this parameter + | | | | | + | | | | expected some other arguments to be an `&str` type to match the type of this parameter + | | | expected `&str`, found integer + | | expected `&str`, found integer + | expected some other arguments to be an `&str` type to match the type of this parameter + | +note: function defined here + --> $DIR/generic-mismatch-reporting-issue-116615.rs:2:4 + | +LL | fn foo_multi_same(a: T, b: T, c: T, d: T, e: T, f: i32) {} + | ^^^^^^^^^^^^^^ - ---- ---- ---- ---- ---- ------ + | | | | | | | + | | | | | | `b` and `c` need to match the `&str` type of this parameter + | | | | | `b` and `c` need to match the `&str` type of this parameter + | | | | this parameter needs to match the `&str` type of `a`, `d` and `e` + | | | this parameter needs to match the `&str` type of `a`, `d` and `e` + | | `b` and `c` need to match the `&str` type of this parameter + | `a`, `b`, `c`, `d` and `e` all reference this parameter T + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/issue-96335.stderr b/tests/ui/never_type/issue-96335.stderr index 13cdbe842c9d..c3d80a425e05 100644 --- a/tests/ui/never_type/issue-96335.stderr +++ b/tests/ui/never_type/issue-96335.stderr @@ -21,7 +21,6 @@ LL | 0.....{loop{}1}; | | | | | expected integer, found `RangeTo<{integer}>` | arguments to this function are incorrect - | expected all arguments to be integer because they need to match the type of this parameter | = note: expected type `{integer}` found struct `RangeTo<{integer}>` diff --git a/tests/ui/parser/issues/issue-93282.stderr b/tests/ui/parser/issues/issue-93282.stderr index fc15865e1a72..c6140bb821e4 100644 --- a/tests/ui/parser/issues/issue-93282.stderr +++ b/tests/ui/parser/issues/issue-93282.stderr @@ -43,7 +43,7 @@ note: function defined here --> $DIR/issue-93282.rs:7:4 | LL | fn bar(a: usize, b: usize) -> usize { - | ^^^ -------- -------- + | ^^^ -------- error: aborting due to 4 previous errors diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr index 1b9ad3a3f167..f0dea66f6128 100644 --- a/tests/ui/span/issue-34264.stderr +++ b/tests/ui/span/issue-34264.stderr @@ -77,7 +77,7 @@ note: function defined here --> $DIR/issue-34264.rs:3:4 | LL | fn bar(x, y: usize) {} - | ^^^ - -------- + | ^^^ -------- error[E0061]: this function takes 2 arguments but 3 arguments were supplied --> $DIR/issue-34264.rs:10:5 diff --git a/tests/ui/tuple/add-tuple-within-arguments.stderr b/tests/ui/tuple/add-tuple-within-arguments.stderr index 8414a51bfd5e..6849128eaddd 100644 --- a/tests/ui/tuple/add-tuple-within-arguments.stderr +++ b/tests/ui/tuple/add-tuple-within-arguments.stderr @@ -8,7 +8,7 @@ note: function defined here --> $DIR/add-tuple-within-arguments.rs:1:4 | LL | fn foo(s: &str, a: (i32, i32), s2: &str) {} - | ^^^ ------- ------------- -------- + | ^^^ ------------- help: wrap these arguments in parentheses to construct a tuple | LL | foo("hi", (1, 2), "hi"); @@ -28,7 +28,7 @@ note: function defined here --> $DIR/add-tuple-within-arguments.rs:3:4 | LL | fn bar(s: &str, a: (&str,), s2: &str) {} - | ^^^ ------- ---------- -------- + | ^^^ ---------- help: use a trailing comma to create a tuple with one element | LL | bar("hi", ("hi",), "hi"); diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr index 63a98a55127a..fbe6bfeebb14 100644 --- a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr +++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr @@ -74,7 +74,7 @@ note: function defined here --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 | LL | fn function(x: T, y: bool) -> T { - | ^^^^^^^^ ---- ------- + | ^^^^^^^^ ---- help: change the type of the numeric literal from `u32` to `u16` | LL | let x: u16 = function(0u16, true); From 4498cd6a8da86e4d7a84953c891281c8c2dace26 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 17 Mar 2024 00:07:42 -0400 Subject: [PATCH 11/51] extend extern tests to include FiveU16s As described in the code, this extends just beyond a 64bit reg, but isn't a round number, so it triggers some edge cases in the cast ABI. --- tests/auxiliary/rust_test_helpers.c | 24 +++++++++++++++ tests/ui/abi/extern/extern-pass-FiveU16s.rs | 30 +++++++++++++++++++ tests/ui/abi/extern/extern-return-FiveU16s.rs | 26 ++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 tests/ui/abi/extern/extern-pass-FiveU16s.rs create mode 100644 tests/ui/abi/extern/extern-return-FiveU16s.rs diff --git a/tests/auxiliary/rust_test_helpers.c b/tests/auxiliary/rust_test_helpers.c index 977ea487a980..965df44c6760 100644 --- a/tests/auxiliary/rust_test_helpers.c +++ b/tests/auxiliary/rust_test_helpers.c @@ -118,6 +118,30 @@ rust_dbg_extern_identity_TwoDoubles(struct TwoDoubles u) { return u; } +struct FiveU16s { + uint16_t one; + uint16_t two; + uint16_t three; + uint16_t four; + uint16_t five; +}; + +struct FiveU16s +rust_dbg_extern_return_FiveU16s() { + struct FiveU16s s; + s.one = 10; + s.two = 20; + s.three = 30; + s.four = 40; + s.five = 50; + return s; +} + +struct FiveU16s +rust_dbg_extern_identity_FiveU16s(struct FiveU16s u) { + return u; +} + struct ManyInts { int8_t arg1; int16_t arg2; diff --git a/tests/ui/abi/extern/extern-pass-FiveU16s.rs b/tests/ui/abi/extern/extern-pass-FiveU16s.rs new file mode 100644 index 000000000000..5f1307beb28e --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-FiveU16s.rs @@ -0,0 +1,30 @@ +//@ run-pass +#![allow(improper_ctypes)] + +// Test a foreign function that accepts and returns a struct by value. + +// FiveU16s in particular is interesting because it is larger than a single 64 bit or 32 bit +// register, which are used as cast destinations on some targets, but does not evenly divide those +// sizes, causing there to be padding in the last element. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct FiveU16s { + one: u16, + two: u16, + three: u16, + four: u16, + five: u16, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_FiveU16s(v: FiveU16s) -> FiveU16s; +} + +pub fn main() { + unsafe { + let x = FiveU16s { one: 22, two: 23, three: 24, four: 25, five: 26 }; + let y = rust_dbg_extern_identity_FiveU16s(x); + assert_eq!(x, y); + } +} diff --git a/tests/ui/abi/extern/extern-return-FiveU16s.rs b/tests/ui/abi/extern/extern-return-FiveU16s.rs new file mode 100644 index 000000000000..d8ae8b2661c5 --- /dev/null +++ b/tests/ui/abi/extern/extern-return-FiveU16s.rs @@ -0,0 +1,26 @@ +//@ run-pass +#![allow(improper_ctypes)] + +pub struct FiveU16s { + one: u16, + two: u16, + three: u16, + four: u16, + five: u16, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_return_FiveU16s() -> FiveU16s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_FiveU16s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + assert_eq!(y.three, 30); + assert_eq!(y.four, 40); + assert_eq!(y.five, 50); + } +} From 41c6fa812b0bed63e54c455134734452f9cee97c Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 17 Mar 2024 00:11:54 -0400 Subject: [PATCH 12/51] sparc64: fix crash in ABI code for { f64, f32 } struct This would trigger a `Size::sub: 0 - 8 would result in negative size` abort, if `data.last_offset > offset`. This is almost hilariously easy to trigger (https://godbolt.org/z/8rbv57xET): ```rust #[repr(C)] pub struct DoubleFloat { f: f64, g: f32, } #[no_mangle] pub extern "C" fn foo(x: DoubleFloat) {} ``` Tests for this will be covered by the cast-target-abi.rs test added in a later commit. --- compiler/rustc_target/src/abi/call/sparc64.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index cbed5b4afc13..377fee0a2f51 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -35,12 +35,14 @@ where data.last_offset = data.last_offset + Reg::i32().size; } - for _ in 0..((offset - data.last_offset).bits() / 64) - .min((data.prefix.len() - data.prefix_index) as u64) - { - data.prefix[data.prefix_index] = Some(Reg::i64()); - data.prefix_index += 1; - data.last_offset = data.last_offset + Reg::i64().size; + if data.last_offset < offset { + for _ in 0..((offset - data.last_offset).bits() / 64) + .min((data.prefix.len() - data.prefix_index) as u64) + { + data.prefix[data.prefix_index] = Some(Reg::i64()); + data.prefix_index += 1; + data.last_offset = data.last_offset + Reg::i64().size; + } } if data.last_offset < offset { From 74ef47e90ca1466ea7f3dd8c3ec3738f05345809 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 17 Mar 2024 00:14:20 -0400 Subject: [PATCH 13/51] make CastTarget::size and CastTarget::llvm_type consistent, remove special case that's not present in Clang Making the methods consistent doesn't require much justification. It's required for us to generate correct code. The special case was present near the end of `CastTarget::llvm_type`, and resulted in the final integer component of the ABI type being shrunk to the smallest integer that fits. You can see this in action here (https://godbolt.org/z/Pe73cr91d), where, for a struct with 5 u16 elements, rustc generates `{ i64, i16 }`, while Clang generates `[2 x i64]`. This special case was added a long time ago, when the function was originally written [1]. That commit consolidated logic from many backends, and in some of the code it deleted, sparc64 [2] and powerpc64 [3] had similar special cases. However, looking at Clang today, it doesn't have this special case for sparc64 (https://godbolt.org/z/YaafvYWdf) or powerpc64 (https://godbolt.org/z/5c3YePTje), so this change just removes it. [1]: https://github.com/rust-lang/rust/commit/f0636b61c7f84962a609e831760db9d77f4f5e14#diff-183c4dadf10704bd1f521b71f71d89bf755c9603a93f894d66c03bb1effc6021R231 [2]: https://github.com/rust-lang/rust/commit/f0636b61c7f84962a609e831760db9d77f4f5e14#diff-2d8f87ea6db6d7f0a6fbeb1d5549adc07e93331278d951a1e051a40f92914436L163-L166 [3]: https://github.com/rust-lang/rust/commit/f0636b61c7f84962a609e831760db9d77f4f5e14#diff-88af4a9df9ead503a5c7774a0455d270dea3ba60e9b0ec1ce550b4c53d3bce3bL172-L175 --- compiler/rustc_codegen_llvm/src/abi.rs | 52 +++++++++++------------ compiler/rustc_target/src/abi/call/mod.rs | 25 ++++++----- 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index e5f5146fac8f..1990634fc512 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -16,13 +16,15 @@ pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc_middle::ty::Ty; use rustc_session::config; pub use rustc_target::abi::call::*; -use rustc_target::abi::{self, HasDataLayout, Int}; +use rustc_target::abi::{self, HasDataLayout, Int, Size}; pub use rustc_target::spec::abi::Abi; use rustc_target::spec::SanitizerSet; use libc::c_uint; use smallvec::SmallVec; +use std::cmp; + pub trait ArgAttributesExt { fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value); fn apply_attrs_to_callsite( @@ -130,42 +132,36 @@ impl LlvmType for Reg { impl LlvmType for CastTarget { fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { let rest_ll_unit = self.rest.unit.llvm_type(cx); - let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 { - (0, 0) + let rest_count = if self.rest.total == Size::ZERO { + 0 } else { - ( - self.rest.total.bytes() / self.rest.unit.size.bytes(), - self.rest.total.bytes() % self.rest.unit.size.bytes(), - ) + assert_ne!( + self.rest.unit.size, + Size::ZERO, + "total size {:?} cannot be divided into units of zero size", + self.rest.total + ); + if self.rest.total.bytes() % self.rest.unit.size.bytes() != 0 { + assert_eq!(self.rest.unit.kind, RegKind::Integer, "only int regs can be split"); + } + self.rest.total.bytes().div_ceil(self.rest.unit.size.bytes()) }; + // Simplify to a single unit or an array if there's no prefix. + // This produces the same layout, but using a simpler type. if self.prefix.iter().all(|x| x.is_none()) { - // Simplify to a single unit when there is no prefix and size <= unit size - if self.rest.total <= self.rest.unit.size { + if rest_count == 1 { return rest_ll_unit; } - // Simplify to array when all chunks are the same size and type - if rem_bytes == 0 { - return cx.type_array(rest_ll_unit, rest_count); - } - } - - // Create list of fields in the main structure - let mut args: Vec<_> = self - .prefix - .iter() - .flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx))) - .chain((0..rest_count).map(|_| rest_ll_unit)) - .collect(); - - // Append final integer - if rem_bytes != 0 { - // Only integers can be really split further. - assert_eq!(self.rest.unit.kind, RegKind::Integer); - args.push(cx.type_ix(rem_bytes * 8)); + return cx.type_array(rest_ll_unit, rest_count); } + // Generate a struct type with the prefix and the "rest" arguments. + let prefix_args = + self.prefix.iter().flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx))); + let rest_args = (0..rest_count).map(|_| rest_ll_unit); + let args: Vec<_> = prefix_args.chain(rest_args).collect(); cx.type_struct(&args, false) } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 486afc5f8f30..643ba9f1cddc 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -251,9 +251,9 @@ pub struct Uniform { /// The total size of the argument, which can be: /// * equal to `unit.size` (one scalar/vector), /// * a multiple of `unit.size` (an array of scalar/vectors), - /// * if `unit.kind` is `Integer`, the last element - /// can be shorter, i.e., `{ i64, i64, i32 }` for - /// 64-bit integers with a total size of 20 bytes. + /// * if `unit.kind` is `Integer`, the last element can be shorter, i.e., `{ i64, i64, i32 }` + /// for 64-bit integers with a total size of 20 bytes. When the argument is actually passed, + /// this size will be rounded up to the nearest multiple of `unit.size`. pub total: Size, } @@ -319,14 +319,17 @@ impl CastTarget { } pub fn size(&self, _cx: &C) -> Size { - let mut size = self.rest.total; - for i in 0..self.prefix.iter().count() { - match self.prefix[i] { - Some(v) => size += v.size, - None => {} - } - } - return size; + // Prefix arguments are passed in specific designated registers + let prefix_size = self + .prefix + .iter() + .filter_map(|x| x.map(|reg| reg.size)) + .fold(Size::ZERO, |acc, size| acc + size); + // Remaining arguments are passed in chunks of the unit size + let rest_size = + self.rest.unit.size * self.rest.total.bytes().div_ceil(self.rest.unit.size.bytes()); + + prefix_size + rest_size } pub fn align(&self, cx: &C) -> Align { From 8841315d3e9aa02cb54d757cb5cd8131c263a893 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 17 Mar 2024 00:22:35 -0400 Subject: [PATCH 14/51] make PassMode::Cast consistently copy between Rust/ABI representation Previously, we did this slightly incorrectly for return values, and didn't do it at all for arguments. --- compiler/rustc_codegen_llvm/src/abi.rs | 68 ++++++++------------- compiler/rustc_codegen_ssa/src/mir/block.rs | 32 +++++++++- 2 files changed, 56 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 1990634fc512..d2828669d438 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -211,47 +211,33 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { bug!("unsized `ArgAbi` must be handled through `store_fn_arg`"); } PassMode::Cast { cast, pad_i32: _ } => { - // FIXME(eddyb): Figure out when the simpler Store is safe, clang - // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}. - let can_store_through_cast_ptr = false; - if can_store_through_cast_ptr { - bx.store(val, dst.llval, self.layout.align.abi); - } else { - // The actual return type is a struct, but the ABI - // adaptation code has cast it into some scalar type. The - // code that follows is the only reliable way I have - // found to do a transform like i64 -> {i32,i32}. - // Basically we dump the data onto the stack then memcpy it. - // - // Other approaches I tried: - // - Casting rust ret pointer to the foreign type and using Store - // is (a) unsafe if size of foreign type > size of rust type and - // (b) runs afoul of strict aliasing rules, yielding invalid - // assembly under -O (specifically, the store gets removed). - // - Truncating foreign type to correct integral type and then - // bitcasting to the struct type yields invalid cast errors. - - // We instead thus allocate some scratch space... - let scratch_size = cast.size(bx); - let scratch_align = cast.align(bx); - let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align); - bx.lifetime_start(llscratch, scratch_size); - - // ... where we first store the value... - bx.store(val, llscratch, scratch_align); - - // ... and then memcpy it to the intended destination. - bx.memcpy( - dst.llval, - self.layout.align.abi, - llscratch, - scratch_align, - bx.const_usize(self.layout.size.bytes()), - MemFlags::empty(), - ); - - bx.lifetime_end(llscratch, scratch_size); - } + // The ABI mandates that the value is passed as a different struct representation. + // Spill and reload it from the stack to convert from the ABI representation to + // the Rust representation. + let scratch_size = cast.size(bx); + let scratch_align = cast.align(bx); + // Note that the ABI type may be either larger or smaller than the Rust type, + // due to the presence or absence of trailing padding. For example: + // - On some ABIs, the Rust layout { f64, f32, } may omit padding + // when passed by value, making it smaller. + // - On some ABIs, the Rust layout { u16, u16, u16 } may be padded up to 8 bytes + // when passed by value, making it larger. + let copy_bytes = cmp::min(scratch_size.bytes(), self.layout.size.bytes()); + // Allocate some scratch space... + let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align); + bx.lifetime_start(llscratch, scratch_size); + // ...store the value... + bx.store(val, llscratch, scratch_align); + // ... and then memcpy it to the intended destination. + bx.memcpy( + dst.llval, + self.layout.align.abi, + llscratch, + scratch_align, + bx.const_usize(copy_bytes), + MemFlags::empty(), + ); + bx.lifetime_end(llscratch, scratch_size); } _ => { OperandRef::from_immediate_or_packed_pair(bx, val, self.layout).val.store(bx, dst); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 9bb2a5282658..333c03ce8237 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1471,9 +1471,35 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if by_ref && !arg.is_indirect() { // Have to load the argument, maybe while casting it. - if let PassMode::Cast { cast: ty, .. } = &arg.mode { - let llty = bx.cast_backend_type(ty); - llval = bx.load(llty, llval, align.min(arg.layout.align.abi)); + if let PassMode::Cast { cast, pad_i32: _ } = &arg.mode { + // The ABI mandates that the value is passed as a different struct representation. + // Spill and reload it from the stack to convert from the Rust representation to + // the ABI representation. + let scratch_size = cast.size(bx); + let scratch_align = cast.align(bx); + // Note that the ABI type may be either larger or smaller than the Rust type, + // due to the presence or absence of trailing padding. For example: + // - On some ABIs, the Rust layout { f64, f32, } may omit padding + // when passed by value, making it smaller. + // - On some ABIs, the Rust layout { u16, u16, u16 } may be padded up to 8 bytes + // when passed by value, making it larger. + let copy_bytes = cmp::min(scratch_size.bytes(), arg.layout.size.bytes()); + // Allocate some scratch space... + let llscratch = bx.alloca(bx.cast_backend_type(cast), scratch_align); + bx.lifetime_start(llscratch, scratch_size); + // ...memcpy the value... + bx.memcpy( + llscratch, + scratch_align, + llval, + align, + bx.const_usize(copy_bytes), + MemFlags::empty(), + ); + // ...and then load it with the ABI type. + let cast_ty = bx.cast_backend_type(cast); + llval = bx.load(cast_ty, llscratch, scratch_align); + bx.lifetime_end(llscratch, scratch_size); } else { // We can't use `PlaceRef::load` here because the argument // may have a type we don't treat as immediate, but the ABI From 8d5fd94e6292b298e59a637d84fa16bed30d64d4 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 17 Mar 2024 00:25:36 -0400 Subject: [PATCH 15/51] add tests for PassMode::Cast fixes Tests added in cast-target-abi.rs, covering the single element, array, and prefix cases in `CastTarget::llvm_type`, and the Rust-is-larger/smaller cases in the Rust<->ABI copying code. ffi-out-of-bounds-loads.rs was overhauled to be runnable on any platform. Its alignment also increases due to the removal of a `min` in the previous commit; this was probably an insufficient workaround for this issue or similar. The higher alignment is fine, since the alloca is actually aligned to 8 bytes, as the test checks now confirm. --- tests/codegen/cast-target-abi.rs | 269 ++++++++++++++++++ tests/codegen/cffi/ffi-out-of-bounds-loads.rs | 28 +- 2 files changed, 291 insertions(+), 6 deletions(-) create mode 100644 tests/codegen/cast-target-abi.rs diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs new file mode 100644 index 000000000000..2d800d044726 --- /dev/null +++ b/tests/codegen/cast-target-abi.rs @@ -0,0 +1,269 @@ +// ignore-tidy-linelength +//@ revisions:aarch64 loongarch64 powerpc64 sparc64 +//@ compile-flags: -O -C no-prepopulate-passes + +//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@[aarch64] needs-llvm-components: arm +//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu +//@[loongarch64] needs-llvm-components: loongarch +//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//@[powerpc64] needs-llvm-components: powerpc +//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//@[sparc64] needs-llvm-components: sparc + +// Tests that arguments with `PassMode::Cast` are handled correctly. + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang="sized"] trait Sized { } +#[lang="freeze"] trait Freeze { } +#[lang="copy"] trait Copy { } + +// This struct will be passed as a single `i64` or `i32`. +// This may be (if `i64)) larger than the Rust layout, which is just `{ i16, i16 }`. +#[repr(C)] +pub struct TwoU16s { + a: u16, + b: u16, +} + +// This struct will be passed as `[2 x i64]`. +// This is larger than the Rust layout. +#[repr(C)] +pub struct FiveU16s { + a: u16, + b: u16, + c: u16, + d: u16, + e: u16, +} + +// This struct will be passed as `[2 x double]`. +// This is the same as the Rust layout. +#[repr(C)] +pub struct DoubleDouble { + f: f64, + g: f64, +} + +// On loongarch, this struct will be passed as `{ double, float }`. +// This is smaller than the Rust layout, which has trailing padding (`{ f64, f32, }`) +#[repr(C)] +pub struct DoubleFloat { + f: f64, + g: f32, +} + +extern "C" { + fn receives_twou16s(x: TwoU16s); + fn returns_twou16s() -> TwoU16s; + + fn receives_fiveu16s(x: FiveU16s); + fn returns_fiveu16s() -> FiveU16s; + + fn receives_doubledouble(x: DoubleDouble); + fn returns_doubledouble() -> DoubleDouble; + + fn receives_doublefloat(x: DoubleFloat); + fn returns_doublefloat() -> DoubleFloat; +} + +// CHECK-LABEL: @call_twou16s +#[no_mangle] +pub unsafe fn call_twou16s() { + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] + // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i32]], align [[ABI_ALIGN:4]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] + + // CHECK: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] + + // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 4, i1 false) + // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // CHECK: call void @receives_twou16s([[ABI_TYPE]] [[ABI_VALUE]]) + let x = TwoU16s { a: 1, b: 2 }; + receives_twou16s(x); +} + +// CHECK-LABEL: @return_twou16s +#[no_mangle] +pub unsafe fn return_twou16s() -> TwoU16s { + // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. + + // powerpc64: [[RETVAL:%.+]] = alloca %TwoU16s, align 2 + // powerpc64: call void @returns_twou16s(ptr {{.+}} [[RETVAL]]) + + + // The other targets copy the cast ABI type to an alloca. + + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] + + // aarch64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] + // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] + // sparc64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] + + // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s() + // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s() + // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s() + + // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + + // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 4, i1 false) + // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 4, i1 false) + // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 4, i1 false) + returns_twou16s() +} + +// CHECK-LABEL: @call_fiveu16s +#[no_mangle] +pub unsafe fn call_fiveu16s() { + // CHECK: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + + // CHECK: [[RUST_ALLOCA:%.+]] = alloca %FiveU16s, align 2 + + // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 10, i1 false) + // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // CHECK: call void @receives_fiveu16s([[ABI_TYPE]] [[ABI_VALUE]]) + let x = FiveU16s { a: 1, b: 2, c: 3, d: 4, e: 5 }; + receives_fiveu16s(x); +} + +// CHECK-LABEL: @return_fiveu16s +// CHECK-SAME: (ptr {{.+}} sret([10 x i8]) align [[RUST_ALIGN:2]] dereferenceable(10) [[RET_PTR:%.+]]) +#[no_mangle] +pub unsafe fn return_fiveu16s() -> FiveU16s { + // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. + + // powerpc64: call void @returns_fiveu16s(ptr {{.+}} [[RET_PTR]]) + + + // The other targets copy the cast ABI type to the sret pointer. + + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + + // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s() + // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s() + // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s() + + // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + + // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RET_PTR]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 10, i1 false) + // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RET_PTR]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 10, i1 false) + // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RET_PTR]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 10, i1 false) + returns_fiveu16s() +} + +// CHECK-LABEL: @call_doubledouble +#[no_mangle] +pub unsafe fn call_doubledouble() { + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x double\]]], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] + // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] + + // CHECK: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] + + // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) + // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // CHECK: call void @receives_doubledouble([[ABI_TYPE]] [[ABI_VALUE]]) + let x = DoubleDouble { f: 1., g: 2. }; + receives_doubledouble(x); +} + +// CHECK-LABEL: @return_doubledouble +#[no_mangle] +pub unsafe fn return_doubledouble() -> DoubleDouble { + // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. + + // powerpc64: [[RETVAL:%.+]] = alloca %DoubleDouble, align 8 + // powerpc64: call void @returns_doubledouble(ptr {{.+}} [[RETVAL]]) + + + // The other targets copy the cast ABI type to an alloca. + + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x double\]]], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] + + // aarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] + // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] + // sparc64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] + + // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble() + // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble() + // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble() + + // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + + // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) + // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) + // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) + returns_doubledouble() +} + +// CHECK-LABEL: @call_doublefloat +#[no_mangle] +pub unsafe fn call_doublefloat() { + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]] + // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float, i32, i64 }]], align [[ABI_ALIGN:8]] + + // CHECK: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] + + // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) + // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 12, i1 false) + // powerpc64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) + // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) + + // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // CHECK: call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]]) + let x = DoubleFloat { f: 1., g: 2. }; + receives_doublefloat(x); +} + +// CHECK-LABEL: @return_doublefloat +#[no_mangle] +pub unsafe fn return_doublefloat() -> DoubleFloat { + // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. + + // powerpc64: [[RETVAL:%.+]] = alloca %DoubleFloat, align 8 + // powerpc64: call void @returns_doublefloat(ptr {{.+}} [[RETVAL]]) + + + // The other targets copy the cast ABI type to an alloca. + + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float, i32, i64 }]], align [[ABI_ALIGN:8]] + + // aarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] + // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] + // sparc64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] + + // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat() + // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat() + // sparc64: [[ABI_VALUE:%.+]] = call inreg [[ABI_TYPE]] @returns_doublefloat() + + // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + + // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) + // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 12, i1 false) + // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) + returns_doublefloat() +} diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs index 7eda6cf4d576..8b32e902b3f5 100644 --- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs +++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs @@ -1,8 +1,21 @@ +//@ revisions: linux apple +//@ compile-flags: -C opt-level=0 -C no-prepopulate-passes + +//@[linux] compile-flags: --target x86_64-unknown-linux-gnu +//@[linux] needs-llvm-components: x86 +//@[apple] compile-flags: --target x86_64-apple-darwin +//@[apple] needs-llvm-components: x86 + // Regression test for #29988 -//@ compile-flags: -C no-prepopulate-passes -//@ only-x86_64 -//@ ignore-windows +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang="sized"] trait Sized { } +#[lang="freeze"] trait Freeze { } +#[lang="copy"] trait Copy { } #[repr(C)] struct S { @@ -15,11 +28,14 @@ extern "C" { fn foo(s: S); } -fn main() { +// CHECK-LABEL: @test +#[no_mangle] +pub fn test() { let s = S { f1: 1, f2: 2, f3: 3 }; unsafe { - // CHECK: load { i64, i32 }, {{.*}}, align 4 - // CHECK: call void @foo({ i64, i32 } {{.*}}) + // CHECK: [[ALLOCA:%.+]] = alloca { i64, i32 }, align 8 + // CHECK: [[LOAD:%.+]] = load { i64, i32 }, ptr [[ALLOCA]], align 8 + // CHECK: call void @foo({ i64, i32 } [[LOAD]]) foo(s); } } From 6577aefc6f3863607b0d90d836d594a1887a0d90 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 17 Mar 2024 13:33:59 -0400 Subject: [PATCH 16/51] Revert "sparc64: fix crash in ABI code for { f64, f32 } struct" This reverts commit 41c6fa812b0bed63e54c455134734452f9cee97c. --- compiler/rustc_target/src/abi/call/sparc64.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 377fee0a2f51..cbed5b4afc13 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -35,14 +35,12 @@ where data.last_offset = data.last_offset + Reg::i32().size; } - if data.last_offset < offset { - for _ in 0..((offset - data.last_offset).bits() / 64) - .min((data.prefix.len() - data.prefix_index) as u64) - { - data.prefix[data.prefix_index] = Some(Reg::i64()); - data.prefix_index += 1; - data.last_offset = data.last_offset + Reg::i64().size; - } + for _ in 0..((offset - data.last_offset).bits() / 64) + .min((data.prefix.len() - data.prefix_index) as u64) + { + data.prefix[data.prefix_index] = Some(Reg::i64()); + data.prefix_index += 1; + data.last_offset = data.last_offset + Reg::i64().size; } if data.last_offset < offset { From dec81ac223aeda234e72de0eb70443153ef67e96 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 17 Mar 2024 13:40:01 -0400 Subject: [PATCH 17/51] disable crashing test on sparc --- tests/codegen/cast-target-abi.rs | 35 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs index 2d800d044726..e6024f03425f 100644 --- a/tests/codegen/cast-target-abi.rs +++ b/tests/codegen/cast-target-abi.rs @@ -67,7 +67,10 @@ extern "C" { fn receives_doubledouble(x: DoubleDouble); fn returns_doubledouble() -> DoubleDouble; + // These functions cause an ICE in sparc64 ABI code (https://github.com/rust-lang/rust/issues/122620) + #[cfg(not(target_arch = "sparc64"))] fn receives_doublefloat(x: DoubleFloat); + #[cfg(not(target_arch = "sparc64"))] fn returns_doublefloat() -> DoubleFloat; } @@ -214,28 +217,41 @@ pub unsafe fn return_doubledouble() -> DoubleDouble { returns_doubledouble() } -// CHECK-LABEL: @call_doublefloat +// This test causes an ICE in sparc64 ABI code (https://github.com/rust-lang/rust/issues/122620) +#[cfg(not(target_arch = "sparc64"))] +// aarch64-LABEL: @call_doublefloat +// loongarch64-LABEL: @call_doublefloat +// powerpc64-LABEL: @call_doublefloat #[no_mangle] pub unsafe fn call_doublefloat() { // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]] // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] - // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float, i32, i64 }]], align [[ABI_ALIGN:8]] - // CHECK: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] + // aarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] + // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] + // powerpc64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 12, i1 false) // powerpc64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) - // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) - // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // CHECK: call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]]) + // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // powerpc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + + // aarch64: call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]]) + // loongarch64: call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]]) + // powerpc64: call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]]) let x = DoubleFloat { f: 1., g: 2. }; receives_doublefloat(x); } -// CHECK-LABEL: @return_doublefloat +// This test causes an ICE in sparc64 ABI code (https://github.com/rust-lang/rust/issues/122620) +#[cfg(not(target_arch = "sparc64"))] +// aarch64-LABEL: @return_doublefloat +// loongarch64-LABEL: @return_doublefloat +// powerpc64-LABEL: @return_doublefloat #[no_mangle] pub unsafe fn return_doublefloat() -> DoubleFloat { // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. @@ -248,22 +264,17 @@ pub unsafe fn return_doublefloat() -> DoubleFloat { // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]] - // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float, i32, i64 }]], align [[ABI_ALIGN:8]] // aarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] - // sparc64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat() // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat() - // sparc64: [[ABI_VALUE:%.+]] = call inreg [[ABI_TYPE]] @returns_doublefloat() // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 12, i1 false) - // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) returns_doublefloat() } From 4c0aea0d47d9e01642ee59a8620795558f098408 Mon Sep 17 00:00:00 2001 From: Caio Date: Sun, 31 Mar 2024 14:58:17 -0300 Subject: [PATCH 18/51] Move some tests --- src/tools/tidy/src/issues.txt | 18 ++++++++---------- src/tools/tidy/src/ui_tests.rs | 2 +- tests/ui/{issues => closures}/issue-1460.rs | 0 .../ui/{issues => closures}/issue-1460.stderr | 0 tests/ui/{issues => fn}/issue-1451.rs | 0 tests/ui/{issues => fn}/issue-1900.rs | 0 tests/ui/{issues => fn}/issue-1900.stderr | 0 tests/ui/issues/issue-1476.rs | 3 --- tests/ui/issues/issue-1476.stderr | 9 --------- tests/ui/issues/issue-1696.rs | 8 -------- tests/ui/{issues => loops}/issue-1962.fixed | 0 tests/ui/{issues => loops}/issue-1962.rs | 0 tests/ui/{issues => loops}/issue-1962.stderr | 0 tests/ui/{issues => loops}/issue-1974.rs | 0 .../{issues => mismatched_types}/issue-1362.rs | 0 .../issue-1362.stderr | 0 .../issue-1448-2.rs | 0 .../issue-1448-2.stderr | 0 tests/ui/{issues => static}/issue-1660.rs | 0 19 files changed, 9 insertions(+), 31 deletions(-) rename tests/ui/{issues => closures}/issue-1460.rs (100%) rename tests/ui/{issues => closures}/issue-1460.stderr (100%) rename tests/ui/{issues => fn}/issue-1451.rs (100%) rename tests/ui/{issues => fn}/issue-1900.rs (100%) rename tests/ui/{issues => fn}/issue-1900.stderr (100%) delete mode 100644 tests/ui/issues/issue-1476.rs delete mode 100644 tests/ui/issues/issue-1476.stderr delete mode 100644 tests/ui/issues/issue-1696.rs rename tests/ui/{issues => loops}/issue-1962.fixed (100%) rename tests/ui/{issues => loops}/issue-1962.rs (100%) rename tests/ui/{issues => loops}/issue-1962.stderr (100%) rename tests/ui/{issues => loops}/issue-1974.rs (100%) rename tests/ui/{issues => mismatched_types}/issue-1362.rs (100%) rename tests/ui/{issues => mismatched_types}/issue-1362.stderr (100%) rename tests/ui/{issues => mismatched_types}/issue-1448-2.rs (100%) rename tests/ui/{issues => mismatched_types}/issue-1448-2.stderr (100%) rename tests/ui/{issues => static}/issue-1660.rs (100%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index f6b1d45ee94e..6e8452493421 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -434,6 +434,7 @@ "ui/closures/issue-111932.rs", "ui/closures/issue-113087.rs", "ui/closures/issue-11873.rs", +"ui/closures/issue-1460.rs", "ui/closures/issue-23012-supertrait-signature-inference.rs", "ui/closures/issue-25439.rs", "ui/closures/issue-41366.rs", @@ -1007,6 +1008,8 @@ "ui/fmt/issue-86085.rs", "ui/fmt/issue-89173.rs", "ui/fmt/issue-91556.rs", +"ui/fn/issue-1451.rs", +"ui/fn/issue-1900.rs", "ui/fn/issue-3044.rs", "ui/fn/issue-3099.rs", "ui/fn/issue-3904.rs", @@ -1550,7 +1553,6 @@ "ui/issues/issue-13497-2.rs", "ui/issues/issue-13497.rs", "ui/issues/issue-13507-2.rs", -"ui/issues/issue-1362.rs", "ui/issues/issue-13620.rs", "ui/issues/issue-13665.rs", "ui/issues/issue-13703.rs", @@ -1576,12 +1578,8 @@ "ui/issues/issue-14399.rs", "ui/issues/issue-14421.rs", "ui/issues/issue-14422.rs", -"ui/issues/issue-1448-2.rs", -"ui/issues/issue-1451.rs", "ui/issues/issue-14541.rs", -"ui/issues/issue-1460.rs", "ui/issues/issue-14721.rs", -"ui/issues/issue-1476.rs", "ui/issues/issue-14821.rs", "ui/issues/issue-14845.rs", "ui/issues/issue-14853.rs", @@ -1631,7 +1629,6 @@ "ui/issues/issue-16560.rs", "ui/issues/issue-16562.rs", "ui/issues/issue-16596.rs", -"ui/issues/issue-1660.rs", "ui/issues/issue-16643.rs", "ui/issues/issue-16648.rs", "ui/issues/issue-16668.rs", @@ -1645,7 +1642,6 @@ "ui/issues/issue-16819.rs", "ui/issues/issue-16922-rpass.rs", "ui/issues/issue-16939.rs", -"ui/issues/issue-1696.rs", "ui/issues/issue-16966.rs", "ui/issues/issue-16994.rs", "ui/issues/issue-17001.rs", @@ -1725,7 +1721,6 @@ "ui/issues/issue-18952.rs", "ui/issues/issue-18959.rs", "ui/issues/issue-18988.rs", -"ui/issues/issue-1900.rs", "ui/issues/issue-19001.rs", "ui/issues/issue-19037.rs", "ui/issues/issue-19086.rs", @@ -1753,12 +1748,10 @@ "ui/issues/issue-19482.rs", "ui/issues/issue-19499.rs", "ui/issues/issue-19601.rs", -"ui/issues/issue-1962.rs", "ui/issues/issue-19631.rs", "ui/issues/issue-19632.rs", "ui/issues/issue-19692.rs", "ui/issues/issue-19734.rs", -"ui/issues/issue-1974.rs", "ui/issues/issue-19811-escape-unicode.rs", "ui/issues/issue-19850.rs", "ui/issues/issue-19922.rs", @@ -2856,6 +2849,8 @@ "ui/lint/unused/issue-92751.rs", "ui/lint/unused/issue-96606.rs", "ui/lint/use-redundant/issue-92904.rs", +"ui/loops/issue-1962.rs", +"ui/loops/issue-1974.rs", "ui/loops/issue-43162.rs", "ui/loops/issue-50576.rs", "ui/loops/issue-69225-SCEVAddExpr-wrap-flag.rs", @@ -3045,6 +3040,8 @@ "ui/mismatched_types/issue-118145-unwrap-for-shorthand.rs", "ui/mismatched_types/issue-118510.rs", "ui/mismatched_types/issue-13033.rs", +"ui/mismatched_types/issue-1362.rs", +"ui/mismatched_types/issue-1448-2.rs", "ui/mismatched_types/issue-19109.rs", "ui/mismatched_types/issue-26480.rs", "ui/mismatched_types/issue-35030.rs", @@ -3860,6 +3857,7 @@ "ui/stability-attribute/issue-28388-3.rs", "ui/stability-attribute/issue-99286-stable-intrinsics.rs", "ui/static/auxiliary/issue_24843.rs", +"ui/static/issue-1660.rs", "ui/static/issue-18118-2.rs", "ui/static/issue-18118.rs", "ui/static/issue-24446.rs", diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index fe27964981e0..454811c5fbbf 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1750; +const ISSUES_ENTRY_LIMIT: usize = 1733; const ROOT_ENTRY_LIMIT: usize = 860; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ diff --git a/tests/ui/issues/issue-1460.rs b/tests/ui/closures/issue-1460.rs similarity index 100% rename from tests/ui/issues/issue-1460.rs rename to tests/ui/closures/issue-1460.rs diff --git a/tests/ui/issues/issue-1460.stderr b/tests/ui/closures/issue-1460.stderr similarity index 100% rename from tests/ui/issues/issue-1460.stderr rename to tests/ui/closures/issue-1460.stderr diff --git a/tests/ui/issues/issue-1451.rs b/tests/ui/fn/issue-1451.rs similarity index 100% rename from tests/ui/issues/issue-1451.rs rename to tests/ui/fn/issue-1451.rs diff --git a/tests/ui/issues/issue-1900.rs b/tests/ui/fn/issue-1900.rs similarity index 100% rename from tests/ui/issues/issue-1900.rs rename to tests/ui/fn/issue-1900.rs diff --git a/tests/ui/issues/issue-1900.stderr b/tests/ui/fn/issue-1900.stderr similarity index 100% rename from tests/ui/issues/issue-1900.stderr rename to tests/ui/fn/issue-1900.stderr diff --git a/tests/ui/issues/issue-1476.rs b/tests/ui/issues/issue-1476.rs deleted file mode 100644 index 138570a93c49..000000000000 --- a/tests/ui/issues/issue-1476.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("{}", x); //~ ERROR cannot find value `x` in this scope -} diff --git a/tests/ui/issues/issue-1476.stderr b/tests/ui/issues/issue-1476.stderr deleted file mode 100644 index e30dbfd205b8..000000000000 --- a/tests/ui/issues/issue-1476.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0425]: cannot find value `x` in this scope - --> $DIR/issue-1476.rs:2:20 - | -LL | println!("{}", x); - | ^ not found in this scope - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/issues/issue-1696.rs b/tests/ui/issues/issue-1696.rs deleted file mode 100644 index 08002ad3c58b..000000000000 --- a/tests/ui/issues/issue-1696.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ run-pass -use std::collections::HashMap; - -pub fn main() { - let mut m = HashMap::new(); - m.insert(b"foo".to_vec(), b"bar".to_vec()); - println!("{:?}", m); -} diff --git a/tests/ui/issues/issue-1962.fixed b/tests/ui/loops/issue-1962.fixed similarity index 100% rename from tests/ui/issues/issue-1962.fixed rename to tests/ui/loops/issue-1962.fixed diff --git a/tests/ui/issues/issue-1962.rs b/tests/ui/loops/issue-1962.rs similarity index 100% rename from tests/ui/issues/issue-1962.rs rename to tests/ui/loops/issue-1962.rs diff --git a/tests/ui/issues/issue-1962.stderr b/tests/ui/loops/issue-1962.stderr similarity index 100% rename from tests/ui/issues/issue-1962.stderr rename to tests/ui/loops/issue-1962.stderr diff --git a/tests/ui/issues/issue-1974.rs b/tests/ui/loops/issue-1974.rs similarity index 100% rename from tests/ui/issues/issue-1974.rs rename to tests/ui/loops/issue-1974.rs diff --git a/tests/ui/issues/issue-1362.rs b/tests/ui/mismatched_types/issue-1362.rs similarity index 100% rename from tests/ui/issues/issue-1362.rs rename to tests/ui/mismatched_types/issue-1362.rs diff --git a/tests/ui/issues/issue-1362.stderr b/tests/ui/mismatched_types/issue-1362.stderr similarity index 100% rename from tests/ui/issues/issue-1362.stderr rename to tests/ui/mismatched_types/issue-1362.stderr diff --git a/tests/ui/issues/issue-1448-2.rs b/tests/ui/mismatched_types/issue-1448-2.rs similarity index 100% rename from tests/ui/issues/issue-1448-2.rs rename to tests/ui/mismatched_types/issue-1448-2.rs diff --git a/tests/ui/issues/issue-1448-2.stderr b/tests/ui/mismatched_types/issue-1448-2.stderr similarity index 100% rename from tests/ui/issues/issue-1448-2.stderr rename to tests/ui/mismatched_types/issue-1448-2.stderr diff --git a/tests/ui/issues/issue-1660.rs b/tests/ui/static/issue-1660.rs similarity index 100% rename from tests/ui/issues/issue-1660.rs rename to tests/ui/static/issue-1660.rs From 8cf2c0dc67d880e54be03ebb08f7f960c21bb794 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 29 Mar 2024 19:40:54 +0100 Subject: [PATCH 19/51] Improve debugging experience --- compiler/rustc_pattern_analysis/src/constructor.rs | 1 - compiler/rustc_pattern_analysis/src/rustc.rs | 2 -- compiler/rustc_pattern_analysis/src/usefulness.rs | 14 ++++++++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 1c9a9ab0f720..49b2e510642a 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -974,7 +974,6 @@ impl ConstructorSet { /// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation /// and its invariants. - #[instrument(level = "debug", skip(self, ctors), ret)] pub fn split<'a>( &self, ctors: impl Iterator> + Clone, diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index b0f506c3651a..467f09e4c294 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -186,7 +186,6 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Returns the types of the fields for a given constructor. The result must have a length of /// `ctor.arity()`. - #[instrument(level = "trace", skip(self))] pub(crate) fn ctor_sub_tys<'a>( &'a self, ctor: &'a Constructor<'p, 'tcx>, @@ -283,7 +282,6 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Creates a set that represents all the constructors of `ty`. /// /// See [`crate::constructor`] for considerations of emptiness. - #[instrument(level = "debug", skip(self), ret)] pub fn ctors_for_ty( &self, ty: RevealedTy<'tcx>, diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index cdc03eaeb37c..1b5dd8478d64 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -871,12 +871,14 @@ impl PlaceInfo { where Cx: 'a, { + debug!(?self.ty); if self.private_uninhabited { // Skip the whole column return Ok((smallvec![Constructor::PrivateUninhabited], vec![])); } let ctors_for_ty = cx.ctors_for_ty(&self.ty)?; + debug!(?ctors_for_ty); // We treat match scrutinees of type `!` or `EmptyEnum` differently. let is_toplevel_exception = @@ -895,6 +897,7 @@ impl PlaceInfo { // Analyze the constructors present in this column. let mut split_set = ctors_for_ty.split(ctors); + debug!(?split_set); let all_missing = split_set.present.is_empty(); // Build the set of constructors we will specialize with. It must cover the whole type, so @@ -1254,7 +1257,7 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> { /// + true + [Second(true)] + /// + false + [_] + /// + _ + [_, _, tail @ ..] + -/// | ✓ | ? | // column validity +/// | ✓ | ? | // validity /// ``` impl<'p, Cx: PatCx> fmt::Debug for Matrix<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -1285,7 +1288,7 @@ impl<'p, Cx: PatCx> fmt::Debug for Matrix<'p, Cx> { write!(f, " {sep}")?; } if is_validity_row { - write!(f, " // column validity")?; + write!(f, " // validity")?; } write!(f, "\n")?; } @@ -1617,7 +1620,6 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( }; // Analyze the constructors present in this column. - debug!("ty: {:?}", place.ty); let ctors = matrix.heads().map(|p| p.ctor()); let (split_ctors, missing_ctors) = place.split_column_ctors(mcx.tycx, ctors)?; @@ -1669,7 +1671,10 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( for row in matrix.rows() { if row.useful { if let PatOrWild::Pat(pat) = row.head() { - mcx.useful_subpatterns.insert(pat.uid); + let newly_useful = mcx.useful_subpatterns.insert(pat.uid); + if newly_useful { + debug!("newly useful: {pat:?}"); + } } } } @@ -1768,6 +1773,7 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>( .map(|arm| { debug!(?arm); let usefulness = collect_pattern_usefulness(&cx.useful_subpatterns, arm.pat); + debug!(?usefulness); (arm, usefulness) }) .collect(); From db9b4eac480525d7af188a8360371d3cef84de98 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 31 Mar 2024 23:57:47 +0200 Subject: [PATCH 20/51] Add tests --- tests/ui/pattern/usefulness/unions.rs | 34 +++++++++++++++++++++++ tests/ui/pattern/usefulness/unions.stderr | 34 +++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/ui/pattern/usefulness/unions.rs create mode 100644 tests/ui/pattern/usefulness/unions.stderr diff --git a/tests/ui/pattern/usefulness/unions.rs b/tests/ui/pattern/usefulness/unions.rs new file mode 100644 index 000000000000..32fe9b4c04d1 --- /dev/null +++ b/tests/ui/pattern/usefulness/unions.rs @@ -0,0 +1,34 @@ +fn main() { + #[derive(Copy, Clone)] + union U8AsBool { + n: u8, + b: bool, + } + + let x = U8AsBool { n: 1 }; + unsafe { + match x { + // exhaustive + U8AsBool { n: 2 } => {} + U8AsBool { b: true } => {} + U8AsBool { b: false } => {} + } + match x { + // exhaustive + U8AsBool { b: true } => {} + U8AsBool { n: 0 } => {} + U8AsBool { n: 1.. } => {} + } + match x { + //~^ ERROR non-exhaustive patterns: `U8AsBool { n: 0_u8, b: false }` not covered + U8AsBool { b: true } => {} + U8AsBool { n: 1.. } => {} + } + match (x, true) { + //~^ ERROR non-exhaustive patterns: `(U8AsBool { n: 0_u8, b: false }, false)` and `(U8AsBool { n: 0_u8, b: true }, false)` not covered + (U8AsBool { b: true }, true) => {} + (U8AsBool { b: false }, true) => {} + (U8AsBool { n: 1.. }, true) => {} + } + } +} diff --git a/tests/ui/pattern/usefulness/unions.stderr b/tests/ui/pattern/usefulness/unions.stderr new file mode 100644 index 000000000000..d824a031cd3f --- /dev/null +++ b/tests/ui/pattern/usefulness/unions.stderr @@ -0,0 +1,34 @@ +error[E0004]: non-exhaustive patterns: `U8AsBool { n: 0_u8, b: false }` not covered + --> $DIR/unions.rs:22:15 + | +LL | match x { + | ^ pattern `U8AsBool { n: 0_u8, b: false }` not covered + | +note: `U8AsBool` defined here + --> $DIR/unions.rs:3:11 + | +LL | union U8AsBool { + | ^^^^^^^^ + = note: the matched value is of type `U8AsBool` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ U8AsBool { n: 1.. } => {}, +LL + U8AsBool { n: 0_u8, b: false } => todo!() + | + +error[E0004]: non-exhaustive patterns: `(U8AsBool { n: 0_u8, b: false }, false)` and `(U8AsBool { n: 0_u8, b: true }, false)` not covered + --> $DIR/unions.rs:27:15 + | +LL | match (x, true) { + | ^^^^^^^^^ patterns `(U8AsBool { n: 0_u8, b: false }, false)` and `(U8AsBool { n: 0_u8, b: true }, false)` not covered + | + = note: the matched value is of type `(U8AsBool, bool)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (U8AsBool { n: 1.. }, true) => {}, +LL + (U8AsBool { n: 0_u8, b: false }, false) | (U8AsBool { n: 0_u8, b: true }, false) => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. From 27704c7f9eea6e8ffaedac04ae1c932da7422fb7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 31 Mar 2024 23:57:53 +0200 Subject: [PATCH 21/51] Fix union handling in exhaustiveness --- compiler/rustc_middle/src/thir.rs | 3 +- .../rustc_pattern_analysis/src/constructor.rs | 28 +++++++++++++++ .../rustc_pattern_analysis/src/usefulness.rs | 35 +++++++++++++++---- tests/ui/pattern/usefulness/unions.rs | 5 +-- tests/ui/pattern/usefulness/unions.stderr | 32 ++++++++--------- 5 files changed, 78 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 05f6fbbbfa33..5a0cf524e261 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -1120,7 +1120,8 @@ impl<'tcx> fmt::Display for Pat<'tcx> { printed += 1; } - if printed < variant.fields.len() { + let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union()); + if printed < variant.fields.len() && (!is_union || printed == 0) { write!(f, "{}..", start_or_comma())?; } diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 49b2e510642a..44f09b66bf6c 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -140,6 +140,34 @@ //! [`ConstructorSet::split`]. The invariants of [`SplitConstructorSet`] are also of interest. //! //! +//! ## Unions +//! +//! Unions allow us to match a value via several overlapping representations at the same time. For +//! example, the following is exhaustive because when seeing the value as a boolean we handled all +//! possible cases (other cases such as `n == 3` would trigger UB). +//! +//! ```rust +//! # fn main() { +//! union U8AsBool { +//! n: u8, +//! b: bool, +//! } +//! let x = U8AsBool { n: 1 }; +//! unsafe { +//! match x { +//! U8AsBool { n: 2 } => {} +//! U8AsBool { b: true } => {} +//! U8AsBool { b: false } => {} +//! } +//! } +//! # } +//! ``` +//! +//! Pattern-matching has no knowledge that e.g. `false as u8 == 0`, so the values we consider in the +//! algorithm look like `U8AsBool { b: true, n: 2 }`. In other words, for the most part a union is +//! treated like a struct with the same fields. The difference lies in how we construct witnesses of +//! non-exhaustiveness. +//! //! //! ## Opaque patterns //! diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 1b5dd8478d64..7246039174af 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1384,12 +1384,35 @@ impl WitnessStack { /// pats: [(false, "foo"), _, true] /// result: [Enum::Variant { a: (false, "foo"), b: _ }, true] /// ``` - fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor) { + fn apply_constructor( + mut self, + pcx: &PlaceCtxt<'_, Cx>, + ctor: &Constructor, + ) -> SmallVec<[Self; 1]> { let len = self.0.len(); let arity = pcx.ctor_arity(ctor); - let fields = self.0.drain((len - arity)..).rev().collect(); - let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone()); - self.0.push(pat); + let fields: Vec<_> = self.0.drain((len - arity)..).rev().collect(); + if matches!(ctor, Constructor::UnionField) + && fields.iter().filter(|p| !matches!(p.ctor(), Constructor::Wildcard)).count() >= 2 + { + // Convert a `Union { a: p, b: q }` witness into `Union { a: p }` and `Union { b: q }`. + // First add `Union { .. }` to `self`. + self.0.push(WitnessPat::wild_from_ctor(pcx.cx, ctor.clone(), pcx.ty.clone())); + fields + .into_iter() + .enumerate() + .filter(|(_, p)| !matches!(p.ctor(), Constructor::Wildcard)) + .map(|(i, p)| { + let mut ret = self.clone(); + // Fill the `i`th field of the union with `p`. + ret.0.last_mut().unwrap().fields[i] = p; + ret + }) + .collect() + } else { + self.0.push(WitnessPat::new(ctor.clone(), fields, pcx.ty.clone())); + smallvec![self] + } } } @@ -1462,8 +1485,8 @@ impl WitnessMatrix { *self = ret; } else { // Any other constructor we unspecialize as expected. - for witness in self.0.iter_mut() { - witness.apply_constructor(pcx, ctor) + for witness in std::mem::take(&mut self.0) { + self.0.extend(witness.apply_constructor(pcx, ctor)); } } } diff --git a/tests/ui/pattern/usefulness/unions.rs b/tests/ui/pattern/usefulness/unions.rs index 32fe9b4c04d1..80a7f36a09a2 100644 --- a/tests/ui/pattern/usefulness/unions.rs +++ b/tests/ui/pattern/usefulness/unions.rs @@ -20,12 +20,13 @@ fn main() { U8AsBool { n: 1.. } => {} } match x { - //~^ ERROR non-exhaustive patterns: `U8AsBool { n: 0_u8, b: false }` not covered + //~^ ERROR non-exhaustive patterns: `U8AsBool { n: 0_u8 }` and `U8AsBool { b: false }` not covered U8AsBool { b: true } => {} U8AsBool { n: 1.. } => {} } + // Our approach can report duplicate witnesses sometimes. match (x, true) { - //~^ ERROR non-exhaustive patterns: `(U8AsBool { n: 0_u8, b: false }, false)` and `(U8AsBool { n: 0_u8, b: true }, false)` not covered + //~^ ERROR non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered (U8AsBool { b: true }, true) => {} (U8AsBool { b: false }, true) => {} (U8AsBool { n: 1.. }, true) => {} diff --git a/tests/ui/pattern/usefulness/unions.stderr b/tests/ui/pattern/usefulness/unions.stderr index d824a031cd3f..4b397dc25db8 100644 --- a/tests/ui/pattern/usefulness/unions.stderr +++ b/tests/ui/pattern/usefulness/unions.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `U8AsBool { n: 0_u8, b: false }` not covered +error[E0004]: non-exhaustive patterns: `U8AsBool { n: 0_u8 }` and `U8AsBool { b: false }` not covered --> $DIR/unions.rs:22:15 | LL | match x { - | ^ pattern `U8AsBool { n: 0_u8, b: false }` not covered + | ^ patterns `U8AsBool { n: 0_u8 }` and `U8AsBool { b: false }` not covered | note: `U8AsBool` defined here --> $DIR/unions.rs:3:11 @@ -10,23 +10,23 @@ note: `U8AsBool` defined here LL | union U8AsBool { | ^^^^^^^^ = note: the matched value is of type `U8AsBool` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ U8AsBool { n: 1.. } => {}, -LL + U8AsBool { n: 0_u8, b: false } => todo!() - | - -error[E0004]: non-exhaustive patterns: `(U8AsBool { n: 0_u8, b: false }, false)` and `(U8AsBool { n: 0_u8, b: true }, false)` not covered - --> $DIR/unions.rs:27:15 - | -LL | match (x, true) { - | ^^^^^^^^^ patterns `(U8AsBool { n: 0_u8, b: false }, false)` and `(U8AsBool { n: 0_u8, b: true }, false)` not covered - | - = note: the matched value is of type `(U8AsBool, bool)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | +LL ~ U8AsBool { n: 1.. } => {}, +LL + U8AsBool { n: 0_u8 } | U8AsBool { b: false } => todo!() + | + +error[E0004]: non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered + --> $DIR/unions.rs:28:15 + | +LL | match (x, true) { + | ^^^^^^^^^ patterns `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered + | + = note: the matched value is of type `(U8AsBool, bool)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | LL ~ (U8AsBool { n: 1.. }, true) => {}, -LL + (U8AsBool { n: 0_u8, b: false }, false) | (U8AsBool { n: 0_u8, b: true }, false) => todo!() +LL + _ => todo!() | error: aborting due to 2 previous errors From 5a887942a5e50f20569be6569ba62d48a0cc6b53 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 2 Apr 2024 00:06:04 +0200 Subject: [PATCH 22/51] x.py test: remove no-op --skip flag --- src/bootstrap/src/core/builder/tests.rs | 2 -- src/bootstrap/src/core/config/flags.rs | 3 --- src/etc/completions/x.py.fish | 2 +- src/etc/completions/x.py.ps1 | 2 +- src/etc/completions/x.py.sh | 10 +++++----- src/etc/completions/x.py.zsh | 2 +- 6 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 0f9776405596..178df633cec6 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -599,7 +599,6 @@ mod dist { pass: None, run: None, only_modified: false, - skip: vec![], extra_checks: None, }; @@ -664,7 +663,6 @@ mod dist { no_fail_fast: false, doc: true, no_doc: false, - skip: vec![], bless: false, force_rerun: false, compare_mode: None, diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 7262b785ee00..a66f743a1c51 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -339,9 +339,6 @@ pub enum Subcommand { #[arg(long)] /// run all tests regardless of failure no_fail_fast: bool, - #[arg(long, value_name = "SUBSTRING")] - /// skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times - skip: Vec, #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] /// extra arguments to be passed for the test tool being used /// (e.g. libtest, compiletest or rustdoc) diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 9fc95fd09ba9..c95516494ae7 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -261,7 +261,6 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-generate - complete -c x.py -n "__fish_seen_subcommand_from doc" -l enable-bolt-settings -d 'Enable BOLT link flags' complete -c x.py -n "__fish_seen_subcommand_from doc" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c x.py -n "__fish_seen_subcommand_from test" -l skip -d 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times' -r -F complete -c x.py -n "__fish_seen_subcommand_from test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-args -d 'extra options to pass the compiler when running tests' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)' -r @@ -274,6 +273,7 @@ complete -c x.py -n "__fish_seen_subcommand_from test" -l build -d 'build target complete -c x.py -n "__fish_seen_subcommand_from test" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_seen_subcommand_from test" -l target -d 'target targets to build' -r -f complete -c x.py -n "__fish_seen_subcommand_from test" -l exclude -d 'build paths to exclude' -r -F +complete -c x.py -n "__fish_seen_subcommand_from test" -l skip -d 'build paths to skip' -r -F complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-error-format -r -f complete -c x.py -n "__fish_seen_subcommand_from test" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)" complete -c x.py -n "__fish_seen_subcommand_from test" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index 6359b7ff086a..8e505afaf759 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -333,7 +333,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { break } 'x.py;test' { - [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times') [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests') [CompletionResult]::new('--extra-checks', 'extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)') @@ -346,6 +345,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build') [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude') + [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format') [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure') [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index e1436dcde670..742f61f16221 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -1625,16 +1625,12 @@ _x.py() { return 0 ;; x.py__test) - opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in - --skip) - COMPREPLY=($(compgen -f "${cur}")) - return 0 - ;; --test-args) COMPREPLY=($(compgen -f "${cur}")) return 0 @@ -1683,6 +1679,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index ea7e4ba6758f..eec610629a14 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -335,7 +335,6 @@ _arguments "${_arguments_options[@]}" \ ;; (test) _arguments "${_arguments_options[@]}" \ -'*--skip=[skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times]:SUBSTRING:_files' \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \ '*--rustc-args=[extra options to pass the compiler when running tests]:ARGS: ' \ '--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell)]:EXTRA_CHECKS: ' \ @@ -348,6 +347,7 @@ _arguments "${_arguments_options[@]}" \ '--host=[host targets to build]:HOST:( )' \ '--target=[target targets to build]:TARGET:( )' \ '*--exclude=[build paths to exclude]:PATH:_files' \ +'*--skip=[build paths to skip]:PATH:_files' \ '--rustc-error-format=[]:RUSTC_ERROR_FORMAT:( )' \ '--on-fail=[command to run on failure]:CMD:_cmdstring' \ '--stage=[stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)]:N:( )' \ From 1f2d1420cb1c5c5cb52712955f8ed47dcfda8c67 Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Tue, 2 Apr 2024 17:17:13 +0800 Subject: [PATCH 23/51] Fix linking c++ runtimes on AIX --- compiler/rustc_llvm/build.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 4b0c1229da13..66fa4bde785e 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -391,6 +391,11 @@ fn main() { } } + // libc++abi have to be specified explicitly on AIX. + if target.contains("aix") { + println!("cargo:rustc-link-lib=c++abi"); + } + // Libstdc++ depends on pthread which Rust doesn't link on MinGW // since nothing else requires it. if target.ends_with("windows-gnu") { From 00f7f57159aac2e1df49db2eb87353338bef2bb0 Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Tue, 2 Apr 2024 17:25:22 +0800 Subject: [PATCH 24/51] Fix build on AIX --- compiler/rustc_llvm/build.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 66fa4bde785e..e2c0ec90c7cd 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -391,9 +391,10 @@ fn main() { } } - // libc++abi have to be specified explicitly on AIX. + // libc++abi and libunwind have to be specified explicitly on AIX. if target.contains("aix") { println!("cargo:rustc-link-lib=c++abi"); + println!("cargo:rustc-link-lib=unwind"); } // Libstdc++ depends on pthread which Rust doesn't link on MinGW From b4e2d75d3598a4f9e89d918255e84053c68a4583 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 14:12:40 -0400 Subject: [PATCH 25/51] Assert FnDef only constructed with functions (or fn-like ctors) --- compiler/rustc_middle/src/ty/sty.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b5e619f1e2a3..ba0898e07c29 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -11,7 +11,7 @@ use crate::ty::{ }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use crate::ty::{List, ParamEnv}; -use hir::def::DefKind; +use hir::def::{CtorKind, DefKind}; use rustc_data_structures::captures::Captures; use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagArg, MultiSpan}; use rustc_hir as hir; @@ -1677,6 +1677,10 @@ impl<'tcx> Ty<'tcx> { def_id: DefId, args: impl IntoIterator>>, ) -> Ty<'tcx> { + debug_assert_matches!( + tcx.def_kind(def_id), + DefKind::AssocFn | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) + ); let args = tcx.check_and_mk_args(def_id, args); Ty::new(tcx, FnDef(def_id, args)) } From cc5105d246c77d54cabb4f595d4e87c14358073d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 14:13:25 -0400 Subject: [PATCH 26/51] Don't create an FnDef of a DefKind::Variant, use the ctor def id --- compiler/rustc_hir_analysis/src/collect/type_of.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 722def2563cb..9d7deebac48e 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -474,9 +474,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder { tcx.type_of(tcx.hir().get_parent_item(hir_id)).instantiate_identity() } - VariantData::Tuple(..) => { + VariantData::Tuple(_, _, ctor) => { let args = ty::GenericArgs::identity_for_item(tcx, def_id); - Ty::new_fn_def(tcx, def_id.to_def_id(), args) + Ty::new_fn_def(tcx, ctor.to_def_id(), args) } }, From a6b2d12c921552082d6849c75531da666a9c9c82 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 2 Apr 2024 21:41:16 +0200 Subject: [PATCH 27/51] use a consistent style for links --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 9017ba797146..b1102b440e02 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -37,7 +37,7 @@ use crate::time::SystemTime; /// /// # Examples /// -/// Creates a new file and write bytes to it (you can also use [`write()`]): +/// Creates a new file and write bytes to it (you can also use [`write`]): /// /// ```no_run /// use std::fs::File; @@ -2018,7 +2018,7 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// the length of the `to` file as reported by `metadata`. /// /// If you want to copy the contents of one file to another and you’re -/// working with [`File`]s, see the [`io::copy()`] function. +/// working with [`File`]s, see the [`io::copy`](io::copy()) function. /// /// # Platform-specific behavior /// From 049a91753594422b6c672bf5a46e04076fc45d9e Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 2 Apr 2024 16:19:55 -0400 Subject: [PATCH 28/51] Put basic impls for f16 and f128 behind cfg(not(bootstrap)) We will lose `f16` and `f128` in the beta compiler after the revert for lands. Change what was added in to be behind `#[cfg(not(bootstrap))]` to account for this. --- library/core/src/clone.rs | 5 ++++- library/core/src/cmp.rs | 10 ++++++++-- library/core/src/lib.rs | 4 ++-- library/core/src/marker.rs | 8 +++++++- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index d448c5338fc4..44ae72bcd26b 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -227,10 +227,13 @@ mod impls { impl_clone! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 - f16 f32 f64 f128 + f32 f64 bool char } + #[cfg(not(bootstrap))] + impl_clone! { f16 f128 } + #[unstable(feature = "never_type", issue = "35121")] impl Clone for ! { #[inline] diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index b0c5021022f7..e2ca66900586 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1493,9 +1493,12 @@ mod impls { } partial_eq_impl! { - bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 + bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + #[cfg(not(bootstrap))] + partial_eq_impl! { f16 f128 } + macro_rules! eq_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] @@ -1546,7 +1549,10 @@ mod impls { } } - partial_ord_impl! { f16 f32 f64 f128 } + partial_ord_impl! { f32 f64 } + + #[cfg(not(bootstrap))] + partial_ord_impl! { f16 f128 } macro_rules! ord_impl { ($($t:ty)*) => ($( diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0cc3ad1ead7f..ba19ca1f45d7 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -205,6 +205,8 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(not(bootstrap), feature(f128))] +#![cfg_attr(not(bootstrap), feature(f16))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -229,8 +231,6 @@ #![feature(doc_notable_trait)] #![feature(effects)] #![feature(extern_types)] -#![feature(f128)] -#![feature(f16)] #![feature(freeze_impls)] #![feature(fundamental)] #![feature(generic_arg_infer)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 1d073a6d649b..fb97b3bfa092 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -422,11 +422,17 @@ marker_impls! { Copy for usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, - f16, f32, f64, f128, + f32, f64, bool, char, {T: ?Sized} *const T, {T: ?Sized} *mut T, +} +#[cfg(not(bootstrap))] +marker_impls! { + #[stable(feature = "rust1", since = "1.0.0")] + Copy for + f16, f128, } #[unstable(feature = "never_type", issue = "35121")] From 9d116e8e188a84d97e1b64f54410fda7ec6f2dc6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 18:31:42 -0400 Subject: [PATCH 29/51] Don't ICE for postfix match after as --- compiler/rustc_parse/src/parser/expr.rs | 1 + .../ui/match/postfix-match/match-after-as.rs | 7 +++++ .../match/postfix-match/match-after-as.stderr | 28 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 tests/ui/match/postfix-match/match-after-as.rs create mode 100644 tests/ui/match/postfix-match/match-after-as.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 18fb858c84cf..012285e4644d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -860,6 +860,7 @@ impl<'a> Parser<'a> { ExprKind::MethodCall(_) => "a method call", ExprKind::Call(_, _) => "a function call", ExprKind::Await(_, _) => "`.await`", + ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match", ExprKind::Err(_) => return Ok(with_postfix), _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"), } diff --git a/tests/ui/match/postfix-match/match-after-as.rs b/tests/ui/match/postfix-match/match-after-as.rs new file mode 100644 index 000000000000..7c648bfcf035 --- /dev/null +++ b/tests/ui/match/postfix-match/match-after-as.rs @@ -0,0 +1,7 @@ +#![feature(postfix_match)] + +fn main() { + 1 as i32.match {}; + //~^ ERROR cast cannot be followed by a postfix match + //~| ERROR non-exhaustive patterns +} diff --git a/tests/ui/match/postfix-match/match-after-as.stderr b/tests/ui/match/postfix-match/match-after-as.stderr new file mode 100644 index 000000000000..99e42991c52b --- /dev/null +++ b/tests/ui/match/postfix-match/match-after-as.stderr @@ -0,0 +1,28 @@ +error: cast cannot be followed by a postfix match + --> $DIR/match-after-as.rs:4:5 + | +LL | 1 as i32.match {}; + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (1 as i32).match {}; + | + + + +error[E0004]: non-exhaustive patterns: type `i32` is non-empty + --> $DIR/match-after-as.rs:4:5 + | +LL | 1 as i32.match {}; + | ^^^^^^^^ + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ 1 as i32 { +LL + _ => todo!(), +LL ~ }; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. From bed8b70d674de72e0e66ab022a64c33f0b1df15e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 19:06:28 -0400 Subject: [PATCH 30/51] Fix suggestions for match non-exhaustiveness --- compiler/rustc_middle/src/thir.rs | 3 +- compiler/rustc_mir_build/src/errors.rs | 23 +++----- compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 +- .../src/thir/pattern/check_match.rs | 57 +++++++++++++------ .../match/postfix-match/match-after-as.stderr | 2 +- 5 files changed, 54 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 05f6fbbbfa33..95e8509c2d3d 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -12,7 +12,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::{BindingAnnotation, ByRef, RangeEnd}; +use rustc_hir::{BindingAnnotation, ByRef, MatchSource, RangeEnd}; use rustc_index::newtype_index; use rustc_index::IndexVec; use rustc_middle::middle::region; @@ -358,6 +358,7 @@ pub enum ExprKind<'tcx> { scrutinee: ExprId, scrutinee_hir_id: hir::HirId, arms: Box<[ArmId]>, + match_source: MatchSource, }, /// A block. Block { diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 848da56f9816..26f10fdd333c 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -456,8 +456,8 @@ pub enum UnusedUnsafeEnclosing { pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { pub cx: &'m RustcPatCtxt<'p, 'tcx>, - pub expr_span: Span, - pub span: Span, + pub scrut_span: Span, + pub braces_span: Option, pub ty: Ty<'tcx>, } @@ -465,7 +465,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'_, G> { let mut diag = Diag::new(dcx, level, fluent::mir_build_non_exhaustive_patterns_type_not_empty); - diag.span(self.span); + diag.span(self.scrut_span); diag.code(E0004); let peeled_ty = self.ty.peel_refs(); diag.arg("ty", self.ty); @@ -502,26 +502,19 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo } } - let mut suggestion = None; let sm = self.cx.tcx.sess.source_map(); - if self.span.eq_ctxt(self.expr_span) { + if let Some(braces_span) = self.braces_span { // Get the span for the empty match body `{}`. - let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.span) { + let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.scrut_span) + { (format!("\n{snippet}"), " ") } else { (" ".to_string(), "") }; - suggestion = Some(( - self.span.shrink_to_hi().with_hi(self.expr_span.hi()), - format!(" {{{indentation}{more}_ => todo!(),{indentation}}}",), - )); - } - - if let Some((span, sugg)) = suggestion { diag.span_suggestion_verbose( - span, + braces_span, fluent::mir_build_suggestion, - sugg, + format!(" {{{indentation}{more}_ => todo!(),{indentation}}}"), Applicability::HasPlaceholders, ); } else { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 1e508ffc1e75..c697e16217bd 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -716,10 +716,11 @@ impl<'tcx> Cx<'tcx> { then: self.mirror_expr(then), else_opt: else_opt.map(|el| self.mirror_expr(el)), }, - hir::ExprKind::Match(discr, arms, _) => ExprKind::Match { + hir::ExprKind::Match(discr, arms, match_source) => ExprKind::Match { scrutinee: self.mirror_expr(discr), scrutinee_hir_id: discr.hir_id, arms: arms.iter().map(|a| self.convert_arm(a)).collect(), + match_source, }, hir::ExprKind::Loop(body, ..) => { let block_ty = self.typeck_results().node_type(body.hir_id); diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 3a688a14dd50..a3e6c2abc51f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -144,16 +144,8 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { }); return; } - ExprKind::Match { scrutinee, scrutinee_hir_id, box ref arms } => { - let source = match ex.span.desugaring_kind() { - Some(DesugaringKind::ForLoop) => hir::MatchSource::ForLoopDesugar, - Some(DesugaringKind::QuestionMark) => { - hir::MatchSource::TryDesugar(scrutinee_hir_id) - } - Some(DesugaringKind::Await) => hir::MatchSource::AwaitDesugar, - _ => hir::MatchSource::Normal, - }; - self.check_match(scrutinee, arms, source, ex.span); + ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => { + self.check_match(scrutinee, arms, match_source, ex.span); } ExprKind::Let { box ref pat, expr } => { self.check_let(pat, Some(expr), ex.span); @@ -505,8 +497,41 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { None, ); } else { + // span after scrutinee, or after `.match`. That is, the braces, arms, + // and any whitespace preceding the braces. + let braces_span = match source { + hir::MatchSource::Normal => scrut + .span + .find_ancestor_in_same_ctxt(expr_span) + .map(|scrut_span| scrut_span.shrink_to_hi().with_hi(expr_span.hi())), + hir::MatchSource::Postfix => { + // This is horrendous, and we should deal with it by just + // stashing the span of the braces somewhere (like in the match source). + scrut.span.find_ancestor_in_same_ctxt(expr_span).and_then(|scrut_span| { + let sm = self.tcx.sess.source_map(); + let brace_span = sm.span_extend_to_next_char(scrut_span, '{', true); + if sm.span_to_snippet(sm.next_point(brace_span)).as_deref() == Ok("{") { + let sp = brace_span.shrink_to_hi().with_hi(expr_span.hi()); + // We also need to extend backwards for whitespace + sm.span_extend_prev_while(sp, |c| c.is_whitespace()).ok() + } else { + None + } + }) + } + hir::MatchSource::ForLoopDesugar + | hir::MatchSource::TryDesugar(_) + | hir::MatchSource::AwaitDesugar + | hir::MatchSource::FormatArgs => None, + }; self.error = Err(report_non_exhaustive_match( - &cx, self.thir, scrut.ty, scrut.span, witnesses, arms, expr_span, + &cx, + self.thir, + scrut.ty, + scrut.span, + witnesses, + arms, + braces_span, )); } } @@ -929,7 +954,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( sp: Span, witnesses: Vec>, arms: &[ArmId], - expr_span: Span, + braces_span: Option, ) -> ErrorGuaranteed { let is_empty_match = arms.is_empty(); let non_empty_enum = match scrut_ty.kind() { @@ -941,8 +966,8 @@ fn report_non_exhaustive_match<'p, 'tcx>( if is_empty_match && !non_empty_enum { return cx.tcx.dcx().emit_err(NonExhaustivePatternsTypeNotEmpty { cx, - expr_span, - span: sp, + scrut_span: sp, + braces_span, ty: scrut_ty, }); } @@ -1028,7 +1053,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( let mut suggestion = None; let sm = cx.tcx.sess.source_map(); match arms { - [] if sp.eq_ctxt(expr_span) => { + [] if let Some(braces_span) = braces_span => { // Get the span for the empty match body `{}`. let (indentation, more) = if let Some(snippet) = sm.indentation_before(sp) { (format!("\n{snippet}"), " ") @@ -1036,7 +1061,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( (" ".to_string(), "") }; suggestion = Some(( - sp.shrink_to_hi().with_hi(expr_span.hi()), + braces_span, format!(" {{{indentation}{more}{suggested_arm},{indentation}}}",), )); } diff --git a/tests/ui/match/postfix-match/match-after-as.stderr b/tests/ui/match/postfix-match/match-after-as.stderr index 99e42991c52b..68e4762b8d91 100644 --- a/tests/ui/match/postfix-match/match-after-as.stderr +++ b/tests/ui/match/postfix-match/match-after-as.stderr @@ -18,7 +18,7 @@ LL | 1 as i32.match {}; = note: the matched value is of type `i32` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | -LL ~ 1 as i32 { +LL ~ 1 as i32.match { LL + _ => todo!(), LL ~ }; | From ab821aed0c048964a86285d534ca93203d61af89 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 19:30:32 -0400 Subject: [PATCH 31/51] Fix precedence of postfix match --- compiler/rustc_ast/src/ast.rs | 3 ++- compiler/rustc_ast/src/util/parser.rs | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index aba94f4d817d..ccbcd5091b47 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1276,7 +1276,8 @@ impl Expr { ExprKind::While(..) => ExprPrecedence::While, ExprKind::ForLoop { .. } => ExprPrecedence::ForLoop, ExprKind::Loop(..) => ExprPrecedence::Loop, - ExprKind::Match(..) => ExprPrecedence::Match, + ExprKind::Match(_, _, MatchKind::Prefix) => ExprPrecedence::Match, + ExprKind::Match(_, _, MatchKind::Postfix) => ExprPrecedence::PostfixMatch, ExprKind::Closure(..) => ExprPrecedence::Closure, ExprKind::Block(..) => ExprPrecedence::Block, ExprKind::TryBlock(..) => ExprPrecedence::TryBlock, diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 13768c120179..544db992f4f2 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -281,6 +281,7 @@ pub enum ExprPrecedence { ForLoop, Loop, Match, + PostfixMatch, ConstBlock, Block, TryBlock, @@ -334,7 +335,8 @@ impl ExprPrecedence { | ExprPrecedence::InlineAsm | ExprPrecedence::Mac | ExprPrecedence::FormatArgs - | ExprPrecedence::OffsetOf => PREC_POSTFIX, + | ExprPrecedence::OffsetOf + | ExprPrecedence::PostfixMatch => PREC_POSTFIX, // Never need parens ExprPrecedence::Array From 4cb5643bd4b9a66f8c8b8fee2505a7f09b8ed10a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 19:40:12 -0400 Subject: [PATCH 32/51] Fix contains_exterior_struct_lit --- compiler/rustc_ast/src/util/parser.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 544db992f4f2..373c0ebcc5cb 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -392,7 +392,8 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { | ast::ExprKind::Cast(x, _) | ast::ExprKind::Type(x, _) | ast::ExprKind::Field(x, _) - | ast::ExprKind::Index(x, _, _) => { + | ast::ExprKind::Index(x, _, _) + | ast::ExprKind::Match(x, _, ast::MatchKind::Postfix) => { // &X { y: 1 }, X { y: 1 }.y contains_exterior_struct_lit(x) } From a1a1f41027c16a940c1de9e445064692110637c8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 1 Apr 2024 14:42:00 -0400 Subject: [PATCH 33/51] Fix capture analysis for by-move closure bodies --- .../src/coroutine/by_move_body.rs | 68 ++++++++++---- .../miri/tests/pass/async-closure-captures.rs | 89 +++++++++++++++++++ .../tests/pass/async-closure-captures.stdout | 10 +++ .../ui/async-await/async-closures/captures.rs | 80 +++++++++++++++++ .../async-closures/captures.run.stdout | 10 +++ 5 files changed, 240 insertions(+), 17 deletions(-) create mode 100644 src/tools/miri/tests/pass/async-closure-captures.rs create mode 100644 src/tools/miri/tests/pass/async-closure-captures.stdout create mode 100644 tests/ui/async-await/async-closures/captures.rs create mode 100644 tests/ui/async-await/async-closures/captures.run.stdout diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 99dbb3422683..60b52fba2193 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -3,6 +3,8 @@ //! be a coroutine body that takes all of its upvars by-move, and which we stash //! into the `CoroutineInfo` for all coroutines returned by coroutine-closures. +use itertools::Itertools; + use rustc_data_structures::unord::UnordSet; use rustc_hir as hir; use rustc_middle::mir::visit::MutVisitor; @@ -26,36 +28,68 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { if coroutine_ty.references_error() { return; } - let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; - let coroutine_kind = args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(); + let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; + let args = args.as_coroutine(); + + let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap(); if coroutine_kind == ty::ClosureKind::FnOnce { return; } - let mut by_ref_fields = UnordSet::default(); - let by_move_upvars = Ty::new_tup_from_iter( - tcx, - tcx.closure_captures(coroutine_def_id).iter().enumerate().map(|(idx, capture)| { - if capture.is_by_ref() { - by_ref_fields.insert(FieldIdx::from_usize(idx)); - } - capture.place.ty() - }), + let parent_def_id = tcx.local_parent(coroutine_def_id); + let ty::CoroutineClosure(_, parent_args) = + *tcx.type_of(parent_def_id).instantiate_identity().kind() + else { + bug!(); + }; + let parent_args = parent_args.as_coroutine_closure(); + let parent_upvars_ty = parent_args.tupled_upvars_ty(); + let tupled_inputs_ty = tcx.instantiate_bound_regions_with_erased( + parent_args.coroutine_closure_sig().map_bound(|sig| sig.tupled_inputs_ty), ); + let num_args = tupled_inputs_ty.tuple_fields().len(); + + let mut by_ref_fields = UnordSet::default(); + for (idx, (coroutine_capture, parent_capture)) in tcx + .closure_captures(coroutine_def_id) + .iter() + // By construction we capture all the args first. + .skip(num_args) + .zip_eq(tcx.closure_captures(parent_def_id)) + .enumerate() + { + // This argument is captured by-move from the parent closure, but by-ref + // from the inner async block. That means that it's being borrowed from + // the closure body -- we need to change the coroutine take it by move. + if coroutine_capture.is_by_ref() && !parent_capture.is_by_ref() { + by_ref_fields.insert(FieldIdx::from_usize(num_args + idx)); + } + + // Make sure we're actually talking about the same capture. + assert_eq!(coroutine_capture.place.ty(), parent_capture.place.ty()); + } + let by_move_coroutine_ty = Ty::new_coroutine( tcx, coroutine_def_id.to_def_id(), ty::CoroutineArgs::new( tcx, ty::CoroutineArgsParts { - parent_args: args.as_coroutine().parent_args(), + parent_args: args.parent_args(), kind_ty: Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce), - resume_ty: args.as_coroutine().resume_ty(), - yield_ty: args.as_coroutine().yield_ty(), - return_ty: args.as_coroutine().return_ty(), - witness: args.as_coroutine().witness(), - tupled_upvars_ty: by_move_upvars, + resume_ty: args.resume_ty(), + yield_ty: args.yield_ty(), + return_ty: args.return_ty(), + witness: args.witness(), + // Concatenate the args + closure's captures (since they're all by move). + tupled_upvars_ty: Ty::new_tup_from_iter( + tcx, + tupled_inputs_ty + .tuple_fields() + .iter() + .chain(parent_upvars_ty.tuple_fields()), + ), }, ) .args, diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs new file mode 100644 index 000000000000..acff4a38338f --- /dev/null +++ b/src/tools/miri/tests/pass/async-closure-captures.rs @@ -0,0 +1,89 @@ +#![feature(async_closure, noop_waker)] + +use std::future::Future; +use std::pin::pin; +use std::task::*; + +pub fn block_on(fut: impl Future) -> T { + let mut fut = pin!(fut); + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match fut.as_mut().poll(ctx) { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} + +fn main() { + block_on(async_main()); +} + +async fn call(f: &impl async Fn() -> T) -> T { + f().await +} + +async fn call_once(f: impl async FnOnce() -> T) -> T { + f().await +} + +#[derive(Debug)] +#[allow(unused)] +struct Hello(i32); + +async fn async_main() { + // Capture something by-ref + { + let x = Hello(0); + let c = async || { + println!("{x:?}"); + }; + call(&c).await; + call_once(c).await; + + let x = &Hello(1); + let c = async || { + println!("{x:?}"); + }; + call(&c).await; + call_once(c).await; + } + + // Capture something and consume it (force to `AsyncFnOnce`) + { + let x = Hello(2); + let c = async || { + println!("{x:?}"); + drop(x); + }; + call_once(c).await; + } + + // Capture something with `move`, don't consume it + { + let x = Hello(3); + let c = async move || { + println!("{x:?}"); + }; + call(&c).await; + call_once(c).await; + + let x = &Hello(4); + let c = async move || { + println!("{x:?}"); + }; + call(&c).await; + call_once(c).await; + } + + // Capture something with `move`, also consume it (so `AsyncFnOnce`) + { + let x = Hello(5); + let c = async move || { + println!("{x:?}"); + drop(x); + }; + call_once(c).await; + } +} diff --git a/src/tools/miri/tests/pass/async-closure-captures.stdout b/src/tools/miri/tests/pass/async-closure-captures.stdout new file mode 100644 index 000000000000..a0db6d236fef --- /dev/null +++ b/src/tools/miri/tests/pass/async-closure-captures.stdout @@ -0,0 +1,10 @@ +Hello(0) +Hello(0) +Hello(1) +Hello(1) +Hello(2) +Hello(3) +Hello(3) +Hello(4) +Hello(4) +Hello(5) diff --git a/tests/ui/async-await/async-closures/captures.rs b/tests/ui/async-await/async-closures/captures.rs new file mode 100644 index 000000000000..46bbf53f0a7d --- /dev/null +++ b/tests/ui/async-await/async-closures/captures.rs @@ -0,0 +1,80 @@ +//@ aux-build:block-on.rs +//@ edition:2021 +//@ run-pass +//@ check-run-results + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async_main()); +} + +async fn call(f: &impl async Fn() -> T) -> T { + f().await +} + +async fn call_once(f: impl async FnOnce() -> T) -> T { + f().await +} + +#[derive(Debug)] +#[allow(unused)] +struct Hello(i32); + +async fn async_main() { + // Capture something by-ref + { + let x = Hello(0); + let c = async || { + println!("{x:?}"); + }; + call(&c).await; + call_once(c).await; + + let x = &Hello(1); + let c = async || { + println!("{x:?}"); + }; + call(&c).await; + call_once(c).await; + } + + // Capture something and consume it (force to `AsyncFnOnce`) + { + let x = Hello(2); + let c = async || { + println!("{x:?}"); + drop(x); + }; + call_once(c).await; + } + + // Capture something with `move`, don't consume it + { + let x = Hello(3); + let c = async move || { + println!("{x:?}"); + }; + call(&c).await; + call_once(c).await; + + let x = &Hello(4); + let c = async move || { + println!("{x:?}"); + }; + call(&c).await; + call_once(c).await; + } + + // Capture something with `move`, also consume it (so `AsyncFnOnce`) + { + let x = Hello(5); + let c = async move || { + println!("{x:?}"); + drop(x); + }; + call_once(c).await; + } +} diff --git a/tests/ui/async-await/async-closures/captures.run.stdout b/tests/ui/async-await/async-closures/captures.run.stdout new file mode 100644 index 000000000000..a0db6d236fef --- /dev/null +++ b/tests/ui/async-await/async-closures/captures.run.stdout @@ -0,0 +1,10 @@ +Hello(0) +Hello(0) +Hello(1) +Hello(1) +Hello(2) +Hello(3) +Hello(3) +Hello(4) +Hello(4) +Hello(5) From ec74a304bb737f24d6e7f2fb8c3a2b3cf3575f0f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 2 Apr 2024 11:26:57 -0400 Subject: [PATCH 34/51] Comments, comments, comments --- .../src/coroutine/by_move_body.rs | 131 ++++++++++++------ .../miri/tests/pass/async-closure-captures.rs | 2 + .../ui/async-await/async-closures/captures.rs | 2 + 3 files changed, 96 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 60b52fba2193..0866205dfd0d 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -1,7 +1,64 @@ -//! A MIR pass which duplicates a coroutine's body and removes any derefs which -//! would be present for upvars that are taken by-ref. The result of which will -//! be a coroutine body that takes all of its upvars by-move, and which we stash -//! into the `CoroutineInfo` for all coroutines returned by coroutine-closures. +//! This pass constructs a second coroutine body sufficient for return from +//! `FnOnce`/`AsyncFnOnce` implementations for coroutine-closures (e.g. async closures). +//! +//! Consider an async closure like: +//! ```rust +//! #![feature(async_closure)] +//! +//! let x = vec![1, 2, 3]; +//! +//! let closure = async move || { +//! println!("{x:#?}"); +//! }; +//! ``` +//! +//! This desugars to something like: +//! ```rust,ignore (invalid-borrowck) +//! let x = vec![1, 2, 3]; +//! +//! let closure = move || { +//! async { +//! println!("{x:#?}"); +//! } +//! }; +//! ``` +//! +//! Important to note here is that while the outer closure *moves* `x: Vec` +//! into its upvars, the inner `async` coroutine simply captures a ref of `x`. +//! This is the "magic" of async closures -- the futures that they return are +//! allowed to borrow from their parent closure's upvars. +//! +//! However, what happens when we call `closure` with `AsyncFnOnce` (or `FnOnce`, +//! since all async closures implement that too)? Well, recall the signature: +//! ``` +//! use std::future::Future; +//! pub trait AsyncFnOnce +//! { +//! type CallOnceFuture: Future; +//! type Output; +//! fn async_call_once( +//! self, +//! args: Args +//! ) -> Self::CallOnceFuture; +//! } +//! ``` +//! +//! This signature *consumes* the async closure (`self`) and returns a `CallOnceFuture`. +//! How do we deal with the fact that the coroutine is supposed to take a reference +//! to the captured `x` from the parent closure, when that parent closure has been +//! destroyed? +//! +//! This is the second piece of magic of async closures. We can simply create a +//! *second* `async` coroutine body where that `x` that was previously captured +//! by reference is now captured by value. This means that we consume the outer +//! closure and return a new coroutine that will hold onto all of these captures, +//! and drop them when it is finished (i.e. after it has been `.await`ed). +//! +//! We do this with the analysis below, which detects the captures that come from +//! borrowing from the outer closure, and we simply peel off a `deref` projection +//! from them. This second body is stored alongside the first body, and optimized +//! with it in lockstep. When we need to resolve a body for `FnOnce` or `AsyncFnOnce`, +//! we use this "by move" body instead. use itertools::Itertools; @@ -16,6 +73,8 @@ pub struct ByMoveBody; impl<'tcx> MirPass<'tcx> for ByMoveBody { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { + // We only need to generate by-move coroutine bodies for coroutines that come + // from coroutine-closures. let Some(coroutine_def_id) = body.source.def_id().as_local() else { return; }; @@ -24,15 +83,19 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { else { return; }; + + // Also, let's skip processing any bodies with errors, since there's no guarantee + // the MIR body will be constructed well. let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; if coroutine_ty.references_error() { return; } - let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; - let args = args.as_coroutine(); - - let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap(); + let ty::Coroutine(_, coroutine_args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; + // We don't need to generate a by-move coroutine if the kind of the coroutine is + // already `FnOnce` -- that means that any upvars that the closure consumes have + // already been taken by-value. + let coroutine_kind = coroutine_args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(); if coroutine_kind == ty::ClosureKind::FnOnce { return; } @@ -43,12 +106,13 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { else { bug!(); }; - let parent_args = parent_args.as_coroutine_closure(); - let parent_upvars_ty = parent_args.tupled_upvars_ty(); - let tupled_inputs_ty = tcx.instantiate_bound_regions_with_erased( - parent_args.coroutine_closure_sig().map_bound(|sig| sig.tupled_inputs_ty), - ); - let num_args = tupled_inputs_ty.tuple_fields().len(); + let parent_closure_args = parent_args.as_coroutine_closure(); + let num_args = parent_closure_args + .coroutine_closure_sig() + .skip_binder() + .tupled_inputs_ty + .tuple_fields() + .len(); let mut by_ref_fields = UnordSet::default(); for (idx, (coroutine_capture, parent_capture)) in tcx @@ -59,41 +123,30 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { .zip_eq(tcx.closure_captures(parent_def_id)) .enumerate() { - // This argument is captured by-move from the parent closure, but by-ref + // This upvar is captured by-move from the parent closure, but by-ref // from the inner async block. That means that it's being borrowed from - // the closure body -- we need to change the coroutine take it by move. + // the outer closure body -- we need to change the coroutine to take the + // upvar by value. if coroutine_capture.is_by_ref() && !parent_capture.is_by_ref() { by_ref_fields.insert(FieldIdx::from_usize(num_args + idx)); } // Make sure we're actually talking about the same capture. + // FIXME(async_closures): We could look at the `hir::Upvar` instead? assert_eq!(coroutine_capture.place.ty(), parent_capture.place.ty()); } - let by_move_coroutine_ty = Ty::new_coroutine( - tcx, - coroutine_def_id.to_def_id(), - ty::CoroutineArgs::new( + let by_move_coroutine_ty = tcx + .instantiate_bound_regions_with_erased(parent_closure_args.coroutine_closure_sig()) + .to_coroutine_given_kind_and_upvars( tcx, - ty::CoroutineArgsParts { - parent_args: args.parent_args(), - kind_ty: Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce), - resume_ty: args.resume_ty(), - yield_ty: args.yield_ty(), - return_ty: args.return_ty(), - witness: args.witness(), - // Concatenate the args + closure's captures (since they're all by move). - tupled_upvars_ty: Ty::new_tup_from_iter( - tcx, - tupled_inputs_ty - .tuple_fields() - .iter() - .chain(parent_upvars_ty.tuple_fields()), - ), - }, - ) - .args, - ); + parent_closure_args.parent_args(), + coroutine_def_id.to_def_id(), + ty::ClosureKind::FnOnce, + tcx.lifetimes.re_erased, + parent_closure_args.tupled_upvars_ty(), + parent_closure_args.coroutine_captures_by_ref_ty(), + ); let mut by_move_body = body.clone(); MakeByMoveBody { tcx, by_ref_fields, by_move_coroutine_ty }.visit_body(&mut by_move_body); diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs index acff4a38338f..3e33de32efb0 100644 --- a/src/tools/miri/tests/pass/async-closure-captures.rs +++ b/src/tools/miri/tests/pass/async-closure-captures.rs @@ -1,3 +1,5 @@ +// Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync + #![feature(async_closure, noop_waker)] use std::future::Future; diff --git a/tests/ui/async-await/async-closures/captures.rs b/tests/ui/async-await/async-closures/captures.rs index 46bbf53f0a7d..e3ab8713709d 100644 --- a/tests/ui/async-await/async-closures/captures.rs +++ b/tests/ui/async-await/async-closures/captures.rs @@ -3,6 +3,8 @@ //@ run-pass //@ check-run-results +// Same as miri's `tests/pass/async-closure-captures.rs`, keep in sync + #![feature(async_closure)] extern crate block_on; From 382459e0478bfefacd0c1c5a0240bd4bab518d53 Mon Sep 17 00:00:00 2001 From: Aaron Loyd Date: Fri, 29 Mar 2024 17:07:38 -0500 Subject: [PATCH 35/51] Add section to sanitizer doc for `-Zexternal-clangrt` After spending a week looking for answers to how to do the very thing this flag lets me do, it felt appropriate to document it where I would've expected it to be. --- .../src/compiler-flags/external-clangrt.md | 6 ++++++ .../unstable-book/src/compiler-flags/sanitizer.md | 15 +++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/external-clangrt.md diff --git a/src/doc/unstable-book/src/compiler-flags/external-clangrt.md b/src/doc/unstable-book/src/compiler-flags/external-clangrt.md new file mode 100644 index 000000000000..76b78d733e51 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/external-clangrt.md @@ -0,0 +1,6 @@ +# `external-clangrt` + +This option controls whether the compiler links in its own runtime library for +[sanitizers](./sanitizer.md). Passing this flag makes the compiler *not* link +its own library. For more information, see the section in the sanitizers doc on +[working with other languages.](./sanitizer.md#working-with-other-languages) diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index c8fd154a00ec..72b44e002b4d 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -45,6 +45,9 @@ To enable a sanitizer compile with `-Zsanitizer=address`, `-Zsanitizer=cfi`, `-Zsanitizer=dataflow`,`-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`, `-Zsanitizer=memtag`, `-Zsanitizer=shadow-call-stack`, or `-Zsanitizer=thread`. You might also need the `--target` and `build-std` flags. +If you're working with other languages that are also instrumented with sanitizers, +you might need the `external-clangrt` flag. See the section on +[working with other languages](#working-with-other-languages). Example: ```shell @@ -853,6 +856,18 @@ functionality][build-std]. [build-std]: ../../cargo/reference/unstable.html#build-std +# Working with other languages + +Sanitizers rely on compiler runtime libraries to function properly. Rust links +in its own compiler runtime which might conflict with runtimes required by +languages such as C++. Since Rust's runtime doesn't always contain the symbols +required by C++ instrumented code, you might need to skip linking it so another +runtime can be linked instead. + +A separate unstable option `-Zexternal-clangrt` can be used to make rustc skip +linking the compiler runtime for the sanitizer. This will require you to link +in an external runtime, such as from clang instead. + # Build scripts and procedural macros Use of sanitizers together with build scripts and procedural macros is From c6348a976831958e88ab90afa91eb17f68dc1e6f Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 2 Apr 2024 21:38:06 -0400 Subject: [PATCH 36/51] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index a59aba136aab..0637083df5bb 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit a59aba136aab5510c16b0750a36cbd9916f91796 +Subproject commit 0637083df5bbdcc951845f0d2eff6999cdb6d30a From 5075931290ac4939b1645d2a9cde06cce240ba59 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Tue, 2 Apr 2024 22:46:00 +0000 Subject: [PATCH 37/51] rustc_ast: Update `P` docs to reflect mutable status. `P` has implemented `DerefMut` since #54277. While this was lamented at the time [1], rustc now relies on it extensively via the many implementors of MutVisitor [2]. Updates the docs to reflect that `P` is fundamentally mutable, and a few other cleanups to make them nicer to browse. [1]: https://github.com/rust-lang/rust/pull/54277#discussion_r257181754 [2]: https://doc.rust-lang.org/1.77.1/nightly-rustc/rustc_ast/mut_visit/trait.MutVisitor.html#implementors --- compiler/rustc_ast/src/ptr.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs index 0140fb752bf9..e22a523dbc3e 100644 --- a/compiler/rustc_ast/src/ptr.rs +++ b/compiler/rustc_ast/src/ptr.rs @@ -1,6 +1,6 @@ //! The AST pointer. //! -//! Provides `P`, a frozen owned smart pointer. +//! Provides [`P`][struct@P], an owned smart pointer. //! //! # Motivations and benefits //! @@ -8,18 +8,14 @@ //! passes (e.g., one may be able to bypass the borrow checker with a shared //! `ExprKind::AddrOf` node taking a mutable borrow). //! -//! * **Immutability**: `P` disallows mutating its inner `T`, unlike `Box` -//! (unless it contains an `Unsafe` interior, but that may be denied later). -//! This mainly prevents mistakes, but also enforces a kind of "purity". -//! //! * **Efficiency**: folding can reuse allocation space for `P` and `Vec`, //! the latter even when the input and output types differ (as it would be the //! case with arenas or a GADT AST using type parameters to toggle features). //! -//! * **Maintainability**: `P` provides a fixed interface - `Deref`, -//! `and_then` and `map` - which can remain fully functional even if the -//! implementation changes (using a special thread-local heap, for example). -//! Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated. +//! * **Maintainability**: `P` provides an interface, which can remain fully +//! functional even if the implementation changes (using a special thread-local +//! heap, for example). Moreover, a switch to, e.g., `P<'a, T>` would be easy +//! and mostly automated. use std::fmt::{self, Debug, Display}; use std::ops::{Deref, DerefMut}; @@ -29,6 +25,8 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; /// An owned smart pointer. +/// +/// See the [module level documentation][crate::ptr] for details. pub struct P { ptr: Box, } From a277c901d95c5fcbb3dbd6608731eebb9e1a01ce Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 27 Feb 2024 11:57:52 +0000 Subject: [PATCH 38/51] Remove MIR unsafe check This also remove safety information from MIR. --- compiler/rustc_interface/src/passes.rs | 3 - compiler/rustc_interface/src/tests.rs | 1 - compiler/rustc_middle/src/arena.rs | 1 - compiler/rustc_middle/src/mir/mod.rs | 15 +- compiler/rustc_middle/src/mir/query.rs | 63 -- compiler/rustc_middle/src/query/mod.rs | 6 - compiler/rustc_middle/src/ty/codec.rs | 1 - compiler/rustc_mir_build/src/build/block.rs | 45 +- .../rustc_mir_build/src/build/custom/mod.rs | 5 +- .../src/build/expr/as_rvalue.rs | 15 +- .../rustc_mir_build/src/build/expr/into.rs | 2 +- .../rustc_mir_build/src/build/matches/mod.rs | 2 +- compiler/rustc_mir_build/src/build/mod.rs | 52 +- compiler/rustc_mir_build/src/build/scope.rs | 18 +- .../rustc_mir_build/src/check_unsafety.rs | 5 - compiler/rustc_mir_transform/messages.ftl | 49 -- .../rustc_mir_transform/src/check_unsafety.rs | 615 ------------------ compiler/rustc_mir_transform/src/errors.rs | 171 +---- compiler/rustc_mir_transform/src/lib.rs | 7 - compiler/rustc_session/src/options.rs | 2 - .../incremental/hashes/function_interfaces.rs | 6 +- tests/incremental/hashes/inherent_impls.rs | 8 +- ...fg-pre-optimizations.after.panic-abort.mir | 2 - ...g-pre-optimizations.after.panic-unwind.mir | 2 - ...c_abort.main.AbortUnwindingCalls.after.mir | 2 - .../mir-opt/box_expr.main.ElaborateDrops.diff | 2 - ...await.b-{closure#0}.coroutine_resume.0.mir | 8 +- ...e_out.move_out_by_subslice.built.after.mir | 6 +- ...move_out.move_out_from_end.built.after.mir | 6 +- ...motion_extern_static.FOO.PromoteTemps.diff | 2 - .../const_prop/address_of_pair.fn0.GVN.diff | 2 - ...for_slices.main.GVN.32bit.panic-abort.diff | 6 +- ...or_slices.main.GVN.32bit.panic-unwind.diff | 6 +- ...for_slices.main.GVN.64bit.panic-abort.diff | 6 +- ...or_slices.main.GVN.64bit.panic-unwind.diff | 6 +- .../boxes.main.GVN.panic-abort.diff | 2 - .../boxes.main.GVN.panic-unwind.diff | 2 - .../const_prop/indirect_mutation.bar.GVN.diff | 2 - .../const_prop/invalid_constant.main.GVN.diff | 12 +- .../invalid_constant.main.RemoveZsts.diff | 12 +- .../mutable_variable_no_prop.main.GVN.diff | 2 - .../transmute.from_char.GVN.32bit.diff | 2 - .../transmute.from_char.GVN.64bit.diff | 2 - .../transmute.invalid_bool.GVN.32bit.diff | 2 - .../transmute.invalid_bool.GVN.64bit.diff | 2 - .../transmute.invalid_char.GVN.32bit.diff | 2 - .../transmute.invalid_char.GVN.64bit.diff | 2 - .../transmute.less_as_i8.GVN.32bit.diff | 2 - .../transmute.less_as_i8.GVN.64bit.diff | 2 - ...mute.undef_union_as_integer.GVN.32bit.diff | 2 - ...mute.undef_union_as_integer.GVN.64bit.diff | 2 - .../transmute.unreachable_box.GVN.32bit.diff | 2 - .../transmute.unreachable_box.GVN.64bit.diff | 2 - ...ransmute.unreachable_direct.GVN.32bit.diff | 2 - ...ransmute.unreachable_direct.GVN.64bit.diff | 2 - .../transmute.unreachable_mut.GVN.32bit.diff | 2 - .../transmute.unreachable_mut.GVN.64bit.diff | 2 - .../transmute.unreachable_ref.GVN.32bit.diff | 2 - .../transmute.unreachable_ref.GVN.64bit.diff | 2 - .../transmute.valid_char.GVN.32bit.diff | 2 - .../transmute.valid_char.GVN.64bit.diff | 2 - ...reborrow.demiraw.CopyProp.panic-abort.diff | 4 +- ...eborrow.demiraw.CopyProp.panic-unwind.diff | 4 +- .../reborrow.miraw.CopyProp.panic-abort.diff | 4 +- .../reborrow.miraw.CopyProp.panic-unwind.diff | 4 +- ...n.DataflowConstProp.32bit.panic-abort.diff | 38 +- ....DataflowConstProp.32bit.panic-unwind.diff | 38 +- ...n.DataflowConstProp.64bit.panic-abort.diff | 38 +- ....DataflowConstProp.64bit.panic-unwind.diff | 38 +- ...oxed_slice.main.GVN.32bit.panic-abort.diff | 38 +- ...xed_slice.main.GVN.32bit.panic-unwind.diff | 38 +- ...oxed_slice.main.GVN.64bit.panic-abort.diff | 38 +- ...xed_slice.main.GVN.64bit.panic-unwind.diff | 38 +- ...tr.main.DataflowConstProp.panic-abort.diff | 8 +- ...r.main.DataflowConstProp.panic-unwind.diff | 8 +- ...ute.from_char.DataflowConstProp.32bit.diff | 2 - ...ute.from_char.DataflowConstProp.64bit.diff | 2 - ....invalid_bool.DataflowConstProp.32bit.diff | 2 - ....invalid_bool.DataflowConstProp.64bit.diff | 2 - ....invalid_char.DataflowConstProp.32bit.diff | 2 - ....invalid_char.DataflowConstProp.64bit.diff | 2 - ...te.less_as_i8.DataflowConstProp.32bit.diff | 2 - ...te.less_as_i8.DataflowConstProp.64bit.diff | 2 - ...on_as_integer.DataflowConstProp.32bit.diff | 2 - ...on_as_integer.DataflowConstProp.64bit.diff | 2 - ...reachable_box.DataflowConstProp.32bit.diff | 2 - ...reachable_box.DataflowConstProp.64bit.diff | 2 - ...chable_direct.DataflowConstProp.32bit.diff | 2 - ...chable_direct.DataflowConstProp.64bit.diff | 2 - ...reachable_mut.DataflowConstProp.32bit.diff | 2 - ...reachable_mut.DataflowConstProp.64bit.diff | 2 - ...reachable_ref.DataflowConstProp.32bit.diff | 2 - ...reachable_ref.DataflowConstProp.64bit.diff | 2 - ...te.valid_char.DataflowConstProp.32bit.diff | 2 - ...te.valid_char.DataflowConstProp.64bit.diff | 2 - ...in.DestinationPropagation.panic-abort.diff | 6 +- ...n.DestinationPropagation.panic-unwind.diff | 6 +- .../gvn.dereferences.GVN.panic-abort.diff | 10 +- .../gvn.dereferences.GVN.panic-unwind.diff | 10 +- tests/mir-opt/gvn.slices.GVN.panic-abort.diff | 6 +- .../mir-opt/gvn.slices.GVN.panic-unwind.diff | 6 +- ...xpression_elimination.GVN.panic-abort.diff | 12 +- ...pression_elimination.GVN.panic-unwind.diff | 12 +- .../gvn.wide_ptr_integer.GVN.panic-abort.diff | 6 +- ...gvn.wide_ptr_integer.GVN.panic-unwind.diff | 6 +- .../gvn_uninhabited.f.GVN.panic-abort.diff | 4 +- .../gvn_uninhabited.f.GVN.panic-unwind.diff | 4 +- .../asm_unwind.main.Inline.panic-unwind.diff | 2 - ...ine_coroutine.main.Inline.panic-abort.diff | 8 +- ...ne_coroutine.main.Inline.panic-unwind.diff | 8 +- ...inline_instruction_set.default.Inline.diff | 2 - .../inline_shims.drop.Inline.panic-abort.diff | 20 +- ...inline_shims.drop.Inline.panic-unwind.diff | 12 +- ...l_unsigned_smaller.Inline.panic-abort.diff | 2 - ..._unsigned_smaller.Inline.panic-unwind.diff | 2 - ...d_smaller.PreCodegen.after.panic-abort.mir | 2 - ..._smaller.PreCodegen.after.panic-unwind.mir | 2 - ..._shr_signed_bigger.Inline.panic-abort.diff | 2 - ...shr_signed_bigger.Inline.panic-unwind.diff | 2 - ...ed_bigger.PreCodegen.after.panic-abort.mir | 2 - ...d_bigger.PreCodegen.after.panic-unwind.mir | 2 - ...d.unwrap_unchecked.Inline.panic-abort.diff | 14 +- ....unwrap_unchecked.Inline.panic-unwind.diff | 14 +- ...unchecked.PreCodegen.after.panic-abort.mir | 10 +- ...nchecked.PreCodegen.after.panic-unwind.mir | 10 +- ...y.run2-{closure#0}.Inline.panic-abort.diff | 24 +- ....run2-{closure#0}.Inline.panic-unwind.diff | 24 +- ...b_check.unwrap_unchecked.InstSimplify.diff | 28 +- ....AbortUnwindingCalls.after.panic-abort.mir | 2 - ...AbortUnwindingCalls.after.panic-unwind.mir | 2 - ...test.ElaborateDrops.before.panic-abort.mir | 8 +- ...est.ElaborateDrops.before.panic-unwind.mir | 8 +- .../mir-opt/issue_72181.main.built.after.mir | 2 - .../issue_72181_1.main.built.after.mir | 2 - ...e_75439.foo.MatchBranchSimplification.diff | 6 +- ...mutable_ref.JumpThreading.panic-abort.diff | 2 - ...utable_ref.JumpThreading.panic-unwind.diff | 2 - ...len_raw.NormalizeArrayLen.panic-abort.diff | 2 - ...en_raw.NormalizeArrayLen.panic-unwind.diff | 2 - ...cs.assume.LowerIntrinsics.panic-abort.diff | 2 - ...s.assume.LowerIntrinsics.panic-unwind.diff | 2 - ...erlapping.LowerIntrinsics.panic-abort.diff | 2 - ...rlapping.LowerIntrinsics.panic-unwind.diff | 2 - ...primitive.LowerIntrinsics.panic-abort.diff | 2 - ...rimitive.LowerIntrinsics.panic-unwind.diff | 2 - ...inhabited.LowerIntrinsics.panic-abort.diff | 2 - ...nhabited.LowerIntrinsics.panic-unwind.diff | 2 - ...inhabited.LowerIntrinsics.panic-abort.diff | 2 - ...nhabited.LowerIntrinsics.panic-unwind.diff | 2 - ...e_ref_dst.LowerIntrinsics.panic-abort.diff | 2 - ..._ref_dst.LowerIntrinsics.panic-unwind.diff | 2 - ...inhabited.LowerIntrinsics.panic-abort.diff | 2 - ...nhabited.LowerIntrinsics.panic-unwind.diff | 2 - ...reachable.LowerIntrinsics.panic-abort.diff | 2 - ...eachable.LowerIntrinsics.panic-unwind.diff | 2 - ...ve_string.LowerIntrinsics.panic-abort.diff | 2 - ...e_string.LowerIntrinsics.panic-unwind.diff | 2 - ...ecked_ops.checked_shl.PreCodegen.after.mir | 10 +- ...witch_targets.ub_if_b.PreCodegen.after.mir | 6 +- .../loops.int_range.PreCodegen.after.mir | 4 +- ...m_replace.PreCodegen.after.panic-abort.mir | 20 +- ..._replace.PreCodegen.after.panic-unwind.mir | 20 +- ...ward_loop.PreCodegen.after.panic-abort.mir | 4 +- ...ard_loop.PreCodegen.after.panic-unwind.mir | 4 +- ...iter_next.PreCodegen.after.panic-abort.mir | 4 +- ...ter_next.PreCodegen.after.panic-unwind.mir | 4 +- ...mut_range.PreCodegen.after.panic-abort.mir | 2 - ...ut_range.PreCodegen.after.panic-unwind.mir | 2 - ...ated_loop.PreCodegen.after.panic-abort.mir | 48 +- ...ted_loop.PreCodegen.after.panic-unwind.mir | 48 +- ...ward_loop.PreCodegen.after.panic-abort.mir | 44 +- ...ard_loop.PreCodegen.after.panic-unwind.mir | 44 +- ...ange_loop.PreCodegen.after.panic-abort.mir | 4 +- ...nge_loop.PreCodegen.after.panic-unwind.mir | 4 +- ...erse_loop.PreCodegen.after.panic-abort.mir | 50 +- ...rse_loop.PreCodegen.after.panic-unwind.mir | 50 +- ...raw_then_mut_shr.ReferencePropagation.diff | 2 - ...gation_const_ptr.ReferencePropagation.diff | 268 ++++---- ...pagation_mut_ptr.ReferencePropagation.diff | 238 ++++--- ...ique_with_copies.ReferencePropagation.diff | 4 - ...fg-pre-optimizations.after.panic-abort.mir | 10 +- ...g-pre-optimizations.after.panic-unwind.mir | 10 +- ...s.t1.SimplifyLocals-before-const-prop.diff | 2 - ...s.t2.SimplifyLocals-before-const-prop.diff | 2 - ...s.t3.SimplifyLocals-before-const-prop.diff | 2 - ...s.t4.SimplifyLocals-before-const-prop.diff | 2 - ....unions.ScalarReplacementOfAggregates.diff | 2 - .../tls_access.main.PreCodegen.after.mir | 6 +- ...ocess_never.SimplifyLocals-final.after.mir | 2 - ...rocess_void.SimplifyLocals-final.after.mir | 2 - ...d_access.bar.SimplifyCfg-initial.after.mir | 2 - tests/ui/asm/x86_64/goto.rs | 2 - .../{goto.mirunsafeck.stderr => goto.stderr} | 4 +- tests/ui/asm/x86_64/goto.thirunsafeck.stderr | 23 - 194 files changed, 667 insertions(+), 2238 deletions(-) delete mode 100644 compiler/rustc_mir_transform/src/check_unsafety.rs rename tests/ui/asm/x86_64/{goto.mirunsafeck.stderr => goto.stderr} (92%) delete mode 100644 tests/ui/asm/x86_64/goto.thirunsafeck.stderr diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index d763a12f816b..1f92cc4d7639 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -748,9 +748,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { sess.time("MIR_effect_checking", || { for def_id in tcx.hir().body_owners() { - if !tcx.sess.opts.unstable_opts.thir_unsafeck { - rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id); - } tcx.ensure().has_ffi_unwind_calls(def_id); // If we need to codegen, ensure that we emit all errors from diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 3b78e6a43ab3..b9025917d137 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -840,7 +840,6 @@ fn test_unstable_options_tracking_hash() { tracked!(stack_protector, StackProtector::All); tracked!(teach, true); tracked!(thinlto, Some(true)); - tracked!(thir_unsafeck, false); tracked!(tiny_const_eval_limit, true); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); tracked!(translate_remapped_path_to_local_path, false); diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index c90427256b85..bd11b3eb04c6 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -35,7 +35,6 @@ macro_rules! arena_types { )>, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, - [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, [decode] code_region: rustc_middle::mir::coverage::CodeRegion, [] const_allocs: rustc_middle::mir::interpret::Allocation, [] region_scope_tree: rustc_middle::middle::region::ScopeTree, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e5a650c5ac4a..b87e9ee60be5 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -845,17 +845,6 @@ impl<'tcx> Body<'tcx> { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)] -pub enum Safety { - Safe, - /// Unsafe because of compiler-generated unsafe code, like `await` desugaring - BuiltinUnsafe, - /// Unsafe because of an unsafe fn - FnUnsafe, - /// Unsafe because of an `unsafe` block - ExplicitUnsafe(hir::HirId), -} - impl<'tcx> Index for Body<'tcx> { type Output = BasicBlockData<'tcx>; @@ -1611,8 +1600,6 @@ pub struct SourceScopeData<'tcx> { pub struct SourceScopeLocalData { /// An `HirId` with lint levels equivalent to this scope's lint levels. pub lint_root: hir::HirId, - /// The unsafe block that contains this node. - pub safety: Safety, } /// A collection of projections into user types. @@ -1888,7 +1875,7 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(BasicBlockData<'_>, 144); static_assert_size!(LocalDecl<'_>, 40); - static_assert_size!(SourceScopeData<'_>, 72); + static_assert_size!(SourceScopeData<'_>, 64); static_assert_size!(Statement<'_>, 32); static_assert_size!(StatementKind<'_>, 16); static_assert_size!(Terminator<'_>, 112); diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 731e050ca9b7..d286c208083e 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -3,9 +3,7 @@ use crate::mir; use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; use rustc_data_structures::fx::FxIndexMap; -use rustc_data_structures::unord::UnordSet; use rustc_errors::ErrorGuaranteed; -use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::BitMatrix; use rustc_index::{Idx, IndexVec}; @@ -18,67 +16,6 @@ use std::fmt::{self, Debug}; use super::{ConstValue, SourceInfo}; -#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] -pub enum UnsafetyViolationKind { - /// Unsafe operation outside `unsafe`. - General, - /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block. - /// Has to be handled as a lint for backwards compatibility. - UnsafeFn, -} - -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] -pub enum UnsafetyViolationDetails { - CallToUnsafeFunction, - UseOfInlineAssembly, - InitializingTypeWith, - CastOfPointerToInt, - UseOfMutableStatic, - UseOfExternStatic, - DerefOfRawPointer, - AccessToUnionField, - MutationOfLayoutConstrainedField, - BorrowOfLayoutConstrainedField, - CallToFunctionWith { - /// Target features enabled in callee's `#[target_feature]` but missing in - /// caller's `#[target_feature]`. - missing: Vec, - /// Target features in `missing` that are enabled at compile time - /// (e.g., with `-C target-feature`). - build_enabled: Vec, - }, -} - -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] -pub struct UnsafetyViolation { - pub source_info: SourceInfo, - pub lint_root: hir::HirId, - pub kind: UnsafetyViolationKind, - pub details: UnsafetyViolationDetails, -} - -#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] -pub enum UnusedUnsafe { - /// `unsafe` block contains no unsafe operations - /// > ``unnecessary `unsafe` block`` - Unused, - /// `unsafe` block nested under another (used) `unsafe` block - /// > ``… because it's nested under this `unsafe` block`` - InUnsafeBlock(hir::HirId), -} - -#[derive(TyEncodable, TyDecodable, HashStable, Debug)] -pub struct UnsafetyCheckResult { - /// Violations that are propagated *upwards* from this function. - pub violations: Vec, - - /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. - pub used_unsafe_blocks: UnordSet, - - /// This is `Some` iff the item is not a closure. - pub unused_unsafes: Option>, -} - rustc_index::newtype_index! { #[derive(HashStable)] #[encodable] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5e4454db3e28..62a60a650ecc 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -877,12 +877,6 @@ rustc_queries! { desc { |tcx| "collecting all inherent impls for `{:?}`", key } } - /// The result of unsafety-checking this `LocalDefId` with the old checker. - query mir_unsafety_check_result(key: LocalDefId) -> &'tcx mir::UnsafetyCheckResult { - desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } - } - /// Unsafety-check this `LocalDefId`. query check_unsafety(key: LocalDefId) { desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index ddbc0bffaedd..e7a1679b151d 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -458,7 +458,6 @@ impl_decodable_via_ref! { &'tcx ty::List>, &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, - &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, &'tcx mir::coverage::CodeRegion, &'tcx ty::List, diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 6200f4bda6ba..00e99f330f72 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -13,31 +13,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ast_block: BlockId, source_info: SourceInfo, ) -> BlockAnd<()> { - let Block { region_scope, span, ref stmts, expr, targeted_by_break, safety_mode } = + let Block { region_scope, span, ref stmts, expr, targeted_by_break, safety_mode: _ } = self.thir[ast_block]; self.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| { if targeted_by_break { this.in_breakable_scope(None, destination, span, |this| { - Some(this.ast_block_stmts( - destination, - block, - span, - stmts, - expr, - safety_mode, - region_scope, - )) + Some(this.ast_block_stmts(destination, block, span, stmts, expr, region_scope)) }) } else { - this.ast_block_stmts( - destination, - block, - span, - stmts, - expr, - safety_mode, - region_scope, - ) + this.ast_block_stmts(destination, block, span, stmts, expr, region_scope) } }) } @@ -49,7 +33,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, stmts: &[StmtId], expr: Option, - safety_mode: BlockSafety, region_scope: Scope, ) -> BlockAnd<()> { let this = self; @@ -72,13 +55,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // First we build all the statements in the block. let mut let_scope_stack = Vec::with_capacity(8); let outer_source_scope = this.source_scope; - let outer_in_scope_unsafe = this.in_scope_unsafe; // This scope information is kept for breaking out of the parent remainder scope in case // one let-else pattern matching fails. // By doing so, we can be sure that even temporaries that receive extended lifetime // assignments are dropped, too. let mut last_remainder_scope = region_scope; - this.update_source_scope_for_safety_mode(span, safety_mode); let source_info = this.source_info(span); for stmt in stmts { @@ -202,7 +183,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let_scope_stack.push(remainder_scope); let visibility_scope = - Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None)); + Some(this.new_source_scope(remainder_span, LintLevel::Inherited)); let initializer_span = this.thir[*initializer].span; let scope = (*init_scope, source_info); @@ -271,7 +252,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let remainder_span = remainder_scope.span(this.tcx, this.region_scope_tree); let visibility_scope = - Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None)); + Some(this.new_source_scope(remainder_span, LintLevel::Inherited)); // Evaluate the initializer, if present. if let Some(init) = *initializer { @@ -364,22 +345,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } // Restore the original source scope. this.source_scope = outer_source_scope; - this.in_scope_unsafe = outer_in_scope_unsafe; block.unit() } - - /// If we are entering an unsafe block, create a new source scope - fn update_source_scope_for_safety_mode(&mut self, span: Span, safety_mode: BlockSafety) { - debug!("update_source_scope_for({:?}, {:?})", span, safety_mode); - let new_unsafety = match safety_mode { - BlockSafety::Safe => return, - BlockSafety::BuiltinUnsafe => Safety::BuiltinUnsafe, - BlockSafety::ExplicitUnsafe(hir_id) => { - self.in_scope_unsafe = Safety::ExplicitUnsafe(hir_id); - Safety::ExplicitUnsafe(hir_id) - } - }; - - self.source_scope = self.new_source_scope(span, LintLevel::Inherited, Some(new_unsafety)); - } } diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 0475bb8908b2..30877e38318d 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -72,10 +72,7 @@ pub(super) fn build_custom_mir<'tcx>( parent_scope: None, inlined: None, inlined_parent_scope: None, - local_data: ClearCrossCrate::Set(SourceScopeLocalData { - lint_root: hir_id, - safety: Safety::Safe, - }), + local_data: ClearCrossCrate::Set(SourceScopeLocalData { lint_root: hir_id }), }); body.injection_phase = Some(parse_attribute(attr)); diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index c77f4a06d056..00600f354ca5 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -118,19 +118,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Box { value } => { let value_ty = this.thir[value].ty; let tcx = this.tcx; - - // `exchange_malloc` is unsafe but box is safe, so need a new scope. - let synth_scope = this.new_source_scope( - expr_span, - LintLevel::Inherited, - Some(Safety::BuiltinUnsafe), - ); - let synth_info = SourceInfo { span: expr_span, scope: synth_scope }; + let source_info = this.source_info(expr_span); let size = this.temp(tcx.types.usize, expr_span); this.cfg.push_assign( block, - synth_info, + source_info, size, Rvalue::NullaryOp(NullOp::SizeOf, value_ty), ); @@ -138,7 +131,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let align = this.temp(tcx.types.usize, expr_span); this.cfg.push_assign( block, - synth_info, + source_info, align, Rvalue::NullaryOp(NullOp::AlignOf, value_ty), ); @@ -154,7 +147,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let success = this.cfg.start_new_block(); this.cfg.terminate( block, - synth_info, + source_info, TerminatorKind::Call { func: exchange_malloc, args: vec![ diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index b4eeeccc127b..c8360b6a5fdd 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // FIXME: Does this need extra logic to handle let-chains? let source_info = if this.is_let(cond) { let variable_scope = - this.new_source_scope(then_span, LintLevel::Inherited, None); + this.new_source_scope(then_span, LintLevel::Inherited); this.source_scope = variable_scope; SourceInfo { span: then_span, scope: variable_scope } } else { diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index a6b513ce7d06..1ea671a4f791 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -732,7 +732,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut |this, name, mode, var, span, ty, user_ty| { if visibility_scope.is_none() { visibility_scope = - Some(this.new_source_scope(scope_span, LintLevel::Inherited, None)); + Some(this.new_source_scope(scope_span, LintLevel::Inherited)); } let source_info = SourceInfo { span, scope: this.source_scope }; let visibility_scope = visibility_scope.unwrap(); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 274edf358e0b..6972bc00e0b2 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -66,17 +66,10 @@ pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx // maybe move the check to a MIR pass? tcx.ensure().check_liveness(def); - if tcx.sess.opts.unstable_opts.thir_unsafeck { - // Don't steal here if THIR unsafeck is being used. Instead - // steal in unsafeck. This is so that pattern inline constants - // can be evaluated as part of building the THIR of the parent - // function without a cycle. - build_mir(&thir.borrow()) - } else { - // We ran all queries that depended on THIR at the beginning - // of `mir_build`, so now we can steal it - build_mir(&thir.steal()) - } + // Don't steal here, instead steal in unsafeck. This is so that + // pattern inline constants can be evaluated as part of building the + // THIR of the parent function without a cycle. + build_mir(&thir.borrow()) } }; @@ -190,9 +183,6 @@ struct Builder<'a, 'tcx> { /// `{ STMTS; EXPR1 } + EXPR2`. block_context: BlockContext, - /// The current unsafe block in scope - in_scope_unsafe: Safety, - /// The vector of all scopes that we have created thus far; /// we track this for debuginfo later. source_scopes: IndexVec>, @@ -470,11 +460,6 @@ fn construct_fn<'tcx>( .output .span(); - let safety = match fn_sig.unsafety { - hir::Unsafety::Normal => Safety::Safe, - hir::Unsafety::Unsafe => Safety::FnUnsafe, - }; - let mut abi = fn_sig.abi; if let DefKind::Closure = tcx.def_kind(fn_def) { // HACK(eddyb) Avoid having RustCall on closures, @@ -520,7 +505,6 @@ fn construct_fn<'tcx>( fn_id, span_with_body, arguments.len(), - safety, return_ty, return_ty_span, coroutine, @@ -590,18 +574,8 @@ fn construct_const<'a, 'tcx>( }; let infcx = tcx.infer_ctxt().build(); - let mut builder = Builder::new( - thir, - infcx, - def, - hir_id, - span, - 0, - Safety::Safe, - const_ty, - const_ty_span, - None, - ); + let mut builder = + Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None); let mut block = START_BLOCK; unpack!(block = builder.expr_into_dest(Place::return_place(), block, expr)); @@ -723,10 +697,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - parent_scope: None, inlined: None, inlined_parent_scope: None, - local_data: ClearCrossCrate::Set(SourceScopeLocalData { - lint_root: hir_id, - safety: Safety::Safe, - }), + local_data: ClearCrossCrate::Set(SourceScopeLocalData { lint_root: hir_id }), }); cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); @@ -753,7 +724,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { hir_id: hir::HirId, span: Span, arg_count: usize, - safety: Safety, return_ty: Ty<'tcx>, return_span: Span, coroutine: Option>>, @@ -795,7 +765,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { guard_context: vec![], fixed_temps: Default::default(), fixed_temps_scope: None, - in_scope_unsafe: safety, local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1), canonical_user_type_annotations: IndexVec::new(), upvars: CaptureMap::new(), @@ -807,10 +776,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; assert_eq!(builder.cfg.start_new_block(), START_BLOCK); - assert_eq!( - builder.new_source_scope(span, lint_level, Some(safety)), - OUTERMOST_SOURCE_SCOPE - ); + assert_eq!(builder.new_source_scope(span, lint_level), OUTERMOST_SOURCE_SCOPE); builder.source_scopes[OUTERMOST_SOURCE_SCOPE].parent_scope = None; builder @@ -1024,7 +990,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .as_ref() .assert_crate_local() .lint_root; - self.maybe_new_source_scope(pattern_span, None, arg_hir_id, parent_id); + self.maybe_new_source_scope(pattern_span, arg_hir_id, parent_id); } fn get_unit_temp(&mut self) -> Place<'tcx> { diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index aef63896dde1..9ac8c1b44174 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -578,7 +578,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let LintLevel::Explicit(current_hir_id) = lint_level { let parent_id = self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root; - self.maybe_new_source_scope(region_scope.1.span, None, current_hir_id, parent_id); + self.maybe_new_source_scope(region_scope.1.span, current_hir_id, parent_id); } self.push_scope(region_scope); let mut block; @@ -767,7 +767,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn maybe_new_source_scope( &mut self, span: Span, - safety: Option, current_id: HirId, parent_id: HirId, ) { @@ -797,7 +796,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if current_root != parent_root { let lint_level = LintLevel::Explicit(current_root); - self.source_scope = self.new_source_scope(span, lint_level, safety); + self.source_scope = self.new_source_scope(span, lint_level); } } @@ -846,18 +845,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } /// Creates a new source scope, nested in the current one. - pub(crate) fn new_source_scope( - &mut self, - span: Span, - lint_level: LintLevel, - safety: Option, - ) -> SourceScope { + pub(crate) fn new_source_scope(&mut self, span: Span, lint_level: LintLevel) -> SourceScope { let parent = self.source_scope; debug!( - "new_source_scope({:?}, {:?}, {:?}) - parent({:?})={:?}", + "new_source_scope({:?}, {:?}) - parent({:?})={:?}", span, lint_level, - safety, parent, self.source_scopes.get(parent) ); @@ -867,9 +860,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } else { self.source_scopes[parent].local_data.as_ref().assert_crate_local().lint_root }, - safety: safety.unwrap_or_else(|| { - self.source_scopes[parent].local_data.as_ref().assert_crate_local().safety - }), }; self.source_scopes.push(SourceScopeData { span, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 07dc332b7914..8aa9a75d96af 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -909,11 +909,6 @@ impl UnsafeOpKind { } pub fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { - // THIR unsafeck can be disabled with `-Z thir-unsafeck=off` - if !tcx.sess.opts.unstable_opts.thir_unsafeck { - return; - } - // Closures and inline consts are handled by their owner, if it has a body // Also, don't safety check custom MIR if tcx.is_typeck_child(def.to_def_id()) || tcx.has_attr(def, sym::custom_mir) { diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index b8dbdf18db3e..f9b79d72b050 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -1,6 +1,4 @@ mir_transform_arithmetic_overflow = this arithmetic operation will overflow -mir_transform_call_to_unsafe_label = call to unsafe function -mir_transform_call_to_unsafe_note = consult the function's documentation for information on how to avoid undefined behavior mir_transform_const_defined_here = `const` item defined here mir_transform_const_modify = attempting to modify a `const` item @@ -11,10 +9,6 @@ mir_transform_const_mut_borrow = taking a mutable reference to a `const` item .note2 = the mutable reference will refer to this temporary, not the original `const` item .note3 = mutable reference created due to call to this method -mir_transform_const_ptr2int_label = cast of pointer to int -mir_transform_const_ptr2int_note = casting pointers to integers in constants -mir_transform_deref_ptr_label = dereference of raw pointer -mir_transform_deref_ptr_note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior mir_transform_ffi_unwind_call = call to {$foreign -> [true] foreign function *[false] function pointer @@ -23,56 +17,13 @@ mir_transform_ffi_unwind_call = call to {$foreign -> mir_transform_fn_item_ref = taking a reference to a function item does not give a function pointer .suggestion = cast `{$ident}` to obtain a function pointer -mir_transform_initializing_valid_range_label = initializing type with `rustc_layout_scalar_valid_range` attr -mir_transform_initializing_valid_range_note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior mir_transform_must_not_suspend = {$pre}`{$def_path}`{$post} held across a suspend point, but should not be .label = the value is held across this suspend point .note = {$reason} .help = consider using a block (`{"{ ... }"}`) to shrink the value's scope, ending before the suspend point - -mir_transform_mutation_layout_constrained_borrow_label = borrow of layout constrained field with interior mutability -mir_transform_mutation_layout_constrained_borrow_note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values -mir_transform_mutation_layout_constrained_label = mutation of layout constrained field -mir_transform_mutation_layout_constrained_note = mutating layout constrained fields cannot statically be checked for valid values mir_transform_operation_will_panic = this operation will panic at runtime -mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in_unsafe_fn_allowed -> - [true] function or block - *[false] block - } - .not_inherited = items do not inherit unsafety from separate enclosing items - -mir_transform_target_feature_call_help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> - [1] feature - *[count] features - }: {$missing_target_features} - -mir_transform_target_feature_call_label = call to function with `#[target_feature]` -mir_transform_target_feature_call_note = the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features - } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it - *[count] them - } in `#[target_feature]` - mir_transform_unaligned_packed_ref = reference to packed field is unaligned .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) .help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) - -mir_transform_union_access_label = access to union field -mir_transform_union_access_note = the field may not be properly initialized: using uninitialized data will cause undefined behavior -mir_transform_unsafe_op_in_unsafe_fn = {$details} is unsafe and requires unsafe block (error E0133) - .suggestion = consider wrapping the function body in an unsafe block - .note = an unsafe function restricts its caller, but its body is safe by default - -mir_transform_unused_unsafe = unnecessary `unsafe` block - .label = because it's nested under this `unsafe` block - -mir_transform_use_of_asm_label = use of inline assembly -mir_transform_use_of_asm_note = inline assembly is entirely unchecked and can cause undefined behavior -mir_transform_use_of_extern_static_label = use of extern static -mir_transform_use_of_extern_static_note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior -mir_transform_use_of_static_mut_label = use of mutable static -mir_transform_use_of_static_mut_note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs deleted file mode 100644 index a0c3de3af586..000000000000 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ /dev/null @@ -1,615 +0,0 @@ -use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet}; -use rustc_hir as hir; -use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::hir_id::HirId; -use rustc_hir::intravisit; -use rustc_hir::{BlockCheckMode, ExprKind, Node}; -use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; -use rustc_middle::mir::*; -use rustc_middle::query::Providers; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; -use rustc_session::lint::Level; - -use std::ops::Bound; - -use crate::errors; - -pub struct UnsafetyChecker<'a, 'tcx> { - body: &'a Body<'tcx>, - body_did: LocalDefId, - violations: Vec, - source_info: SourceInfo, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - - /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. - used_unsafe_blocks: UnordSet, -} - -impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { - fn new( - body: &'a Body<'tcx>, - body_did: LocalDefId, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Self { - Self { - body, - body_did, - violations: vec![], - source_info: SourceInfo::outermost(body.span), - tcx, - param_env, - used_unsafe_blocks: Default::default(), - } - } -} - -impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { - fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - self.source_info = terminator.source_info; - match terminator.kind { - TerminatorKind::Goto { .. } - | TerminatorKind::SwitchInt { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::Yield { .. } - | TerminatorKind::Assert { .. } - | TerminatorKind::CoroutineDrop - | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } => { - // safe (at least as emitted during MIR construction) - } - - TerminatorKind::Call { ref func, .. } => { - let func_ty = func.ty(self.body, self.tcx); - let func_id = - if let ty::FnDef(func_id, _) = func_ty.kind() { Some(func_id) } else { None }; - let sig = func_ty.fn_sig(self.tcx); - if let hir::Unsafety::Unsafe = sig.unsafety() { - self.require_unsafe( - UnsafetyViolationKind::General, - UnsafetyViolationDetails::CallToUnsafeFunction, - ) - } - - if let Some(func_id) = func_id { - self.check_target_features(*func_id); - } - } - - TerminatorKind::InlineAsm { .. } => self.require_unsafe( - UnsafetyViolationKind::General, - UnsafetyViolationDetails::UseOfInlineAssembly, - ), - } - self.super_terminator(terminator, location); - } - - fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { - self.source_info = statement.source_info; - match statement.kind { - StatementKind::Assign(..) - | StatementKind::FakeRead(..) - | StatementKind::SetDiscriminant { .. } - | StatementKind::Deinit(..) - | StatementKind::StorageLive(..) - | StatementKind::StorageDead(..) - | StatementKind::Retag { .. } - | StatementKind::PlaceMention(..) - | StatementKind::Coverage(..) - | StatementKind::Intrinsic(..) - | StatementKind::ConstEvalCounter - | StatementKind::Nop => { - // safe (at least as emitted during MIR construction) - } - // `AscribeUserType` just exists to help MIR borrowck. - // It has no semantics, and everything is already reported by `PlaceMention`. - StatementKind::AscribeUserType(..) => return, - } - self.super_statement(statement, location); - } - - fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { - match rvalue { - Rvalue::Aggregate(box ref aggregate, _) => match aggregate { - &AggregateKind::Array(..) | &AggregateKind::Tuple => {} - &AggregateKind::Adt(adt_did, ..) => { - match self.tcx.layout_scalar_valid_range(adt_did) { - (Bound::Unbounded, Bound::Unbounded) => {} - _ => self.require_unsafe( - UnsafetyViolationKind::General, - UnsafetyViolationDetails::InitializingTypeWith, - ), - } - } - &AggregateKind::Closure(def_id, _) - | &AggregateKind::CoroutineClosure(def_id, _) - | &AggregateKind::Coroutine(def_id, _) => { - let def_id = def_id.expect_local(); - let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = - self.tcx.mir_unsafety_check_result(def_id); - self.register_violations(violations, used_unsafe_blocks.items().copied()); - } - }, - _ => {} - } - self.super_rvalue(rvalue, location); - } - - fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) { - if let Operand::Constant(constant) = op { - let maybe_uneval = match constant.const_ { - Const::Val(..) | Const::Ty(_) => None, - Const::Unevaluated(uv, _) => Some(uv), - }; - - if let Some(uv) = maybe_uneval { - if uv.promoted.is_none() { - let def_id = uv.def; - if self.tcx.def_kind(def_id) == DefKind::InlineConst { - let local_def_id = def_id.expect_local(); - let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = - self.tcx.mir_unsafety_check_result(local_def_id); - self.register_violations(violations, used_unsafe_blocks.items().copied()); - } - } - } - } - self.super_operand(op, location); - } - - fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - // On types with `scalar_valid_range`, prevent - // * `&mut x.field` - // * `x.field = y;` - // * `&x.field` if `field`'s type has interior mutability - // because either of these would allow modifying the layout constrained field and - // insert values that violate the layout constraints. - if context.is_mutating_use() || context.is_borrow() { - self.check_mut_borrowing_layout_constrained_field(*place, context.is_mutating_use()); - } - - // Some checks below need the extra meta info of the local declaration. - let decl = &self.body.local_decls[place.local]; - - // Check the base local: it might be an unsafe-to-access static. We only check derefs of the - // temporary holding the static pointer to avoid duplicate errors - // . - if place.projection.first() == Some(&ProjectionElem::Deref) { - // If the projection root is an artificial local that we introduced when - // desugaring `static`, give a more specific error message - // (avoid the general "raw pointer" clause below, that would only be confusing). - if let LocalInfo::StaticRef { def_id, .. } = *decl.local_info() { - if self.tcx.is_mutable_static(def_id) { - self.require_unsafe( - UnsafetyViolationKind::General, - UnsafetyViolationDetails::UseOfMutableStatic, - ); - return; - } else if self.tcx.is_foreign_item(def_id) { - self.require_unsafe( - UnsafetyViolationKind::General, - UnsafetyViolationDetails::UseOfExternStatic, - ); - return; - } - } - } - - // Check for raw pointer `Deref`. - for (base, proj) in place.iter_projections() { - if proj == ProjectionElem::Deref { - let base_ty = base.ty(self.body, self.tcx).ty; - if base_ty.is_unsafe_ptr() { - self.require_unsafe( - UnsafetyViolationKind::General, - UnsafetyViolationDetails::DerefOfRawPointer, - ) - } - } - } - - // Check for union fields. For this we traverse right-to-left, as the last `Deref` changes - // whether we *read* the union field or potentially *write* to it (if this place is being assigned to). - let mut saw_deref = false; - for (base, proj) in place.iter_projections().rev() { - if proj == ProjectionElem::Deref { - saw_deref = true; - continue; - } - - let base_ty = base.ty(self.body, self.tcx).ty; - if base_ty.is_union() { - // If we did not hit a `Deref` yet and the overall place use is an assignment, the - // rules are different. - let assign_to_field = !saw_deref - && matches!( - context, - PlaceContext::MutatingUse( - MutatingUseContext::Store - | MutatingUseContext::Drop - | MutatingUseContext::AsmOutput - ) - ); - // If this is just an assignment, determine if the assigned type needs dropping. - if assign_to_field { - // We have to check the actual type of the assignment, as that determines if the - // old value is being dropped. - let assigned_ty = place.ty(&self.body.local_decls, self.tcx).ty; - if assigned_ty.needs_drop(self.tcx, self.param_env) { - // This would be unsafe, but should be outright impossible since we reject - // such unions. - assert!( - self.tcx.dcx().has_errors().is_some(), - "union fields that need dropping should be impossible: {assigned_ty}" - ); - } - } else { - self.require_unsafe( - UnsafetyViolationKind::General, - UnsafetyViolationDetails::AccessToUnionField, - ) - } - } - } - } -} - -impl<'tcx> UnsafetyChecker<'_, 'tcx> { - fn require_unsafe(&mut self, kind: UnsafetyViolationKind, details: UnsafetyViolationDetails) { - // Violations can turn out to be `UnsafeFn` during analysis, but they should not start out as such. - assert_ne!(kind, UnsafetyViolationKind::UnsafeFn); - - let source_info = self.source_info; - let lint_root = self.body.source_scopes[self.source_info.scope] - .local_data - .as_ref() - .assert_crate_local() - .lint_root; - self.register_violations( - [&UnsafetyViolation { source_info, lint_root, kind, details }], - UnordItems::empty(), - ); - } - - fn register_violations<'a>( - &mut self, - violations: impl IntoIterator, - new_used_unsafe_blocks: UnordItems>, - ) { - let safety = self.body.source_scopes[self.source_info.scope] - .local_data - .as_ref() - .assert_crate_local() - .safety; - match safety { - // `unsafe` blocks are required in safe code - Safety::Safe => violations.into_iter().for_each(|violation| { - match violation.kind { - UnsafetyViolationKind::General => {} - UnsafetyViolationKind::UnsafeFn => { - bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context") - } - } - if !self.violations.contains(violation) { - self.violations.push(violation.clone()) - } - }), - // With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s - Safety::FnUnsafe => violations.into_iter().for_each(|violation| { - let mut violation = violation.clone(); - violation.kind = UnsafetyViolationKind::UnsafeFn; - if !self.violations.contains(&violation) { - self.violations.push(violation) - } - }), - Safety::BuiltinUnsafe => {} - Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|_violation| { - self.used_unsafe_blocks.insert(hir_id); - }), - }; - - self.used_unsafe_blocks.extend_unord(new_used_unsafe_blocks); - } - fn check_mut_borrowing_layout_constrained_field( - &mut self, - place: Place<'tcx>, - is_mut_use: bool, - ) { - for (place_base, elem) in place.iter_projections().rev() { - match elem { - // Modifications behind a dereference don't affect the value of - // the pointer. - ProjectionElem::Deref => return, - ProjectionElem::Field(..) => { - let ty = place_base.ty(&self.body.local_decls, self.tcx).ty; - if let ty::Adt(def, _) = ty.kind() { - if self.tcx.layout_scalar_valid_range(def.did()) - != (Bound::Unbounded, Bound::Unbounded) - { - let details = if is_mut_use { - UnsafetyViolationDetails::MutationOfLayoutConstrainedField - - // Check `is_freeze` as late as possible to avoid cycle errors - // with opaque types. - } else if !place - .ty(self.body, self.tcx) - .ty - .is_freeze(self.tcx, self.param_env) - { - UnsafetyViolationDetails::BorrowOfLayoutConstrainedField - } else { - continue; - }; - self.require_unsafe(UnsafetyViolationKind::General, details); - } - } - } - _ => {} - } - } - } - - /// Checks whether calling `func_did` needs an `unsafe` context or not, i.e. whether - /// the called function has target features the calling function hasn't. - fn check_target_features(&mut self, func_did: DefId) { - // Unsafety isn't required on wasm targets. For more information see - // the corresponding check in typeck/src/collect.rs - if self.tcx.sess.target.options.is_like_wasm { - return; - } - - let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; - // The body might be a constant, so it doesn't have codegen attributes. - let self_features = &self.tcx.body_codegen_attrs(self.body_did.to_def_id()).target_features; - - // Is `callee_features` a subset of `calling_features`? - if !callee_features.iter().all(|feature| self_features.contains(feature)) { - let missing: Vec<_> = callee_features - .iter() - .copied() - .filter(|feature| !self_features.contains(feature)) - .collect(); - let build_enabled = self - .tcx - .sess - .target_features - .iter() - .copied() - .filter(|feature| missing.contains(feature)) - .collect(); - self.require_unsafe( - UnsafetyViolationKind::General, - UnsafetyViolationDetails::CallToFunctionWith { missing, build_enabled }, - ) - } - } -} - -pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { mir_unsafety_check_result, ..*providers }; -} - -/// Context information for [`UnusedUnsafeVisitor`] traversal, -/// saves (innermost) relevant context -#[derive(Copy, Clone, Debug)] -enum Context { - Safe, - /// in an `unsafe fn` - UnsafeFn, - /// in a *used* `unsafe` block - /// (i.e. a block without unused-unsafe warning) - UnsafeBlock(HirId), -} - -struct UnusedUnsafeVisitor<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - used_unsafe_blocks: &'a UnordSet, - context: Context, - unused_unsafes: &'a mut Vec<(HirId, UnusedUnsafe)>, -} - -impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> { - fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) { - if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules { - let used = match self.tcx.lint_level_at_node(UNUSED_UNSAFE, block.hir_id) { - (Level::Allow, _) => true, - _ => self.used_unsafe_blocks.contains(&block.hir_id), - }; - let unused_unsafe = match (self.context, used) { - (_, false) => UnusedUnsafe::Unused, - (Context::Safe, true) | (Context::UnsafeFn, true) => { - let previous_context = self.context; - self.context = Context::UnsafeBlock(block.hir_id); - intravisit::walk_block(self, block); - self.context = previous_context; - return; - } - (Context::UnsafeBlock(hir_id), true) => UnusedUnsafe::InUnsafeBlock(hir_id), - }; - self.unused_unsafes.push((block.hir_id, unused_unsafe)); - } - intravisit::walk_block(self, block); - } - - fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { - self.visit_body(self.tcx.hir().body(c.body)) - } - - fn visit_fn( - &mut self, - fk: intravisit::FnKind<'tcx>, - _fd: &'tcx hir::FnDecl<'tcx>, - b: hir::BodyId, - _s: rustc_span::Span, - _id: LocalDefId, - ) { - if matches!(fk, intravisit::FnKind::Closure) { - self.visit_body(self.tcx.hir().body(b)) - } - } -} - -fn check_unused_unsafe( - tcx: TyCtxt<'_>, - def_id: LocalDefId, - used_unsafe_blocks: &UnordSet, -) -> Vec<(HirId, UnusedUnsafe)> { - let body_id = tcx.hir().maybe_body_owned_by(def_id); - - let Some(body_id) = body_id else { - debug!("check_unused_unsafe({:?}) - no body found", def_id); - return vec![]; - }; - - let body = tcx.hir().body(body_id); - let hir_id = tcx.local_def_id_to_hir_id(def_id); - let context = match tcx.hir().fn_sig_by_hir_id(hir_id) { - Some(sig) if sig.header.unsafety == hir::Unsafety::Unsafe => Context::UnsafeFn, - _ => Context::Safe, - }; - - debug!( - "check_unused_unsafe({:?}, context={:?}, body={:?}, used_unsafe_blocks={:?})", - def_id, body, context, used_unsafe_blocks - ); - - let mut unused_unsafes = vec![]; - - let mut visitor = UnusedUnsafeVisitor { - tcx, - used_unsafe_blocks, - context, - unused_unsafes: &mut unused_unsafes, - }; - intravisit::Visitor::visit_body(&mut visitor, body); - - unused_unsafes -} - -fn mir_unsafety_check_result(tcx: TyCtxt<'_>, def: LocalDefId) -> &UnsafetyCheckResult { - debug!("unsafety_violations({:?})", def); - - // N.B., this borrow is valid because all the consumers of - // `mir_built` force this. - let body = &tcx.mir_built(def).borrow(); - - if body.is_custom_mir() || body.tainted_by_errors.is_some() { - return tcx.arena.alloc(UnsafetyCheckResult { - violations: Vec::new(), - used_unsafe_blocks: Default::default(), - unused_unsafes: Some(Vec::new()), - }); - } - - let param_env = tcx.param_env(def); - - let mut checker = UnsafetyChecker::new(body, def, tcx, param_env); - checker.visit_body(body); - - let unused_unsafes = (!tcx.is_typeck_child(def.to_def_id())) - .then(|| check_unused_unsafe(tcx, def, &checker.used_unsafe_blocks)); - - tcx.arena.alloc(UnsafetyCheckResult { - violations: checker.violations, - used_unsafe_blocks: checker.used_unsafe_blocks, - unused_unsafes, - }) -} - -fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { - let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id)); - let nested_parent = if let UnusedUnsafe::InUnsafeBlock(id) = kind { - Some(tcx.sess.source_map().guess_head_span(tcx.hir().span(id))) - } else { - None - }; - tcx.emit_node_span_lint(UNUSED_UNSAFE, id, span, errors::UnusedUnsafe { span, nested_parent }); -} - -pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { - debug!("check_unsafety({:?})", def_id); - - // closures and inline consts are handled by their parent fn. - if tcx.is_typeck_child(def_id.to_def_id()) { - return; - } - - let UnsafetyCheckResult { violations, unused_unsafes, .. } = - tcx.mir_unsafety_check_result(def_id); - // Only suggest wrapping the entire function body in an unsafe block once - let mut suggest_unsafe_block = true; - - for &UnsafetyViolation { source_info, lint_root, kind, ref details } in violations.iter() { - let details = - errors::RequiresUnsafeDetail { violation: details.clone(), span: source_info.span }; - - match kind { - UnsafetyViolationKind::General => { - let op_in_unsafe_fn_allowed = unsafe_op_in_unsafe_fn_allowed(tcx, lint_root); - let note_non_inherited = tcx.hir().parent_iter(lint_root).find(|(id, node)| { - if let Node::Expr(block) = node - && let ExprKind::Block(block, _) = block.kind - && let BlockCheckMode::UnsafeBlock(_) = block.rules - { - true - } else if let Some(sig) = tcx.hir().fn_sig_by_hir_id(*id) - && sig.header.is_unsafe() - { - true - } else { - false - } - }); - let enclosing = if let Some((id, _)) = note_non_inherited { - Some(tcx.sess.source_map().guess_head_span(tcx.hir().span(id))) - } else { - None - }; - tcx.dcx().emit_err(errors::RequiresUnsafe { - span: source_info.span, - enclosing, - details, - op_in_unsafe_fn_allowed, - }); - } - UnsafetyViolationKind::UnsafeFn => { - tcx.emit_node_span_lint( - UNSAFE_OP_IN_UNSAFE_FN, - lint_root, - source_info.span, - errors::UnsafeOpInUnsafeFn { - details, - suggest_unsafe_block: suggest_unsafe_block.then(|| { - let hir_id = tcx.local_def_id_to_hir_id(def_id); - let fn_sig = tcx - .hir() - .fn_sig_by_hir_id(hir_id) - .expect("this violation only occurs in fn"); - let body = tcx.hir().body_owned_by(def_id); - let body_span = tcx.hir().body(body).value.span; - let start = tcx.sess.source_map().start_point(body_span).shrink_to_hi(); - let end = tcx.sess.source_map().end_point(body_span).shrink_to_lo(); - (start, end, fn_sig.span) - }), - }, - ); - suggest_unsafe_block = false; - } - } - } - - for &(block_id, kind) in unused_unsafes.as_ref().unwrap() { - report_unused_unsafe(tcx, kind, block_id); - } -} - -fn unsafe_op_in_unsafe_fn_allowed(tcx: TyCtxt<'_>, id: HirId) -> bool { - tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, id).0 == Level::Allow -} diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 9297bc51fad9..0634e321ea30 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -1,11 +1,6 @@ -use std::borrow::Cow; - -use rustc_errors::{ - codes::*, Applicability, Diag, DiagArgValue, DiagCtxt, DiagMessage, Diagnostic, - EmissionGuarantee, Level, LintDiagnostic, -}; +use rustc_errors::{codes::*, Diag, DiagMessage, LintDiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; -use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; +use rustc_middle::mir::AssertKind; use rustc_middle::ty::TyCtxt; use rustc_session::lint::{self, Lint}; use rustc_span::def_id::DefId; @@ -42,168 +37,6 @@ pub(crate) struct UnalignedPackedRef { pub span: Span, } -#[derive(LintDiagnostic)] -#[diag(mir_transform_unused_unsafe)] -pub(crate) struct UnusedUnsafe { - #[label(mir_transform_unused_unsafe)] - pub span: Span, - #[label] - pub nested_parent: Option, -} - -pub(crate) struct RequiresUnsafe { - pub span: Span, - pub details: RequiresUnsafeDetail, - pub enclosing: Option, - pub op_in_unsafe_fn_allowed: bool, -} - -// The primary message for this diagnostic should be '{$label} is unsafe and...', -// so we need to eagerly translate the label here, which isn't supported by the derive API -// We could also exhaustively list out the primary messages for all unsafe violations, -// but this would result in a lot of duplication. -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for RequiresUnsafe { - #[track_caller] - fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> { - let mut diag = Diag::new(dcx, level, fluent::mir_transform_requires_unsafe); - diag.code(E0133); - diag.span(self.span); - diag.span_label(self.span, self.details.label()); - let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); - diag.arg("details", desc); - diag.arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); - self.details.add_subdiagnostics(&mut diag); - if let Some(sp) = self.enclosing { - diag.span_label(sp, fluent::mir_transform_not_inherited); - } - diag - } -} - -#[derive(Clone)] -pub(crate) struct RequiresUnsafeDetail { - pub span: Span, - pub violation: UnsafetyViolationDetails, -} - -impl RequiresUnsafeDetail { - // FIXME: make this translatable - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] - fn add_subdiagnostics(&self, diag: &mut Diag<'_, G>) { - use UnsafetyViolationDetails::*; - match self.violation { - CallToUnsafeFunction => { - diag.note(fluent::mir_transform_call_to_unsafe_note); - } - UseOfInlineAssembly => { - diag.note(fluent::mir_transform_use_of_asm_note); - } - InitializingTypeWith => { - diag.note(fluent::mir_transform_initializing_valid_range_note); - } - CastOfPointerToInt => { - diag.note(fluent::mir_transform_const_ptr2int_note); - } - UseOfMutableStatic => { - diag.note(fluent::mir_transform_use_of_static_mut_note); - } - UseOfExternStatic => { - diag.note(fluent::mir_transform_use_of_extern_static_note); - } - DerefOfRawPointer => { - diag.note(fluent::mir_transform_deref_ptr_note); - } - AccessToUnionField => { - diag.note(fluent::mir_transform_union_access_note); - } - MutationOfLayoutConstrainedField => { - diag.note(fluent::mir_transform_mutation_layout_constrained_note); - } - BorrowOfLayoutConstrainedField => { - diag.note(fluent::mir_transform_mutation_layout_constrained_borrow_note); - } - CallToFunctionWith { ref missing, ref build_enabled } => { - diag.help(fluent::mir_transform_target_feature_call_help); - diag.arg( - "missing_target_features", - DiagArgValue::StrListSepByAnd( - missing.iter().map(|feature| Cow::from(feature.to_string())).collect(), - ), - ); - diag.arg("missing_target_features_count", missing.len()); - if !build_enabled.is_empty() { - diag.note(fluent::mir_transform_target_feature_call_note); - diag.arg( - "build_target_features", - DiagArgValue::StrListSepByAnd( - build_enabled - .iter() - .map(|feature| Cow::from(feature.to_string())) - .collect(), - ), - ); - diag.arg("build_target_features_count", build_enabled.len()); - } - } - } - } - - fn label(&self) -> DiagMessage { - use UnsafetyViolationDetails::*; - match self.violation { - CallToUnsafeFunction => fluent::mir_transform_call_to_unsafe_label, - UseOfInlineAssembly => fluent::mir_transform_use_of_asm_label, - InitializingTypeWith => fluent::mir_transform_initializing_valid_range_label, - CastOfPointerToInt => fluent::mir_transform_const_ptr2int_label, - UseOfMutableStatic => fluent::mir_transform_use_of_static_mut_label, - UseOfExternStatic => fluent::mir_transform_use_of_extern_static_label, - DerefOfRawPointer => fluent::mir_transform_deref_ptr_label, - AccessToUnionField => fluent::mir_transform_union_access_label, - MutationOfLayoutConstrainedField => { - fluent::mir_transform_mutation_layout_constrained_label - } - BorrowOfLayoutConstrainedField => { - fluent::mir_transform_mutation_layout_constrained_borrow_label - } - CallToFunctionWith { .. } => fluent::mir_transform_target_feature_call_label, - } - } -} - -pub(crate) struct UnsafeOpInUnsafeFn { - pub details: RequiresUnsafeDetail, - - /// These spans point to: - /// 1. the start of the function body - /// 2. the end of the function body - /// 3. the function signature - pub suggest_unsafe_block: Option<(Span, Span, Span)>, -} - -impl<'a> LintDiagnostic<'a, ()> for UnsafeOpInUnsafeFn { - #[track_caller] - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - let desc = diag.dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); - diag.arg("details", desc); - diag.span_label(self.details.span, self.details.label()); - self.details.add_subdiagnostics(diag); - - if let Some((start, end, fn_sig)) = self.suggest_unsafe_block { - diag.span_note(fn_sig, fluent::mir_transform_note); - diag.tool_only_multipart_suggestion( - fluent::mir_transform_suggestion, - vec![(start, " unsafe {".into()), (end, "}".into())], - Applicability::MaybeIncorrect, - ); - } - } - - fn msg(&self) -> DiagMessage { - fluent::mir_transform_unsafe_op_in_unsafe_fn - } -} - pub(crate) struct AssertLint

{ pub span: Span, pub assert_kind: AssertKind

, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index a684f9bdff19..e477c068229f 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -53,7 +53,6 @@ mod add_moves_for_packed_drops; mod add_retag; mod check_const_item_mutation; mod check_packed_ref; -pub mod check_unsafety; mod remove_place_mention; // This pass is public to allow external drivers to perform MIR cleanup mod add_subtyping_projections; @@ -120,7 +119,6 @@ use rustc_mir_dataflow::rustc_peek; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { - check_unsafety::provide(providers); coverage::query::provide(providers); ffi_unwind_calls::provide(providers); shim::provide(providers); @@ -280,11 +278,6 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { } fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { - // MIR unsafety check uses the raw mir, so make sure it is run. - if !tcx.sess.opts.unstable_opts.thir_unsafeck { - tcx.ensure_with_value().mir_unsafety_check_result(def); - } - let mut body = tcx.build_mir(def); pass_manager::dump_mir_for_phase_change(tcx, &body); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6204f8683854..a76eb6b06aa7 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1950,8 +1950,6 @@ written to standard error output)"), #[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")] thinlto: Option = (None, parse_opt_bool, [TRACKED], "enable ThinLTO when possible"), - thir_unsafeck: bool = (true, parse_bool, [TRACKED], - "use the THIR unsafety checker (default: yes)"), /// We default to 1 here since we want to behave like /// a sequential compiler for now. This'll likely be adjusted /// in the future. Note that -Zthreads=0 is the way to get diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index 4fa2762099cd..ab4d578458d4 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -104,17 +104,17 @@ pub fn order_of_parameters(p2: i64, p1: i32) {} // Unsafe ---------------------------------------------------------------------- #[cfg(any(cfail1,cfail4))] -pub fn make_unsafe() {} +pub fn make_unsafe() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub unsafe fn make_unsafe() {} diff --git a/tests/incremental/hashes/inherent_impls.rs b/tests/incremental/hashes/inherent_impls.rs index 2b0de1edc0c6..caea394977a7 100644 --- a/tests/incremental/hashes/inherent_impls.rs +++ b/tests/incremental/hashes/inherent_impls.rs @@ -348,9 +348,9 @@ impl Foo { // Make method unsafe ---------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- pub fn make_method_unsafe(&self) { } } @@ -361,9 +361,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail6")] pub unsafe fn make_method_unsafe(&self) { } } diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir index 3b7c4b8796ea..ef51b07827fb 100644 --- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -17,8 +17,6 @@ fn main() -> () { let _3: *mut usize; scope 3 { debug z => _3; - scope 4 { - } } } } diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index 3dcddea0353f..d1aa9382a2c5 100644 --- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -17,8 +17,6 @@ fn main() -> () { let _3: *mut usize; scope 3 { debug z => _3; - scope 4 { - } } } } diff --git a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir index 6c3128f8c36f..005b3ee3b249 100644 --- a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir +++ b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir @@ -3,8 +3,6 @@ fn main() -> () { let mut _0: (); let _1: (); - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.diff b/tests/mir-opt/box_expr.main.ElaborateDrops.diff index 88b12f19e64d..ec40fac2894e 100644 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.diff +++ b/tests/mir-opt/box_expr.main.ElaborateDrops.diff @@ -15,8 +15,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index d697ea492316..d2a0fb0cb3c3 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -93,17 +93,13 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}); let _17: (); scope 2 { - } - scope 3 { debug result => _17; } } - scope 4 { + scope 3 { debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}); let _33: (); - scope 5 { - } - scope 6 { + scope 4 { debug result => _33; } } diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir index 128af9c56024..db758368a138 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir @@ -16,14 +16,10 @@ fn move_out_by_subslice() -> () { scope 1 { debug a => _1; let _12: [std::boxed::Box; 2]; - scope 4 { + scope 2 { debug _y => _12; } } - scope 2 { - } - scope 3 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir index d50a6872a417..84cd557715c2 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir @@ -16,14 +16,10 @@ fn move_out_from_end() -> () { scope 1 { debug a => _1; let _12: std::boxed::Box; - scope 4 { + scope 2 { debug _y => _12; } } - scope 2 { - } - scope 3 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index 3596671f614f..bfefd2b8c95c 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -9,8 +9,6 @@ let mut _4: &i32; let _5: *const i32; + let mut _6: &[&i32; 1]; - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff index a044cfc62e20..3f4958f60e85 100644 --- a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff @@ -14,8 +14,6 @@ debug ptr => _3; let _5: bool; scope 3 { - } - scope 4 { debug ret => _5; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff index 20fda589c396..826f4c342777 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff @@ -13,11 +13,9 @@ let mut _9: &[i32; 3]; scope 1 { debug a => _1; + let _5: i32; scope 2 { - let _5: i32; - scope 3 { - debug _b => _5; - } + debug _b => _5; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff index f1b90c28e72f..0e2ec65652f5 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff @@ -13,11 +13,9 @@ let mut _9: &[i32; 3]; scope 1 { debug a => _1; + let _5: i32; scope 2 { - let _5: i32; - scope 3 { - debug _b => _5; - } + debug _b => _5; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff index 20fda589c396..826f4c342777 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff @@ -13,11 +13,9 @@ let mut _9: &[i32; 3]; scope 1 { debug a => _1; + let _5: i32; scope 2 { - let _5: i32; - scope 3 { - debug _b => _5; - } + debug _b => _5; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff index f1b90c28e72f..0e2ec65652f5 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff @@ -13,11 +13,9 @@ let mut _9: &[i32; 3]; scope 1 { debug a => _1; + let _5: i32; scope 2 { - let _5: i32; - scope 3 { - debug _b => _5; - } + debug _b => _5; } } diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff index 59ee38f5a2b9..a408c197fd14 100644 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff @@ -15,8 +15,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff index 9d87bd809d1f..5706a739602e 100644 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff @@ -15,8 +15,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff index b389080c4977..99a6ba7d08ab 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff +++ b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff @@ -11,8 +11,6 @@ debug v => _1; let _4: bool; scope 2 { - } - scope 3 { debug y => _4; } } diff --git a/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff b/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff index da5bf1cf42ca..f50413656049 100644 --- a/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff +++ b/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff @@ -12,23 +12,17 @@ scope 1 { debug _invalid_char => _1; let _3: [E; 1]; - scope 3 { + scope 2 { debug _invalid_tag => _3; let _6: [Empty; 1]; - scope 5 { + scope 3 { debug _enum_without_variants => const [ZeroSized: Empty]; let _9: main::Str<"���">; - scope 7 { + scope 4 { debug _non_utf8_str => const Str::<"���">; } } - scope 6 { - } } - scope 4 { - } - } - scope 2 { } bb0: { diff --git a/tests/mir-opt/const_prop/invalid_constant.main.RemoveZsts.diff b/tests/mir-opt/const_prop/invalid_constant.main.RemoveZsts.diff index 455c2375eff9..6e5ad8d6b81a 100644 --- a/tests/mir-opt/const_prop/invalid_constant.main.RemoveZsts.diff +++ b/tests/mir-opt/const_prop/invalid_constant.main.RemoveZsts.diff @@ -12,25 +12,19 @@ scope 1 { debug _invalid_char => _1; let _3: [E; 1]; - scope 3 { + scope 2 { debug _invalid_tag => _3; let _6: [Empty; 1]; - scope 5 { + scope 3 { - debug _enum_without_variants => _6; + debug _enum_without_variants => const [ZeroSized: Empty]; let _9: main::Str<"���">; - scope 7 { + scope 4 { - debug _non_utf8_str => _9; + debug _non_utf8_str => const Str::<"���">; } } - scope 6 { - } } - scope 4 { - } - } - scope 2 { } bb0: { diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff index e113f43a56e9..31c839f67490 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff @@ -11,8 +11,6 @@ debug x => _1; let _5: u32; scope 2 { - } - scope 3 { debug y => _5; } } diff --git a/tests/mir-opt/const_prop/transmute.from_char.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.from_char.GVN.32bit.diff index 47dfb421ebc8..2b38e88ae4c7 100644 --- a/tests/mir-opt/const_prop/transmute.from_char.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.from_char.GVN.32bit.diff @@ -3,8 +3,6 @@ fn from_char() -> i32 { let mut _0: i32; - scope 1 { - } bb0: { - _0 = const 'R' as i32 (Transmute); diff --git a/tests/mir-opt/const_prop/transmute.from_char.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.from_char.GVN.64bit.diff index 47dfb421ebc8..2b38e88ae4c7 100644 --- a/tests/mir-opt/const_prop/transmute.from_char.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.from_char.GVN.64bit.diff @@ -3,8 +3,6 @@ fn from_char() -> i32 { let mut _0: i32; - scope 1 { - } bb0: { - _0 = const 'R' as i32 (Transmute); diff --git a/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.32bit.diff index f0c6f55f775f..45c48e9046ec 100644 --- a/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.32bit.diff @@ -3,8 +3,6 @@ fn invalid_bool() -> bool { let mut _0: bool; - scope 1 { - } bb0: { - _0 = const -1_i8 as bool (Transmute); diff --git a/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.64bit.diff index f0c6f55f775f..45c48e9046ec 100644 --- a/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.64bit.diff @@ -3,8 +3,6 @@ fn invalid_bool() -> bool { let mut _0: bool; - scope 1 { - } bb0: { - _0 = const -1_i8 as bool (Transmute); diff --git a/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff index 03a7706401f2..b4fe64d0aff3 100644 --- a/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff @@ -3,8 +3,6 @@ fn invalid_char() -> char { let mut _0: char; - scope 1 { - } bb0: { - _0 = const core::num::::MAX as char (Transmute); diff --git a/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff index 03a7706401f2..b4fe64d0aff3 100644 --- a/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff @@ -3,8 +3,6 @@ fn invalid_char() -> char { let mut _0: char; - scope 1 { - } bb0: { - _0 = const core::num::::MAX as char (Transmute); diff --git a/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.32bit.diff index 5e0c076b9819..ab3481a3be5a 100644 --- a/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.32bit.diff @@ -4,8 +4,6 @@ fn less_as_i8() -> i8 { let mut _0: i8; let mut _1: std::cmp::Ordering; - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.64bit.diff index 5e0c076b9819..ab3481a3be5a 100644 --- a/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.64bit.diff @@ -4,8 +4,6 @@ fn less_as_i8() -> i8 { let mut _0: i8; let mut _1: std::cmp::Ordering; - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff index c6a428019d81..febb6bfb0a43 100644 --- a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff @@ -5,8 +5,6 @@ let mut _0: u32; let mut _1: undef_union_as_integer::Union32; let mut _2: (); - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff index c6a428019d81..febb6bfb0a43 100644 --- a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff @@ -5,8 +5,6 @@ let mut _0: u32; let mut _1: undef_union_as_integer::Union32; let mut _2: (); - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff index 2ef83abfac0a..7a289563c506 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff index 2ef83abfac0a..7a289563c506 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff index b2e91014625c..3364782022dc 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff index b2e91014625c..3364782022dc 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff index 0ff31b1a9818..a70207932378 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff index 0ff31b1a9818..a70207932378 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.32bit.diff index 430d16c97a6c..d44b08720356 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.32bit.diff @@ -7,8 +7,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.64bit.diff index 430d16c97a6c..d44b08720356 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.64bit.diff @@ -7,8 +7,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/const_prop/transmute.valid_char.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.valid_char.GVN.32bit.diff index f9d002f96ab0..069ff906ec59 100644 --- a/tests/mir-opt/const_prop/transmute.valid_char.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.valid_char.GVN.32bit.diff @@ -3,8 +3,6 @@ fn valid_char() -> char { let mut _0: char; - scope 1 { - } bb0: { - _0 = const 82_u32 as char (Transmute); diff --git a/tests/mir-opt/const_prop/transmute.valid_char.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.valid_char.GVN.64bit.diff index f9d002f96ab0..069ff906ec59 100644 --- a/tests/mir-opt/const_prop/transmute.valid_char.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.valid_char.GVN.64bit.diff @@ -3,8 +3,6 @@ fn valid_char() -> char { let mut _0: char; - scope 1 { - } bb0: { - _0 = const 82_u32 as char (Transmute); diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff index ffb0c4b23fb2..ef30ac2fc8c0 100644 --- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff @@ -14,13 +14,11 @@ scope 2 { debug b => _3; let _5: *mut u8; - scope 4 { + scope 3 { - debug c => _5; + debug c => _2; } } - scope 3 { - } } bb0: { diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff index 66a0f49cfb9d..a743a3e829a7 100644 --- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff @@ -14,13 +14,11 @@ scope 2 { debug b => _3; let _5: *mut u8; - scope 4 { + scope 3 { - debug c => _5; + debug c => _2; } } - scope 3 { - } } bb0: { diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff index 0777a9135235..2de6f85ce64b 100644 --- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff @@ -13,13 +13,11 @@ scope 2 { debug b => _3; let _4: *mut u8; - scope 4 { + scope 3 { - debug c => _4; + debug c => _2; } } - scope 3 { - } } bb0: { diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff index f5a512b89955..2afec4898bc8 100644 --- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff @@ -13,13 +13,11 @@ scope 2 { debug b => _3; let _4: *mut u8; - scope 4 { + scope 3 { - debug c => _4; + debug c => _2; } } - scope 3 { - } } bb0: { diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 21cf745b680a..44e73b560982 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -17,33 +17,27 @@ scope 4 (inlined Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let _6: *mut [bool; 0]; scope 6 { - let _6: *mut [bool; 0]; - scope 7 { + debug ptr => _6; + scope 10 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - scope 12 (inlined NonNull::<[bool; 0]>::new_unchecked) { - debug ptr => _6; - let mut _8: bool; - let _9: (); - let mut _10: *mut (); - let mut _11: *const [bool; 0]; - scope 13 { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 8 (inlined dangling_mut::<[bool; 0]>) { - let mut _7: usize; - scope 9 (inlined align_of::<[bool; 0]>) { - } - scope 10 (inlined without_provenance_mut::<[bool; 0]>) { - debug addr => _7; - scope 11 { - } - } + } + scope 7 (inlined dangling_mut::<[bool; 0]>) { + let mut _7: usize; + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined without_provenance_mut::<[bool; 0]>) { + debug addr => _7; } } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index ee58a9744805..6cef8b692ba7 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -17,33 +17,27 @@ scope 4 (inlined Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let _6: *mut [bool; 0]; scope 6 { - let _6: *mut [bool; 0]; - scope 7 { + debug ptr => _6; + scope 10 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - scope 12 (inlined NonNull::<[bool; 0]>::new_unchecked) { - debug ptr => _6; - let mut _8: bool; - let _9: (); - let mut _10: *mut (); - let mut _11: *const [bool; 0]; - scope 13 { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 8 (inlined dangling_mut::<[bool; 0]>) { - let mut _7: usize; - scope 9 (inlined align_of::<[bool; 0]>) { - } - scope 10 (inlined without_provenance_mut::<[bool; 0]>) { - debug addr => _7; - scope 11 { - } - } + } + scope 7 (inlined dangling_mut::<[bool; 0]>) { + let mut _7: usize; + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined without_provenance_mut::<[bool; 0]>) { + debug addr => _7; } } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 9fc9c8ed409c..6efccded9939 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -17,33 +17,27 @@ scope 4 (inlined Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let _6: *mut [bool; 0]; scope 6 { - let _6: *mut [bool; 0]; - scope 7 { + debug ptr => _6; + scope 10 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - scope 12 (inlined NonNull::<[bool; 0]>::new_unchecked) { - debug ptr => _6; - let mut _8: bool; - let _9: (); - let mut _10: *mut (); - let mut _11: *const [bool; 0]; - scope 13 { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 8 (inlined dangling_mut::<[bool; 0]>) { - let mut _7: usize; - scope 9 (inlined align_of::<[bool; 0]>) { - } - scope 10 (inlined without_provenance_mut::<[bool; 0]>) { - debug addr => _7; - scope 11 { - } - } + } + scope 7 (inlined dangling_mut::<[bool; 0]>) { + let mut _7: usize; + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined without_provenance_mut::<[bool; 0]>) { + debug addr => _7; } } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 30d93347afdc..a705d0064cba 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -17,33 +17,27 @@ scope 4 (inlined Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let _6: *mut [bool; 0]; scope 6 { - let _6: *mut [bool; 0]; - scope 7 { + debug ptr => _6; + scope 10 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - scope 12 (inlined NonNull::<[bool; 0]>::new_unchecked) { - debug ptr => _6; - let mut _8: bool; - let _9: (); - let mut _10: *mut (); - let mut _11: *const [bool; 0]; - scope 13 { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 8 (inlined dangling_mut::<[bool; 0]>) { - let mut _7: usize; - scope 9 (inlined align_of::<[bool; 0]>) { - } - scope 10 (inlined without_provenance_mut::<[bool; 0]>) { - debug addr => _7; - scope 11 { - } - } + } + scope 7 (inlined dangling_mut::<[bool; 0]>) { + let mut _7: usize; + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined without_provenance_mut::<[bool; 0]>) { + debug addr => _7; } } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 3a46edbc8496..f9c854ca3f47 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -17,33 +17,27 @@ scope 4 (inlined Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let _6: *mut [bool; 0]; scope 6 { - let _6: *mut [bool; 0]; - scope 7 { + debug ptr => _6; + scope 10 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - scope 12 (inlined NonNull::<[bool; 0]>::new_unchecked) { - debug ptr => _6; - let mut _8: bool; - let _9: (); - let mut _10: *mut (); - let mut _11: *const [bool; 0]; - scope 13 { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 8 (inlined dangling_mut::<[bool; 0]>) { - let mut _7: usize; - scope 9 (inlined align_of::<[bool; 0]>) { - } - scope 10 (inlined without_provenance_mut::<[bool; 0]>) { - debug addr => _7; - scope 11 { - } - } + } + scope 7 (inlined dangling_mut::<[bool; 0]>) { + let mut _7: usize; + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined without_provenance_mut::<[bool; 0]>) { + debug addr => _7; } } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index 3c71214c35ff..333726689d7a 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -17,33 +17,27 @@ scope 4 (inlined Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let _6: *mut [bool; 0]; scope 6 { - let _6: *mut [bool; 0]; - scope 7 { + debug ptr => _6; + scope 10 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - scope 12 (inlined NonNull::<[bool; 0]>::new_unchecked) { - debug ptr => _6; - let mut _8: bool; - let _9: (); - let mut _10: *mut (); - let mut _11: *const [bool; 0]; - scope 13 { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 8 (inlined dangling_mut::<[bool; 0]>) { - let mut _7: usize; - scope 9 (inlined align_of::<[bool; 0]>) { - } - scope 10 (inlined without_provenance_mut::<[bool; 0]>) { - debug addr => _7; - scope 11 { - } - } + } + scope 7 (inlined dangling_mut::<[bool; 0]>) { + let mut _7: usize; + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined without_provenance_mut::<[bool; 0]>) { + debug addr => _7; } } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index 4557e7b26d61..e1841760077d 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -17,33 +17,27 @@ scope 4 (inlined Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let _6: *mut [bool; 0]; scope 6 { - let _6: *mut [bool; 0]; - scope 7 { + debug ptr => _6; + scope 10 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - scope 12 (inlined NonNull::<[bool; 0]>::new_unchecked) { - debug ptr => _6; - let mut _8: bool; - let _9: (); - let mut _10: *mut (); - let mut _11: *const [bool; 0]; - scope 13 { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 8 (inlined dangling_mut::<[bool; 0]>) { - let mut _7: usize; - scope 9 (inlined align_of::<[bool; 0]>) { - } - scope 10 (inlined without_provenance_mut::<[bool; 0]>) { - debug addr => _7; - scope 11 { - } - } + } + scope 7 (inlined dangling_mut::<[bool; 0]>) { + let mut _7: usize; + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined without_provenance_mut::<[bool; 0]>) { + debug addr => _7; } } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index 5ab2d5e0fdc0..7aa02556ec5e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -17,33 +17,27 @@ scope 4 (inlined Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { + let _6: *mut [bool; 0]; scope 6 { - let _6: *mut [bool; 0]; - scope 7 { + debug ptr => _6; + scope 10 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - scope 12 (inlined NonNull::<[bool; 0]>::new_unchecked) { - debug ptr => _6; - let mut _8: bool; - let _9: (); - let mut _10: *mut (); - let mut _11: *const [bool; 0]; - scope 13 { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { } } } - scope 8 (inlined dangling_mut::<[bool; 0]>) { - let mut _7: usize; - scope 9 (inlined align_of::<[bool; 0]>) { - } - scope 10 (inlined without_provenance_mut::<[bool; 0]>) { - debug addr => _7; - scope 11 { - } - } + } + scope 7 (inlined dangling_mut::<[bool; 0]>) { + let mut _7: usize; + scope 8 (inlined align_of::<[bool; 0]>) { + } + scope 9 (inlined without_provenance_mut::<[bool; 0]>) { + debug addr => _7; } } } diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff index 9b0093c454e1..a5e409907510 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff @@ -9,14 +9,12 @@ let mut _5: *mut u8; scope 1 { debug x => _1; + let _3: *mut u8; let _6: u8; scope 2 { - let _3: *mut u8; - scope 3 { - debug p => _3; - } + debug p => _3; } - scope 4 { + scope 3 { debug x1 => _6; } } diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff index 635a214251bc..ce2178ddbee6 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff @@ -9,14 +9,12 @@ let mut _5: *mut u8; scope 1 { debug x => _1; + let _3: *mut u8; let _6: u8; scope 2 { - let _3: *mut u8; - scope 3 { - debug p => _3; - } + debug p => _3; } - scope 4 { + scope 3 { debug x1 => _6; } } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.32bit.diff index 52f096ac0e4e..a5529253762c 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.32bit.diff @@ -3,8 +3,6 @@ fn from_char() -> i32 { let mut _0: i32; - scope 1 { - } bb0: { - _0 = const 'R' as i32 (Transmute); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.64bit.diff index 52f096ac0e4e..a5529253762c 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.from_char.DataflowConstProp.64bit.diff @@ -3,8 +3,6 @@ fn from_char() -> i32 { let mut _0: i32; - scope 1 { - } bb0: { - _0 = const 'R' as i32 (Transmute); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.32bit.diff index 3972eb209a16..a66d8dbe8443 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.32bit.diff @@ -3,8 +3,6 @@ fn invalid_bool() -> bool { let mut _0: bool; - scope 1 { - } bb0: { - _0 = const -1_i8 as bool (Transmute); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.64bit.diff index 3972eb209a16..a66d8dbe8443 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_bool.DataflowConstProp.64bit.diff @@ -3,8 +3,6 @@ fn invalid_bool() -> bool { let mut _0: bool; - scope 1 { - } bb0: { - _0 = const -1_i8 as bool (Transmute); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff index dd737017ffd5..4f3f3e03d758 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff @@ -3,8 +3,6 @@ fn invalid_char() -> char { let mut _0: char; - scope 1 { - } bb0: { - _0 = const core::num::::MAX as char (Transmute); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff index dd737017ffd5..4f3f3e03d758 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff @@ -3,8 +3,6 @@ fn invalid_char() -> char { let mut _0: char; - scope 1 { - } bb0: { - _0 = const core::num::::MAX as char (Transmute); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.32bit.diff index 6091e169e8eb..44dd40174092 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.32bit.diff @@ -4,8 +4,6 @@ fn less_as_i8() -> i8 { let mut _0: i8; let mut _1: std::cmp::Ordering; - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.64bit.diff index 6091e169e8eb..44dd40174092 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.less_as_i8.DataflowConstProp.64bit.diff @@ -4,8 +4,6 @@ fn less_as_i8() -> i8 { let mut _0: i8; let mut _1: std::cmp::Ordering; - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff index fb28aa8f6d9c..14a34a1ce38b 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff @@ -5,8 +5,6 @@ let mut _0: u32; let mut _1: undef_union_as_integer::Union32; let mut _2: (); - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff index fb28aa8f6d9c..14a34a1ce38b 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff @@ -5,8 +5,6 @@ let mut _0: u32; let mut _1: undef_union_as_integer::Union32; let mut _2: (); - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff index 5d17c47ae666..258e2b454ebe 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff index 5d17c47ae666..258e2b454ebe 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff index c8d4d6edba1e..a0b4fb2f5e44 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff index c8d4d6edba1e..a0b4fb2f5e44 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.32bit.diff index 2ffaeea72db2..ef461423c328 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.32bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.64bit.diff index 2ffaeea72db2..ef461423c328 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_mut.DataflowConstProp.64bit.diff @@ -8,8 +8,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.32bit.diff index 31fcaafc5bca..c8910029a03f 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.32bit.diff @@ -7,8 +7,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.64bit.diff index 31fcaafc5bca..c8910029a03f 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_ref.DataflowConstProp.64bit.diff @@ -7,8 +7,6 @@ scope 1 { debug x => _1; } - scope 2 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.32bit.diff index 402ef754a648..580c5044bb82 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.32bit.diff @@ -3,8 +3,6 @@ fn valid_char() -> char { let mut _0: char; - scope 1 { - } bb0: { - _0 = const 82_u32 as char (Transmute); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.64bit.diff index 402ef754a648..580c5044bb82 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.valid_char.DataflowConstProp.64bit.diff @@ -3,8 +3,6 @@ fn valid_char() -> char { let mut _0: char; - scope 1 { - } bb0: { - _0 = const 82_u32 as char (Transmute); diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index 0af3faf28f07..570ec129f06e 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -8,13 +8,11 @@ let mut _3: u32; scope 1 { debug un => _1; - scope 2 { - } - scope 4 (inlined std::mem::drop::) { + scope 3 (inlined std::mem::drop::) { debug _x => _3; } } - scope 3 (inlined val) { + scope 2 (inlined val) { } bb0: { diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index 0af3faf28f07..570ec129f06e 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -8,13 +8,11 @@ let mut _3: u32; scope 1 { debug un => _1; - scope 2 { - } - scope 4 (inlined std::mem::drop::) { + scope 3 (inlined std::mem::drop::) { debug _x => _3; } } - scope 3 (inlined val) { + scope 2 (inlined val) { } bb0: { diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff index 46bf13985daf..906835530d86 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff @@ -37,17 +37,9 @@ debug z => _8; let _13: *mut u32; scope 2 { - } - scope 3 { - } - scope 4 { debug z => _13; let _18: &u32; - scope 5 { - } - scope 6 { - } - scope 7 { + scope 3 { debug z => _18; } } diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff index 3e731ead859e..006b5da646c1 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff @@ -37,17 +37,9 @@ debug z => _8; let _13: *mut u32; scope 2 { - } - scope 3 { - } - scope 4 { debug z => _13; let _18: &u32; - scope 5 { - } - scope 6 { - } - scope 7 { + scope 3 { debug z => _18; } } diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff index f3f9073909e3..2389d98b5b3c 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -69,17 +69,15 @@ debug u => _29; let _41: &*const u8; let _42: &*const u8; - scope 7 { + scope 6 { debug left_val => _41; debug right_val => _42; let _47: core::panicking::AssertKind; - scope 8 { + scope 7 { debug kind => _47; } } } - scope 6 { - } } } diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff index 383152cce5e2..50715d748e79 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -69,17 +69,15 @@ debug u => _29; let _41: &*const u8; let _42: &*const u8; - scope 7 { + scope 6 { debug left_val => _41; debug right_val => _42; let _47: core::panicking::AssertKind; - scope 8 { + scope 7 { debug kind => _47; } } } - scope 6 { - } } } diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff index 3ecd4650d810..ba9e507560d6 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -175,18 +175,16 @@ let _135: &mut u64; scope 2 { debug b => _135; + let _145: *const u64; let _163: &u64; scope 3 { - let _145: *const u64; + debug c => _145; + let _154: *mut u64; scope 4 { - debug c => _145; - let _154: *mut u64; - scope 5 { - debug d => _154; - } + debug d => _154; } } - scope 6 { + scope 5 { debug e => _163; } } diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff index bf448280b1ed..41c015361301 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -175,18 +175,16 @@ let _135: &mut u64; scope 2 { debug b => _135; + let _145: *const u64; let _163: &u64; scope 3 { - let _145: *const u64; + debug c => _145; + let _154: *mut u64; scope 4 { - debug c => _145; - let _154: *mut u64; - scope 5 { - debug d => _154; - } + debug d => _154; } } - scope 6 { + scope 5 { debug e => _163; } } diff --git a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff index 11cd43fc0e07..07c4c7663c15 100644 --- a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-abort.diff @@ -33,13 +33,9 @@ scope 1 { debug a => _1; let _3: *const [u8]; - scope 3 { + scope 2 { debug b => _3; } - scope 4 { - } - } - scope 2 { } bb0: { diff --git a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff index c77cd07c60c7..df0f93f1077e 100644 --- a/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.wide_ptr_integer.GVN.panic-unwind.diff @@ -33,13 +33,9 @@ scope 1 { debug a => _1; let _3: *const [u8]; - scope 3 { + scope 2 { debug b => _3; } - scope 4 { - } - } - scope 2 { } bb0: { diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff index 86e6aae11911..c5ee0d9c44d7 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff @@ -7,12 +7,10 @@ let mut _2: E; let mut _3: &U; let _4: U; + let mut _5: &U; scope 1 { debug i => _1; } - scope 2 { - let mut _5: &U; - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff index 86e6aae11911..c5ee0d9c44d7 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff @@ -7,12 +7,10 @@ let mut _2: E; let mut _3: &U; let _4: U; + let mut _5: &U; scope 1 { debug i => _1; } - scope 2 { - let mut _5: &U; - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff index ea9c360aa7b3..dc0004105a7b 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff @@ -8,8 +8,6 @@ + let _2: D; + scope 2 { + debug _d => const D; -+ scope 3 { -+ } + } + } diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index a38b8246bdef..859082c31119 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -15,13 +15,11 @@ + } + scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) { + debug pointer => _3; -+ scope 4 { -+ scope 5 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) { -+ debug pointer => _3; -+ } ++ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) { ++ debug pointer => _3; + } + } -+ scope 6 (inlined g::{closure#0}) { ++ scope 5 (inlined g::{closure#0}) { + debug a => _5; + let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; + let mut _7: u32; diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index dc6628ab44c5..44b06c34972a 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -15,13 +15,11 @@ + } + scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) { + debug pointer => _3; -+ scope 4 { -+ scope 5 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) { -+ debug pointer => _3; -+ } ++ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) { ++ debug pointer => _3; + } + } -+ scope 6 (inlined g::{closure#0}) { ++ scope 5 (inlined g::{closure#0}) { + debug a => _5; + let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; + let mut _7: u32; diff --git a/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff index e38daba27fc1..158cc973779c 100644 --- a/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff +++ b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff @@ -10,8 +10,6 @@ + scope 1 (inlined instruction_set_default) { + } + scope 2 (inlined inline_always_and_using_inline_asm) { -+ scope 3 { -+ } + } bb0: { diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff index 4fcd49994f0d..2a36ccaab110 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff @@ -8,18 +8,14 @@ let _3: (); let mut _4: *mut std::vec::Vec; let mut _5: *mut std::option::Option; - scope 1 { -+ scope 3 (inlined std::ptr::drop_in_place::> - shim(Some(Vec))) { -+ let mut _6: &mut std::vec::Vec; -+ let mut _7: (); -+ } - } - scope 2 { -+ scope 4 (inlined std::ptr::drop_in_place::> - shim(Some(Option))) { -+ let mut _8: isize; -+ let mut _9: isize; -+ } - } ++ scope 1 (inlined std::ptr::drop_in_place::> - shim(Some(Vec))) { ++ let mut _6: &mut std::vec::Vec; ++ let mut _7: (); ++ } ++ scope 2 (inlined std::ptr::drop_in_place::> - shim(Some(Option))) { ++ let mut _8: isize; ++ let mut _9: isize; ++ } bb0: { StorageLive(_3); diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff index 4270ae00b668..e11561076e64 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff @@ -8,14 +8,10 @@ let _3: (); let mut _4: *mut std::vec::Vec; let mut _5: *mut std::option::Option; - scope 1 { - } - scope 2 { -+ scope 3 (inlined std::ptr::drop_in_place::> - shim(Some(Option))) { -+ let mut _6: isize; -+ let mut _7: isize; -+ } - } ++ scope 1 (inlined std::ptr::drop_in_place::> - shim(Some(Option))) { ++ let mut _6: isize; ++ let mut _7: isize; ++ } bb0: { StorageLive(_3); diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff index 51e506142a9c..cc1b8b9b70f5 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff @@ -10,8 +10,6 @@ + scope 1 (inlined core::num::::unchecked_shl) { + debug self => _3; + debug rhs => _4; -+ scope 2 { -+ } + } bb0: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff index 053ccc077a4c..f244f378bce3 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff @@ -10,8 +10,6 @@ + scope 1 (inlined core::num::::unchecked_shl) { + debug self => _3; + debug rhs => _4; -+ scope 2 { -+ } + } bb0: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir index 2be887e9b5a3..c96983c18cb6 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir @@ -7,8 +7,6 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { scope 1 (inlined core::num::::unchecked_shl) { debug self => _1; debug rhs => _2; - scope 2 { - } } bb0: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir index 2be887e9b5a3..c96983c18cb6 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir @@ -7,8 +7,6 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { scope 1 (inlined core::num::::unchecked_shl) { debug self => _1; debug rhs => _2; - scope 2 { - } } bb0: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff index 816d03b44052..74518db370f1 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff @@ -10,8 +10,6 @@ + scope 1 (inlined core::num::::unchecked_shr) { + debug self => _3; + debug rhs => _4; -+ scope 2 { -+ } + } bb0: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff index d4121f89bafb..aab04624f6cd 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff @@ -10,8 +10,6 @@ + scope 1 (inlined core::num::::unchecked_shr) { + debug self => _3; + debug rhs => _4; -+ scope 2 { -+ } + } bb0: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir index 4696112175e6..1dd8cb273143 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir @@ -7,8 +7,6 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 { scope 1 (inlined core::num::::unchecked_shr) { debug self => _1; debug rhs => _2; - scope 2 { - } } bb0: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir index 4696112175e6..1dd8cb273143 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir @@ -7,8 +7,6 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 { scope 1 (inlined core::num::::unchecked_shr) { debug self => _1; debug rhs => _2; - scope 2 { - } } bb0: { diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index 028040edc856..814eda104597 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -11,15 +11,11 @@ + scope 2 { + debug val => _0; + } -+ scope 3 { -+ scope 4 (inlined unreachable_unchecked) { -+ let mut _4: bool; -+ let _5: (); -+ scope 5 { -+ } -+ scope 6 (inlined core::ub_checks::check_language_ub) { -+ scope 7 (inlined core::ub_checks::check_language_ub::runtime) { -+ } ++ scope 3 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 4 (inlined core::ub_checks::check_language_ub) { ++ scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index 484fd37248c6..d5d690743826 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -11,15 +11,11 @@ + scope 2 { + debug val => _0; + } -+ scope 3 { -+ scope 4 (inlined unreachable_unchecked) { -+ let mut _4: bool; -+ let _5: (); -+ scope 5 { -+ } -+ scope 6 (inlined core::ub_checks::check_language_ub) { -+ scope 7 (inlined core::ub_checks::check_language_ub::runtime) { -+ } ++ scope 3 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 4 (inlined core::ub_checks::check_language_ub) { ++ scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index d629336d3859..7c24a97166c1 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -9,13 +9,9 @@ fn unwrap_unchecked(_1: Option) -> T { scope 2 { debug val => _0; } - scope 3 { - scope 4 (inlined unreachable_unchecked) { - scope 5 { - } - scope 6 (inlined core::ub_checks::check_language_ub) { - scope 7 (inlined core::ub_checks::check_language_ub::runtime) { - } + scope 3 (inlined unreachable_unchecked) { + scope 4 (inlined core::ub_checks::check_language_ub) { + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { } } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index d629336d3859..7c24a97166c1 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -9,13 +9,9 @@ fn unwrap_unchecked(_1: Option) -> T { scope 2 { debug val => _0; } - scope 3 { - scope 4 (inlined unreachable_unchecked) { - scope 5 { - } - scope 6 (inlined core::ub_checks::check_language_ub) { - scope 7 (inlined core::ub_checks::check_language_ub::runtime) { - } + scope 3 (inlined unreachable_unchecked) { + scope 4 (inlined core::ub_checks::check_language_ub) { + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { } } } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 0243e31cb1ac..f8cceacd7e69 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -18,9 +18,9 @@ let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; scope 2 { debug fut => _4; - scope 4 { + scope 3 { } -+ scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) { ++ scope 6 (inlined ActionPermit::<'_, T>::perform::{closure#0}) { + debug _task_context => _31; + debug self => ((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})).0: ActionPermit<'_, T>); + let _11: ActionPermit<'_, T>; @@ -51,32 +51,28 @@ + let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()}; + let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()}; + let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()}; -+ scope 8 { ++ scope 7 { + debug self => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).0: ActionPermit<'_, T>); + let mut _15: std::future::Ready<()>; -+ scope 9 { ++ scope 8 { + debug __awaitee => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).1: std::future::Ready<()>); + let _26: (); -+ scope 10 { -+ } -+ scope 11 { ++ scope 9 { + debug result => _26; + } + } -+ scope 12 (inlined ready::<()>) { ++ scope 10 (inlined ready::<()>) { + debug t => _14; + let mut _41: std::option::Option<()>; + } + } + } } - scope 3 { -+ scope 6 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) { -+ debug pointer => _5; -+ } - } ++ scope 5 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) { ++ debug pointer => _5; ++ } } -+ scope 5 (inlined ActionPermit::<'_, T>::perform) { ++ scope 4 (inlined ActionPermit::<'_, T>::perform) { + debug self => _3; + } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 96a93cdda3df..fd080d22d3ad 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -18,9 +18,9 @@ let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; scope 2 { debug fut => _4; - scope 4 { + scope 3 { } -+ scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) { ++ scope 6 (inlined ActionPermit::<'_, T>::perform::{closure#0}) { + debug _task_context => _31; + debug self => ((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})).0: ActionPermit<'_, T>); + let _11: ActionPermit<'_, T>; @@ -53,32 +53,28 @@ + let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()}; + let mut _41: &mut {async fn body of ActionPermit<'_, T>::perform()}; + let mut _42: &mut {async fn body of ActionPermit<'_, T>::perform()}; -+ scope 8 { ++ scope 7 { + debug self => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).0: ActionPermit<'_, T>); + let mut _15: std::future::Ready<()>; -+ scope 9 { ++ scope 8 { + debug __awaitee => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).1: std::future::Ready<()>); + let _26: (); -+ scope 10 { -+ } -+ scope 11 { ++ scope 9 { + debug result => _26; + } + } -+ scope 12 (inlined ready::<()>) { ++ scope 10 (inlined ready::<()>) { + debug t => _14; + let mut _43: std::option::Option<()>; + } + } + } } - scope 3 { -+ scope 6 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) { -+ debug pointer => _5; -+ } - } ++ scope 5 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) { ++ debug pointer => _5; ++ } } -+ scope 5 (inlined ActionPermit::<'_, T>::perform) { ++ scope 4 (inlined ActionPermit::<'_, T>::perform) { + debug self => _3; + } diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff index f3402fde05b9..6d6c9c9a7a16 100644 --- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff +++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff @@ -5,23 +5,17 @@ debug x => _1; let mut _0: i32; let mut _2: std::option::Option; - scope 1 { - scope 2 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _2; - let mut _3: isize; - scope 3 { - debug val => _0; - } - scope 4 { - scope 5 (inlined unreachable_unchecked) { - let mut _4: bool; - let _5: (); - scope 6 { - } - scope 7 (inlined core::ub_checks::check_language_ub) { - scope 8 (inlined core::ub_checks::check_language_ub::runtime) { - } - } + scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { + debug self => _2; + let mut _3: isize; + scope 2 { + debug val => _0; + } + scope 3 (inlined unreachable_unchecked) { + let mut _4: bool; + let _5: (); + scope 4 (inlined core::ub_checks::check_language_ub) { + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { } } } diff --git a/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-abort.mir b/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-abort.mir index b4f212409398..53912adc0031 100644 --- a/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-abort.mir +++ b/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-abort.mir @@ -4,8 +4,6 @@ fn main() -> () { let mut _0: (); let mut _1: !; let mut _2: (); - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-unwind.mir b/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-unwind.mir index 1851747f0a62..50416300094f 100644 --- a/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-unwind.mir +++ b/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-unwind.mir @@ -4,8 +4,6 @@ fn main() -> () { let mut _0: (); let mut _1: !; let mut _2: (); - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir index 91dee82fde06..3104baa5fdbd 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir @@ -15,15 +15,13 @@ fn test() -> Option> { let mut _11: std::option::Option; let _12: u32; scope 1 { - } - scope 2 { debug residual => _9; - scope 3 { + scope 2 { } } - scope 4 { + scope 3 { debug val => _12; - scope 5 { + scope 4 { } } diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir index ff7fc74ff61f..da33c8301151 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir @@ -15,15 +15,13 @@ fn test() -> Option> { let mut _11: std::option::Option; let _12: u32; scope 1 { - } - scope 2 { debug residual => _9; - scope 3 { + scope 2 { } } - scope 4 { + scope 3 { debug val => _12; - scope 5 { + scope 4 { } } diff --git a/tests/mir-opt/issue_72181.main.built.after.mir b/tests/mir-opt/issue_72181.main.built.after.mir index cff20702bf7c..fa101512d729 100644 --- a/tests/mir-opt/issue_72181.main.built.after.mir +++ b/tests/mir-opt/issue_72181.main.built.after.mir @@ -15,8 +15,6 @@ fn main() -> () { debug f => _2; scope 3 { } - scope 4 { - } } } diff --git a/tests/mir-opt/issue_72181_1.main.built.after.mir b/tests/mir-opt/issue_72181_1.main.built.after.mir index d35aada95f88..ae0dc9a0b6a2 100644 --- a/tests/mir-opt/issue_72181_1.main.built.after.mir +++ b/tests/mir-opt/issue_72181_1.main.built.after.mir @@ -14,8 +14,6 @@ fn main() -> () { scope 1 { debug v => _2; } - scope 2 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index f11c993340fd..25ed1b4d0c76 100644 --- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -10,15 +10,11 @@ let mut _6: u32; scope 1 { debug dwords => _2; - scope 3 { + scope 2 { debug ip => _4; let _4: u32; - scope 4 { - } } } - scope 2 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-abort.diff index 80a422636431..e9d4352014f7 100644 --- a/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-abort.diff @@ -12,8 +12,6 @@ let _2: *mut i32; scope 2 { debug a => _2; - scope 3 { - } } } diff --git a/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-unwind.diff index 80a422636431..e9d4352014f7 100644 --- a/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.mutable_ref.JumpThreading.panic-unwind.diff @@ -12,8 +12,6 @@ let _2: *mut i32; scope 2 { debug a => _2; - scope 3 { - } } } diff --git a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-abort.diff index f9f73bf991d1..633a344a2edb 100644 --- a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-abort.diff @@ -14,8 +14,6 @@ let _5: *const [u8]; scope 2 { debug arr => _5; - scope 3 { - } } } diff --git a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-unwind.diff index f9f73bf991d1..633a344a2edb 100644 --- a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.panic-unwind.diff @@ -14,8 +14,6 @@ let _5: *const [u8]; scope 2 { debug arr => _5; - scope 3 { - } } } diff --git a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.panic-abort.diff index 79635f23e8eb..6c1f457cb5f5 100644 --- a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.panic-abort.diff @@ -4,8 +4,6 @@ fn assume() -> () { let mut _0: (); let _1: (); - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.panic-unwind.diff index 79635f23e8eb..6c1f457cb5f5 100644 --- a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.panic-unwind.diff @@ -4,8 +4,6 @@ fn assume() -> () { let mut _0: (); let _1: (); - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff index 6de5f2c4f074..96b66af66a2d 100644 --- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff @@ -18,8 +18,6 @@ let mut _2: (); scope 2 { debug dst => _2; - scope 3 { - } } } diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff index 6de5f2c4f074..96b66af66a2d 100644 --- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff @@ -18,8 +18,6 @@ let mut _2: (); scope 2 { debug dst => _2; - scope 3 { - } } } diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-abort.diff index 147c48a3c01d..781104be290a 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-abort.diff @@ -5,8 +5,6 @@ debug r => _1; let mut _0: i32; let mut _2: *const i32; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-unwind.diff index 147c48a3c01d..781104be290a 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.panic-unwind.diff @@ -5,8 +5,6 @@ debug r => _1; let mut _0: i32; let mut _2: *const i32; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-abort.diff index b2cf3cc1ccac..56c357b3776d 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-abort.diff @@ -5,8 +5,6 @@ debug r => _1; let mut _0: Never; let mut _2: *const Never; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-unwind.diff index b2cf3cc1ccac..56c357b3776d 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -5,8 +5,6 @@ debug r => _1; let mut _0: Never; let mut _2: *const Never; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff index 3b4051e4ae2d..6e542c4b5a7b 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff @@ -5,8 +5,6 @@ debug c => _1; let mut _0: i8; let mut _2: std::cmp::Ordering; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff index 3b4051e4ae2d..6e542c4b5a7b 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff @@ -5,8 +5,6 @@ debug c => _1; let mut _0: i8; let mut _2: std::cmp::Ordering; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff index 91276a1b5c4d..ab4646370f16 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff @@ -5,8 +5,6 @@ debug u => _1; let mut _0: *const T; let mut _2: &T; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff index 91276a1b5c4d..ab4646370f16 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff @@ -5,8 +5,6 @@ debug u => _1; let mut _0: *const T; let mut _2: &T; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff index 792c77d575b6..6d3ad348988b 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff @@ -5,8 +5,6 @@ debug u => _1; let mut _0: Never; let mut _2: (); - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff index 792c77d575b6..6d3ad348988b 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -5,8 +5,6 @@ debug u => _1; let mut _0: Never; let mut _2: (); - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.panic-abort.diff index f5646e7f1e99..2b715ac1d635 100644 --- a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.panic-abort.diff @@ -5,8 +5,6 @@ let mut _0: !; let _1: (); let mut _2: !; - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.panic-unwind.diff index f5646e7f1e99..2b715ac1d635 100644 --- a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.panic-unwind.diff @@ -5,8 +5,6 @@ let mut _0: !; let _1: (); let mut _2: !; - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff index ddc8cf9a3d93..cc9177c90027 100644 --- a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff @@ -7,8 +7,6 @@ let mut _0: (); let mut _3: *mut std::string::String; let mut _4: std::string::String; - scope 1 { - } bb0: { StorageLive(_3); diff --git a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff index ddc8cf9a3d93..cc9177c90027 100644 --- a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff @@ -7,8 +7,6 @@ let mut _0: (); let mut _3: *mut std::string::String; let mut _4: std::string::String; - scope 1 { - } bb0: { StorageLive(_3); diff --git a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir index 656934fce426..845673601b2f 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir @@ -21,13 +21,9 @@ fn checked_shl(_1: u32, _2: u32) -> Option { debug self => _1; debug rhs => _2; let mut _3: u32; - scope 5 { - scope 6 (inlined core::num::::unchecked_shl) { - debug self => _1; - debug rhs => _3; - scope 7 { - } - } + scope 5 (inlined core::num::::unchecked_shl) { + debug self => _1; + debug rhs => _3; } } } diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir index ebe846e8a510..518fedffc169 100644 --- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir @@ -5,10 +5,8 @@ fn ub_if_b(_1: Thing) -> Thing { let mut _0: Thing; let mut _2: isize; scope 1 (inlined unreachable_unchecked) { - scope 2 { - } - scope 3 (inlined core::ub_checks::check_language_ub) { - scope 4 (inlined core::ub_checks::check_language_ub::runtime) { + scope 2 (inlined core::ub_checks::check_language_ub) { + scope 3 (inlined core::ub_checks::check_language_ub::runtime) { } } } diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 0b5ed6ee169e..cdb7eea74fba 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -26,10 +26,8 @@ fn int_range(_1: usize, _2: usize) -> () { let mut _12: usize; scope 6 { debug old => _11; - scope 7 { - } } - scope 8 (inlined std::cmp::impls::::lt) { + scope 7 (inlined std::cmp::impls::::lt) { debug self => _6; debug other => _7; let mut _8: usize; diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir index 26919dd98dd2..c744787fce2c 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir @@ -8,21 +8,15 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { debug dest => _1; debug src => _2; scope 2 { - scope 3 { - debug result => _0; - scope 6 (inlined std::ptr::write::) { - debug dst => _1; - debug src => _2; - scope 7 { - } - } - } - scope 4 (inlined std::ptr::read::) { - debug src => _1; - scope 5 { - } + debug result => _0; + scope 4 (inlined std::ptr::write::) { + debug dst => _1; + debug src => _2; } } + scope 3 (inlined std::ptr::read::) { + debug src => _1; + } } bb0: { diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir index 26919dd98dd2..c744787fce2c 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir @@ -8,21 +8,15 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { debug dest => _1; debug src => _2; scope 2 { - scope 3 { - debug result => _0; - scope 6 (inlined std::ptr::write::) { - debug dst => _1; - debug src => _2; - scope 7 { - } - } - } - scope 4 (inlined std::ptr::read::) { - debug src => _1; - scope 5 { - } + debug result => _0; + scope 4 (inlined std::ptr::write::) { + debug dst => _1; + debug src => _2; } } + scope 3 (inlined std::ptr::read::) { + debug src => _1; + } } bb0: { diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index ed965770adbe..002d55ad9d9e 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -29,10 +29,8 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let mut _13: u32; scope 6 { debug old => _12; - scope 7 { - } } - scope 8 (inlined std::cmp::impls::::lt) { + scope 7 (inlined std::cmp::impls::::lt) { debug self => _7; debug other => _8; let mut _9: u32; diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index a7ee9be19bd4..d5021ac84d28 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -29,10 +29,8 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let mut _13: u32; scope 6 { debug old => _12; - scope 7 { - } } - scope 8 (inlined std::cmp::impls::::lt) { + scope 7 (inlined std::cmp::impls::::lt) { debug self => _7; debug other => _8; let mut _9: u32; diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir index f674f6a30090..7faae1d863c1 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir @@ -14,10 +14,8 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { let mut _8: u32; scope 3 { debug old => _7; - scope 4 { - } } - scope 5 (inlined std::cmp::impls::::lt) { + scope 4 (inlined std::cmp::impls::::lt) { debug self => _2; debug other => _3; let mut _4: u32; diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir index a5029dcad3ad..37f00533b606 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir @@ -14,10 +14,8 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { let mut _8: u32; scope 3 { debug old => _7; - scope 4 { - } } - scope 5 (inlined std::cmp::impls::::lt) { + scope 4 (inlined std::cmp::impls::::lt) { debug self => _2; debug other => _3; let mut _4: u32; diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index bcc540ae6fc0..e5490955a365 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -9,8 +9,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug index => _2; let mut _3: *mut [u32]; let mut _4: *mut [u32]; - scope 2 { - } } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index 1fe7da7d2fdc..810fee9a1498 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -9,8 +9,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug index => _2; let mut _3: *mut [u32]; let mut _4: *mut [u32]; - scope 2 { - } } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index f698e15d302b..1ec85906385e 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -37,52 +37,42 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; + let _11: *const T; scope 7 { - let _11: *const T; - scope 8 { - debug end_or_len => _11; - } - scope 14 (inlined without_provenance::) { - debug addr => _3; - scope 15 { - } - } - scope 16 (inlined NonNull::::as_ptr) { - debug self => _7; - } - scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; - debug count => _3; - scope 18 { - } - } + debug end_or_len => _11; + } + scope 11 (inlined without_provenance::) { + debug addr => _3; + } + scope 12 (inlined NonNull::::as_ptr) { + debug self => _7; + } + scope 13 (inlined std::ptr::mut_ptr::::add) { + debug self => _9; + debug count => _3; } } - scope 9 (inlined as From<&[T]>>::from) { + scope 8 (inlined as From<&[T]>>::from) { debug reference => _1; let mut _4: *const [T]; - scope 10 { - } } - scope 11 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { debug self => _5; let mut _6: *const T; - scope 12 { - scope 13 (inlined NonNull::<[T]>::as_ptr) { - debug self => _5; - } + scope 10 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } } - scope 19 (inlined as Iterator>::enumerate) { + scope 14 (inlined as Iterator>::enumerate) { debug self => _13; - scope 20 (inlined Enumerate::>::new) { + scope 15 (inlined Enumerate::>::new) { debug iter => _13; } } - scope 21 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { debug self => _14; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index eae9f5909e62..70cdf3f41c2b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -37,52 +37,42 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; + let _11: *const T; scope 7 { - let _11: *const T; - scope 8 { - debug end_or_len => _11; - } - scope 14 (inlined without_provenance::) { - debug addr => _3; - scope 15 { - } - } - scope 16 (inlined NonNull::::as_ptr) { - debug self => _7; - } - scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; - debug count => _3; - scope 18 { - } - } + debug end_or_len => _11; + } + scope 11 (inlined without_provenance::) { + debug addr => _3; + } + scope 12 (inlined NonNull::::as_ptr) { + debug self => _7; + } + scope 13 (inlined std::ptr::mut_ptr::::add) { + debug self => _9; + debug count => _3; } } - scope 9 (inlined as From<&[T]>>::from) { + scope 8 (inlined as From<&[T]>>::from) { debug reference => _1; let mut _4: *const [T]; - scope 10 { - } } - scope 11 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { debug self => _5; let mut _6: *const T; - scope 12 { - scope 13 (inlined NonNull::<[T]>::as_ptr) { - debug self => _5; - } + scope 10 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } } - scope 19 (inlined as Iterator>::enumerate) { + scope 14 (inlined as Iterator>::enumerate) { debug self => _13; - scope 20 (inlined Enumerate::>::new) { + scope 15 (inlined Enumerate::>::new) { debug iter => _13; } } - scope 21 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { debug self => _14; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 158ae0de8904..d8252e7267a0 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -34,46 +34,36 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; + let _11: *const T; scope 7 { - let _11: *const T; - scope 8 { - debug end_or_len => _11; - } - scope 14 (inlined without_provenance::) { - debug addr => _3; - scope 15 { - } - } - scope 16 (inlined NonNull::::as_ptr) { - debug self => _7; - } - scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; - debug count => _3; - scope 18 { - } - } + debug end_or_len => _11; + } + scope 11 (inlined without_provenance::) { + debug addr => _3; + } + scope 12 (inlined NonNull::::as_ptr) { + debug self => _7; + } + scope 13 (inlined std::ptr::mut_ptr::::add) { + debug self => _9; + debug count => _3; } } - scope 9 (inlined as From<&[T]>>::from) { + scope 8 (inlined as From<&[T]>>::from) { debug reference => _1; let mut _4: *const [T]; - scope 10 { - } } - scope 11 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { debug self => _5; let mut _6: *const T; - scope 12 { - scope 13 (inlined NonNull::<[T]>::as_ptr) { - debug self => _5; - } + scope 10 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } } - scope 19 (inlined as IntoIterator>::into_iter) { + scope 14 (inlined as IntoIterator>::into_iter) { debug self => _13; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index ac9e31a0da87..b3904dc70a60 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -34,46 +34,36 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; + let _11: *const T; scope 7 { - let _11: *const T; - scope 8 { - debug end_or_len => _11; - } - scope 14 (inlined without_provenance::) { - debug addr => _3; - scope 15 { - } - } - scope 16 (inlined NonNull::::as_ptr) { - debug self => _7; - } - scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; - debug count => _3; - scope 18 { - } - } + debug end_or_len => _11; + } + scope 11 (inlined without_provenance::) { + debug addr => _3; + } + scope 12 (inlined NonNull::::as_ptr) { + debug self => _7; + } + scope 13 (inlined std::ptr::mut_ptr::::add) { + debug self => _9; + debug count => _3; } } - scope 9 (inlined as From<&[T]>>::from) { + scope 8 (inlined as From<&[T]>>::from) { debug reference => _1; let mut _4: *const [T]; - scope 10 { - } } - scope 11 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { debug self => _5; let mut _6: *const T; - scope 12 { - scope 13 (inlined NonNull::<[T]>::as_ptr) { - debug self => _5; - } + scope 10 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } } - scope 19 (inlined as IntoIterator>::into_iter) { + scope 14 (inlined as IntoIterator>::into_iter) { debug self => _13; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index 543e8918e394..5ab88c9b8559 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -35,10 +35,8 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _13: usize; scope 7 { debug old => _12; - scope 8 { - } } - scope 9 (inlined std::cmp::impls::::lt) { + scope 8 (inlined std::cmp::impls::::lt) { debug self => _7; debug other => _8; let mut _9: usize; diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index a16e9cd9e516..513651090a85 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -35,10 +35,8 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _13: usize; scope 7 { debug old => _12; - scope 8 { - } } - scope 9 (inlined std::cmp::impls::::lt) { + scope 8 (inlined std::cmp::impls::::lt) { debug self => _7; debug other => _8; let mut _9: usize; diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 9550df012f81..091c8a0e9681 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -19,7 +19,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _20; } - scope 22 (inlined > as Iterator>::next) { + scope 17 (inlined > as Iterator>::next) { debug self => _16; let mut _17: &mut std::slice::Iter<'_, T>; } @@ -39,52 +39,42 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; + let _11: *const T; scope 7 { - let _11: *const T; - scope 8 { - debug end_or_len => _11; - } - scope 14 (inlined without_provenance::) { - debug addr => _3; - scope 15 { - } - } - scope 16 (inlined NonNull::::as_ptr) { - debug self => _7; - } - scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; - debug count => _3; - scope 18 { - } - } + debug end_or_len => _11; + } + scope 11 (inlined without_provenance::) { + debug addr => _3; + } + scope 12 (inlined NonNull::::as_ptr) { + debug self => _7; + } + scope 13 (inlined std::ptr::mut_ptr::::add) { + debug self => _9; + debug count => _3; } } - scope 9 (inlined as From<&[T]>>::from) { + scope 8 (inlined as From<&[T]>>::from) { debug reference => _1; let mut _4: *const [T]; - scope 10 { - } } - scope 11 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { debug self => _5; let mut _6: *const T; - scope 12 { - scope 13 (inlined NonNull::<[T]>::as_ptr) { - debug self => _5; - } + scope 10 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } } - scope 19 (inlined as Iterator>::rev) { + scope 14 (inlined as Iterator>::rev) { debug self => _13; - scope 20 (inlined Rev::>::new) { + scope 15 (inlined Rev::>::new) { debug iter => _13; } } - scope 21 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { debug self => _14; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index d75aabd12fc7..1873d452f345 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -19,7 +19,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _20; } - scope 22 (inlined > as Iterator>::next) { + scope 17 (inlined > as Iterator>::next) { debug self => _16; let mut _17: &mut std::slice::Iter<'_, T>; } @@ -39,52 +39,42 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; + let _11: *const T; scope 7 { - let _11: *const T; - scope 8 { - debug end_or_len => _11; - } - scope 14 (inlined without_provenance::) { - debug addr => _3; - scope 15 { - } - } - scope 16 (inlined NonNull::::as_ptr) { - debug self => _7; - } - scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; - debug count => _3; - scope 18 { - } - } + debug end_or_len => _11; + } + scope 11 (inlined without_provenance::) { + debug addr => _3; + } + scope 12 (inlined NonNull::::as_ptr) { + debug self => _7; + } + scope 13 (inlined std::ptr::mut_ptr::::add) { + debug self => _9; + debug count => _3; } } - scope 9 (inlined as From<&[T]>>::from) { + scope 8 (inlined as From<&[T]>>::from) { debug reference => _1; let mut _4: *const [T]; - scope 10 { - } } - scope 11 (inlined NonNull::<[T]>::cast::) { + scope 9 (inlined NonNull::<[T]>::cast::) { debug self => _5; let mut _6: *const T; - scope 12 { - scope 13 (inlined NonNull::<[T]>::as_ptr) { - debug self => _5; - } + scope 10 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } } - scope 19 (inlined as Iterator>::rev) { + scope 14 (inlined as Iterator>::rev) { debug self => _13; - scope 20 (inlined Rev::>::new) { + scope 15 (inlined Rev::>::new) { debug iter => _13; } } - scope 21 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { debug self => _14; } diff --git a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff index 747028e128fc..859097d3966a 100644 --- a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff @@ -25,8 +25,6 @@ let _7: i32; scope 5 { debug a => _7; - scope 6 { - } } } } diff --git a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff index ce5ddbfdd123..1e6a168f7564 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff @@ -6,218 +6,196 @@ debug multiple => _2; let mut _0: (); let _3: (); + let _4: usize; let _7: (); let mut _8: (); let _9: (); + let _10: usize; let mut _13: *const usize; let _15: (); let mut _16: (); let _17: (); + let _18: usize; let _22: (); let mut _23: &*const usize; let _24: (); + let _25: usize; let _29: (); let mut _30: *mut *const usize; let _31: (); + let _32: usize; let _35: (); let mut _36: *const usize; let _37: (); + let _38: usize; let _44: (); let mut _45: *const usize; let _46: (); + let _47: *const T; let _49: (); let mut _50: (); let _51: (); + let _52: *const T; let mut _53: *const T; let _55: (); let mut _56: (); let _57: (); + let _58: usize; let _62: (); let mut _63: (); let _64: (); + let _65: usize; let _69: (); let mut _70: (); + let _71: usize; let _75: (); let mut _76: (); scope 1 { - let _4: usize; + debug a => _4; + let _5: *const usize; scope 2 { - debug a => _4; - let _5: *const usize; + debug b => _5; + let _6: usize; scope 3 { - debug b => _5; - let _6: usize; - scope 4 { - debug c => _6; + debug c => _6; + } + } + } + scope 4 { + debug a => _10; + let _11: usize; + scope 5 { + debug a2 => _11; + let mut _12: *const usize; + scope 6 { + debug b => _12; + let _14: usize; + scope 7 { + debug c => _14; } } } } - scope 5 { - let _10: usize; - scope 6 { - debug a => _10; - let _11: usize; - scope 7 { - debug a2 => _11; - let mut _12: *const usize; - scope 8 { - debug b => _12; - let _14: usize; - scope 9 { - debug c => _14; - } + scope 8 { + debug a => _18; + let _19: *const usize; + scope 9 { + debug b => _19; + let _20: &*const usize; + scope 10 { + debug d => _20; + let _21: usize; + scope 11 { + debug c => _21; } } } } - scope 10 { - let _18: usize; - scope 11 { - debug a => _18; - let _19: *const usize; - scope 12 { - debug b => _19; - let _20: &*const usize; - scope 13 { - debug d => _20; - let _21: usize; - scope 14 { - debug c => _21; - } + scope 12 { + debug a => _25; + let mut _26: *const usize; + scope 13 { + debug b => _26; + let _27: *mut *const usize; + scope 14 { + debug d => _27; + let _28: usize; + scope 15 { + debug c => _28; } } } } - scope 15 { - let _25: usize; - scope 16 { - debug a => _25; - let mut _26: *const usize; - scope 17 { - debug b => _26; - let _27: *mut *const usize; - scope 18 { - debug d => _27; - let _28: usize; - scope 19 { - debug c => _28; - } - } + scope 16 { + debug a => _32; + let _33: *const usize; + scope 17 { + debug b => _33; + let _34: usize; + scope 18 { + debug c => _34; } } } - scope 20 { - let _32: usize; - scope 21 { - debug a => _32; - let _33: *const usize; - scope 22 { - debug b => _33; - let _34: usize; - scope 23 { - debug c => _34; - } - } - } - } - scope 24 { - let _38: usize; - scope 25 { - debug a => _38; - let _39: *const usize; - scope 26 { - debug b1 => _39; - let _40: usize; - scope 27 { - debug c => _40; - let _41: *const usize; - scope 28 { - debug b2 => _41; - let _42: usize; - scope 29 { - debug c2 => _42; - let _43: *const usize; - scope 30 { - debug b3 => _43; - } + scope 19 { + debug a => _38; + let _39: *const usize; + scope 20 { + debug b1 => _39; + let _40: usize; + scope 21 { + debug c => _40; + let _41: *const usize; + scope 22 { + debug b2 => _41; + let _42: usize; + scope 23 { + debug c2 => _42; + let _43: *const usize; + scope 24 { + debug b3 => _43; } } } } } } - scope 31 { - let _47: *const T; - scope 32 { -- debug a => _47; -+ debug a => _1; - let _48: T; - scope 33 { - debug b => _48; + scope 25 { +- debug a => _47; ++ debug a => _1; + let _48: T; + scope 26 { + debug b => _48; + } + } + scope 27 { + debug a => _52; + let _54: T; + scope 28 { + debug b => _54; + } + } + scope 29 { + debug a => _58; + let _59: *const usize; + scope 30 { + debug b => _59; + let _60: *const usize; + scope 31 { + debug c => _60; + let _61: usize; + scope 32 { + debug e => _61; + } } } } - scope 34 { - let _52: *const T; - scope 35 { - debug a => _52; - let _54: T; - scope 36 { - debug b => _54; + scope 33 { + debug a => _65; + let _66: *const usize; + scope 34 { + debug b => _66; + let _67: &*const usize; + scope 35 { + debug d => _67; + let _68: usize; + scope 36 { + debug c => _68; + } } } } scope 37 { - let _58: usize; + debug a => _71; + let mut _72: *const usize; scope 38 { - debug a => _58; - let _59: *const usize; + debug b => _72; + let _73: &mut *const usize; scope 39 { - debug b => _59; - let _60: *const usize; + debug d => _73; + let _74: usize; scope 40 { - debug c => _60; - let _61: usize; - scope 41 { - debug e => _61; - } - } - } - } - } - scope 42 { - let _65: usize; - scope 43 { - debug a => _65; - let _66: *const usize; - scope 44 { - debug b => _66; - let _67: &*const usize; - scope 45 { - debug d => _67; - let _68: usize; - scope 46 { - debug c => _68; - } - } - } - } - } - scope 47 { - let _71: usize; - scope 48 { - debug a => _71; - let mut _72: *const usize; - scope 49 { - debug b => _72; - let _73: &mut *const usize; - scope 50 { - debug d => _73; - let _74: usize; - scope 51 { - debug c => _74; - } + debug c => _74; } } } diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff index b6b2acc0b439..5629d04f1b19 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff @@ -6,197 +6,177 @@ debug multiple => _2; let mut _0: (); let _3: (); + let mut _4: usize; let _7: (); let mut _8: (); let _9: (); + let mut _10: usize; let mut _13: *mut usize; let _15: (); let mut _16: (); let _17: (); + let mut _18: usize; let _22: (); let mut _23: &*mut usize; let _24: (); + let mut _25: usize; let _29: (); let mut _30: *mut *mut usize; let _31: (); + let mut _32: usize; let _35: (); let mut _36: *mut usize; let _37: (); + let mut _38: usize; let _44: (); let mut _45: *mut usize; let _46: (); + let _47: *mut T; let _49: (); let mut _50: (); let _51: (); + let _52: *mut T; let mut _53: *mut T; let _55: (); let mut _56: (); let _57: (); + let mut _58: usize; let _62: (); let mut _63: (); + let mut _64: usize; let _68: (); let mut _69: (); scope 1 { - let mut _4: usize; + debug a => _4; + let _5: *mut usize; scope 2 { - debug a => _4; - let _5: *mut usize; + debug b => _5; + let _6: usize; scope 3 { - debug b => _5; - let _6: usize; - scope 4 { - debug c => _6; + debug c => _6; + } + } + } + scope 4 { + debug a => _10; + let mut _11: usize; + scope 5 { + debug a2 => _11; + let mut _12: *mut usize; + scope 6 { + debug b => _12; + let _14: usize; + scope 7 { + debug c => _14; } } } } - scope 5 { - let mut _10: usize; - scope 6 { - debug a => _10; - let mut _11: usize; - scope 7 { - debug a2 => _11; - let mut _12: *mut usize; - scope 8 { - debug b => _12; - let _14: usize; - scope 9 { - debug c => _14; - } + scope 8 { + debug a => _18; + let _19: *mut usize; + scope 9 { + debug b => _19; + let _20: &*mut usize; + scope 10 { + debug d => _20; + let _21: usize; + scope 11 { + debug c => _21; } } } } - scope 10 { - let mut _18: usize; - scope 11 { - debug a => _18; - let _19: *mut usize; - scope 12 { - debug b => _19; - let _20: &*mut usize; - scope 13 { - debug d => _20; - let _21: usize; - scope 14 { - debug c => _21; - } + scope 12 { + debug a => _25; + let mut _26: *mut usize; + scope 13 { + debug b => _26; + let _27: *mut *mut usize; + scope 14 { + debug d => _27; + let _28: usize; + scope 15 { + debug c => _28; } } } } - scope 15 { - let mut _25: usize; - scope 16 { - debug a => _25; - let mut _26: *mut usize; - scope 17 { - debug b => _26; - let _27: *mut *mut usize; - scope 18 { - debug d => _27; - let _28: usize; - scope 19 { - debug c => _28; - } - } + scope 16 { + debug a => _32; + let _33: *mut usize; + scope 17 { + debug b => _33; + let _34: usize; + scope 18 { + debug c => _34; } } } - scope 20 { - let mut _32: usize; - scope 21 { - debug a => _32; - let _33: *mut usize; - scope 22 { - debug b => _33; - let _34: usize; - scope 23 { - debug c => _34; - } - } - } - } - scope 24 { - let mut _38: usize; - scope 25 { - debug a => _38; - let _39: *mut usize; - scope 26 { - debug b1 => _39; - let _40: usize; - scope 27 { - debug c => _40; - let _41: *mut usize; - scope 28 { - debug b2 => _41; - let _42: usize; - scope 29 { - debug c2 => _42; - let _43: *mut usize; - scope 30 { - debug b3 => _43; - } + scope 19 { + debug a => _38; + let _39: *mut usize; + scope 20 { + debug b1 => _39; + let _40: usize; + scope 21 { + debug c => _40; + let _41: *mut usize; + scope 22 { + debug b2 => _41; + let _42: usize; + scope 23 { + debug c2 => _42; + let _43: *mut usize; + scope 24 { + debug b3 => _43; } } } } } } - scope 31 { - let _47: *mut T; - scope 32 { -- debug a => _47; -+ debug a => _1; - let _48: T; - scope 33 { - debug b => _48; - } + scope 25 { +- debug a => _47; ++ debug a => _1; + let _48: T; + scope 26 { + debug b => _48; } } - scope 34 { - let _52: *mut T; - scope 35 { - debug a => _52; - let _54: T; - scope 36 { - debug b => _54; - } + scope 27 { + debug a => _52; + let _54: T; + scope 28 { + debug b => _54; } } - scope 37 { - let mut _58: usize; - scope 38 { - debug a => _58; - let _59: *mut usize; - scope 39 { - debug b => _59; - let _60: &*mut usize; - scope 40 { - debug d => _60; - let _61: usize; - scope 41 { - debug c => _61; - } + scope 29 { + debug a => _58; + let _59: *mut usize; + scope 30 { + debug b => _59; + let _60: &*mut usize; + scope 31 { + debug d => _60; + let _61: usize; + scope 32 { + debug c => _61; } } } } - scope 42 { - let mut _64: usize; - scope 43 { - debug a => _64; - let mut _65: *mut usize; - scope 44 { - debug b => _65; - let _66: &mut *mut usize; - scope 45 { - debug d => _66; - let _67: usize; - scope 46 { - debug c => _67; - } + scope 33 { + debug a => _64; + let mut _65: *mut usize; + scope 34 { + debug b => _65; + let _66: &mut *mut usize; + scope 35 { + debug d => _66; + let _67: usize; + scope 36 { + debug c => _67; } } } diff --git a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff index b4912a918ba4..a5427cea1f8e 100644 --- a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff @@ -12,16 +12,12 @@ scope 1 { - debug y => _1; + debug y => _3; - scope 5 { - } } scope 2 { debug a => _2; let _3: *mut i32; scope 3 { debug x => _3; - scope 4 { - } } } diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir index 7124b4c1cd87..f9d58ea60a39 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -36,22 +36,18 @@ fn array_casts() -> () { debug p => _2; let _8: [usize; 2]; scope 3 { - } - scope 4 { debug x => _8; let _9: *const usize; - scope 5 { + scope 4 { debug p => _9; let _20: &usize; let _21: &usize; let mut _34: &usize; - scope 6 { - } - scope 7 { + scope 5 { debug left_val => _20; debug right_val => _21; let _26: core::panicking::AssertKind; - scope 8 { + scope 6 { debug kind => _26; } } diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index be04757f2a3c..b0b70cd5d910 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -36,22 +36,18 @@ fn array_casts() -> () { debug p => _2; let _8: [usize; 2]; scope 3 { - } - scope 4 { debug x => _8; let _9: *const usize; - scope 5 { + scope 4 { debug p => _9; let _20: &usize; let _21: &usize; let mut _34: &usize; - scope 6 { - } - scope 7 { + scope 5 { debug left_val => _20; debug right_val => _21; let _26: core::panicking::AssertKind; - scope 8 { + scope 6 { debug kind => _26; } } diff --git a/tests/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff index a903e8d789e5..526ff2f25cfc 100644 --- a/tests/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff @@ -5,8 +5,6 @@ let mut _0: (); - let _1: u32; - let mut _2: *mut u32; - scope 1 { - } bb0: { - StorageLive(_1); diff --git a/tests/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff index e72e71a13a2a..a88f6d401157 100644 --- a/tests/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff @@ -5,8 +5,6 @@ let mut _0: (); - let _1: &mut u32; - let mut _2: *mut u32; - scope 1 { - } bb0: { - StorageLive(_1); diff --git a/tests/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff index 37c367c82cab..5d45d7ac7815 100644 --- a/tests/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff @@ -6,8 +6,6 @@ - let _1: u32; - let mut _2: &mut u32; - let mut _3: *mut u32; - scope 1 { - } bb0: { - StorageLive(_1); diff --git a/tests/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff index 006e3c4232d7..4f4855dbaaf8 100644 --- a/tests/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff @@ -5,8 +5,6 @@ let mut _0: u32; let mut _1: u32; let mut _2: *mut u32; - scope 1 { - } bb0: { StorageLive(_1); diff --git a/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff index 6c99d3efd29e..2f8dfcc5d634 100644 --- a/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.unions.ScalarReplacementOfAggregates.diff @@ -6,8 +6,6 @@ let mut _0: u32; let mut _2: unions::Repr; let mut _3: f32; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/mir-opt/tls_access.main.PreCodegen.after.mir b/tests/mir-opt/tls_access.main.PreCodegen.after.mir index 43c7051f0273..1c59e938423b 100644 --- a/tests/mir-opt/tls_access.main.PreCodegen.after.mir +++ b/tests/mir-opt/tls_access.main.PreCodegen.after.mir @@ -3,12 +3,10 @@ fn main() -> () { let mut _0: (); let _1: *mut u8; + let _2: &u8; let mut _3: *mut u8; scope 1 { - let _2: &u8; - scope 2 { - debug a => _2; - } + debug a => _2; } bb0: { diff --git a/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir b/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir index 89f7016fee43..240f409817d7 100644 --- a/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir +++ b/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir @@ -7,8 +7,6 @@ fn process_never(_1: *const !) -> () { scope 1 { debug _input => _2; } - scope 2 { - } bb0: { unreachable; diff --git a/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir b/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir index 51905f982b8f..51514ba5e5d9 100644 --- a/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir +++ b/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir @@ -6,8 +6,6 @@ fn process_void(_1: *const Void) -> () { scope 1 { debug _input => _1; } - scope 2 { - } bb0: { return; diff --git a/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir b/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir index 8edc7b5df88f..f0311422c17b 100644 --- a/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir @@ -11,8 +11,6 @@ fn bar(_1: Bar) -> () { let mut _7: bool; let _8: (); let mut _9: [u8; 1]; - scope 1 { - } bb0: { StorageLive(_2); diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs index 6a567efbb2c7..6c14bb57ac6e 100644 --- a/tests/ui/asm/x86_64/goto.rs +++ b/tests/ui/asm/x86_64/goto.rs @@ -1,8 +1,6 @@ //@ only-x86_64 //@ run-pass //@ needs-asm-support -//@ revisions: mirunsafeck thirunsafeck -//@ [thirunsafeck]compile-flags: -Z thir-unsafeck #![deny(unreachable_code)] #![feature(asm_goto)] diff --git a/tests/ui/asm/x86_64/goto.mirunsafeck.stderr b/tests/ui/asm/x86_64/goto.stderr similarity index 92% rename from tests/ui/asm/x86_64/goto.mirunsafeck.stderr rename to tests/ui/asm/x86_64/goto.stderr index fe189c14f0a7..27e227d71a5f 100644 --- a/tests/ui/asm/x86_64/goto.mirunsafeck.stderr +++ b/tests/ui/asm/x86_64/goto.stderr @@ -1,5 +1,5 @@ warning: unreachable statement - --> $DIR/goto.rs:99:9 + --> $DIR/goto.rs:97:9 | LL | / asm!( LL | | "jmp {}", @@ -13,7 +13,7 @@ LL | unreachable!(); | ^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here - --> $DIR/goto.rs:89:8 + --> $DIR/goto.rs:87:8 | LL | #[warn(unreachable_code)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/x86_64/goto.thirunsafeck.stderr b/tests/ui/asm/x86_64/goto.thirunsafeck.stderr deleted file mode 100644 index fe189c14f0a7..000000000000 --- a/tests/ui/asm/x86_64/goto.thirunsafeck.stderr +++ /dev/null @@ -1,23 +0,0 @@ -warning: unreachable statement - --> $DIR/goto.rs:99:9 - | -LL | / asm!( -LL | | "jmp {}", -LL | | label { -LL | | return; -LL | | }, -LL | | options(noreturn) -LL | | ); - | |_________- any code following this expression is unreachable -LL | unreachable!(); - | ^^^^^^^^^^^^^^ unreachable statement - | -note: the lint level is defined here - --> $DIR/goto.rs:89:8 - | -LL | #[warn(unreachable_code)] - | ^^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) - -warning: 1 warning emitted - From 66dee4a9aa759748319f4e9c81dbb87d7e759ee0 Mon Sep 17 00:00:00 2001 From: Rajveer Date: Wed, 3 Apr 2024 00:49:43 +0530 Subject: [PATCH 39/51] Set `CARGO` instead of `PATH` for Rust Clippy Resolves #123227 --- src/bootstrap/src/core/builder.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index c051b8183287..0cce5130f648 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1194,20 +1194,11 @@ impl<'a> Builder<'a> { } pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> Command { - let initial_sysroot_bin = self.initial_rustc.parent().unwrap(); - // Set PATH to include the sysroot bin dir so clippy can find cargo. - // FIXME: once rust-clippy#11944 lands on beta, set `CARGO` directly instead. - let path = t!(env::join_paths( - // The sysroot comes first in PATH to avoid using rustup's cargo. - std::iter::once(PathBuf::from(initial_sysroot_bin)) - .chain(env::split_paths(&t!(env::var("PATH")))) - )); - if run_compiler.stage == 0 { // `ensure(Clippy { stage: 0 })` *builds* clippy with stage0, it doesn't use the beta clippy. let cargo_clippy = self.build.config.download_clippy(); let mut cmd = Command::new(cargo_clippy); - cmd.env("PATH", &path); + cmd.env("CARGO", &self.initial_cargo); return cmd; } @@ -1227,7 +1218,7 @@ impl<'a> Builder<'a> { let mut cmd = Command::new(cargo_clippy); cmd.env(helpers::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - cmd.env("PATH", path); + cmd.env("CARGO", &self.initial_cargo); cmd } From 508530dbc5b6a1234b1616a077efbfd048c3a3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 3 Apr 2024 15:28:47 +0200 Subject: [PATCH 40/51] Output URLs of CI artifacts to GitHub summary --- src/ci/scripts/upload-artifacts.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh index 9755edb6dce5..c9c85ec20b45 100755 --- a/src/ci/scripts/upload-artifacts.sh +++ b/src/ci/scripts/upload-artifacts.sh @@ -45,3 +45,17 @@ deploy_url="s3://${DEPLOY_BUCKET}/${deploy_dir}/$(ciCommit)" retry aws s3 cp --storage-class INTELLIGENT_TIERING \ --no-progress --recursive --acl public-read "${upload_dir}" "${deploy_url}" + +access_url="https://ci-artifacts.rust-lang.org/${deploy_dir}/$(ciCommit)" + +# Output URLs to the uploaded artifacts to GitHub summary (if it is available) +# to make them easily accessible. +if [ -n "${GITHUB_STEP_SUMMARY}" ] +then + echo "# CI artifacts" >> "${GITHUB_STEP_SUMMARY}" + + for filename in "${upload_dir}"/*.xz; do + filename=`basename "${filename}"` + echo "- [${filename}](${access_url}/${filename})" >> "${GITHUB_STEP_SUMMARY}" + done +fi From 989660c3e6efc1c5eb2e822f68863df7d06cbcb4 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 3 Apr 2024 15:17:00 +0200 Subject: [PATCH 41/51] rename `expose_addr` to `expose_provenance` --- compiler/rustc_borrowck/src/type_check/mod.rs | 4 ++-- compiler/rustc_codegen_cranelift/src/base.rs | 2 +- .../rustc_codegen_cranelift/src/intrinsics/simd.rs | 2 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 2 +- compiler/rustc_const_eval/src/interpret/cast.rs | 6 +++--- .../src/transform/check_consts/check.rs | 2 +- .../rustc_const_eval/src/transform/validate.rs | 2 +- compiler/rustc_hir_analysis/src/check/intrinsic.rs | 2 +- compiler/rustc_hir_typeck/messages.ftl | 2 +- compiler/rustc_lint_defs/src/builtin.rs | 6 +++--- compiler/rustc_middle/src/mir/statement.rs | 2 +- compiler/rustc_middle/src/mir/syntax.rs | 4 ++-- compiler/rustc_middle/src/ty/cast.rs | 2 +- compiler/rustc_mir_transform/src/promote_consts.rs | 2 +- compiler/rustc_mir_transform/src/shim.rs | 2 +- compiler/rustc_smir/src/rustc_smir/convert/mir.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- compiler/stable_mir/src/mir/body.rs | 1 + library/core/src/fmt/mod.rs | 4 ++-- library/core/src/intrinsics/simd.rs | 6 ++++++ library/core/src/ptr/const_ptr.rs | 10 +++++----- library/core/src/ptr/mod.rs | 14 +++++++------- library/core/src/ptr/mut_ptr.rs | 11 +++++------ .../crates/core_simd/src/simd/ptr/const_ptr.rs | 10 +++++----- .../crates/core_simd/src/simd/ptr/mut_ptr.rs | 10 +++++----- .../crates/core_simd/tests/pointers.rs | 6 +++--- library/std/src/sys/pal/hermit/thread.rs | 2 +- library/std/src/sys/pal/itron/thread.rs | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- src/tools/miri/src/alloc_addresses/mod.rs | 4 ++-- src/tools/miri/src/shims/intrinsics/simd.rs | 6 +++--- .../miri/tests/fail/provenance/ptr_invalid.rs | 2 +- .../tests/fail/stacked_borrows/exposed_only_ro.rs | 2 +- src/tools/miri/tests/pass/portable-simd-ptrs.rs | 2 +- src/tools/miri/tests/pass/ptr_int_from_exposed.rs | 10 +++++----- .../miri/tests/pass/stacked-borrows/int-to-ptr.rs | 4 ++-- .../pass/stacked-borrows/unknown-bottom-gc.rs | 2 +- ...er_expose_provenance.main.GVN.panic-abort.diff} | 2 +- ...r_expose_provenance.main.GVN.panic-unwind.diff} | 2 +- ...ose_address.rs => pointer_expose_provenance.rs} | 4 ++-- .../mir-opt/const_prop/reify_fn_ptr.main.GVN.diff | 2 +- tests/mir-opt/const_prop/reify_fn_ptr.rs | 2 +- ...ointer_to_int.DeadStoreElimination-initial.diff | 4 ++-- .../dead-store-elimination/provenance_soundness.rs | 4 ++-- ...ovenance.SimplifyLocals-before-const-prop.diff} | 8 ++++---- tests/mir-opt/simplify_locals.rs | 6 +++--- .../lint/lint-strict-provenance-lossy-casts.stderr | 8 ++++---- tests/ui/simd/intrinsic/ptr-cast.rs | 4 ++-- 49 files changed, 105 insertions(+), 99 deletions(-) rename tests/mir-opt/const_prop/{pointer_expose_address.main.GVN.panic-abort.diff => pointer_expose_provenance.main.GVN.panic-abort.diff} (93%) rename tests/mir-opt/const_prop/{pointer_expose_address.main.GVN.panic-unwind.diff => pointer_expose_provenance.main.GVN.panic-unwind.diff} (93%) rename tests/mir-opt/const_prop/{pointer_expose_address.rs => pointer_expose_provenance.rs} (72%) rename tests/mir-opt/{simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff => simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff} (54%) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6405364c30c1..71b54a761a2b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2261,7 +2261,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - CastKind::PointerExposeAddress => { + CastKind::PointerExposeProvenance => { let ty_from = op.ty(body, tcx); let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(*ty); @@ -2271,7 +2271,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!( self, rvalue, - "Invalid PointerExposeAddress cast {:?} -> {:?}", + "Invalid PointerExposeProvenance cast {:?} -> {:?}", ty_from, ty ) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 249c16898ce6..0aa2bae8f78b 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -649,7 +649,7 @@ fn codegen_stmt<'tcx>( | CastKind::IntToFloat | CastKind::FnPtrToPtr | CastKind::PtrToPtr - | CastKind::PointerExposeAddress + | CastKind::PointerExposeProvenance | CastKind::PointerWithExposedProvenance, ref operand, to_ty, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 783ad5d1dd1f..67f9d8310629 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -965,7 +965,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - sym::simd_expose_addr | sym::simd_with_exposed_provenance | sym::simd_cast_ptr => { + sym::simd_expose_provenance | sym::simd_with_exposed_provenance | sym::simd_cast_ptr => { intrinsic_args!(fx, args => (arg); intrinsic); ret.write_cvalue_transmute(fx, arg); } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index e4ec7974e900..dc52dd156b7e 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -2111,7 +2111,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( return Ok(args[0].immediate()); } - if name == sym::simd_expose_addr { + if name == sym::simd_expose_provenance { let (out_len, out_elem) = require_simd!(ret_ty, SimdReturn); require!( in_len == out_len, diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 6f7b98a262d5..4d746c89f1fc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -405,7 +405,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cast = bx.cx().layout_of(self.monomorphize(mir_cast_ty)); let val = match *kind { - mir::CastKind::PointerExposeAddress => { + mir::CastKind::PointerExposeProvenance => { assert!(bx.cx().is_backend_immediate(cast)); let llptr = operand.immediate(); let llcast_ty = bx.cx().immediate_backend_type(cast); diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index e0d45f1fe114..9447d18fe8c9 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -34,9 +34,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.unsize_into(src, cast_layout, dest)?; } - CastKind::PointerExposeAddress => { + CastKind::PointerExposeProvenance => { let src = self.read_immediate(src)?; - let res = self.pointer_expose_address_cast(&src, cast_layout)?; + let res = self.pointer_expose_provenance_cast(&src, cast_layout)?; self.write_immediate(*res, dest)?; } @@ -225,7 +225,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - pub fn pointer_expose_address_cast( + pub fn pointer_expose_provenance_cast( &mut self, src: &ImmTy<'tcx, M::Provenance>, cast_to: TyAndLayout<'tcx>, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index b6dcc3341473..543996c86bac 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -544,7 +544,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // Unsizing is implemented for CTFE. } - Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => { + Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => { self.check_op(ops::RawPtrToIntCast); } Rvalue::Cast(CastKind::PointerWithExposedProvenance, _, _) => { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index e1e98ebc1e9a..a499e4b980fc 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -1077,7 +1077,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } // FIXME: Add Checks for these CastKind::PointerWithExposedProvenance - | CastKind::PointerExposeAddress + | CastKind::PointerExposeProvenance | CastKind::PointerCoercion(_) => {} CastKind::IntToInt | CastKind::IntToFloat => { let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool(); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 00a0fca49072..cea6f3c1dba2 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -627,7 +627,7 @@ pub fn check_intrinsic_type( sym::simd_cast | sym::simd_as | sym::simd_cast_ptr - | sym::simd_expose_addr + | sym::simd_expose_provenance | sym::simd_with_exposed_provenance => (2, 0, vec![param(0)], param(1)), sym::simd_bitmask => (2, 0, vec![param(0)], param(1)), sym::simd_select | sym::simd_select_bitmask => { diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index fbdc3d1adb81..1d51101c9403 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -91,7 +91,7 @@ hir_typeck_lossy_provenance_int2ptr = hir_typeck_lossy_provenance_ptr2int = under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}` .suggestion = use `.addr()` to obtain the address of a pointer - .help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + .help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead hir_typeck_method_call_on_unknown_raw_pointee = cannot call a method on a raw pointer with an unknown pointee type diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 7e9d35ca6c1a..30522628f468 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2797,17 +2797,17 @@ declare_lint! { /// Since this cast is lossy, it is considered good style to use the /// [`ptr::addr`] method instead, which has a similar effect, but doesn't /// "expose" the pointer provenance. This improves optimisation potential. - /// See the docs of [`ptr::addr`] and [`ptr::expose_addr`] for more information + /// See the docs of [`ptr::addr`] and [`ptr::expose_provenance`] for more information /// about exposing pointer provenance. /// /// If your code can't comply with strict provenance and needs to expose - /// the provenance, then there is [`ptr::expose_addr`] as an escape hatch, + /// the provenance, then there is [`ptr::expose_provenance`] as an escape hatch, /// which preserves the behaviour of `as usize` casts while being explicit /// about the semantics. /// /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228 /// [`ptr::addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.addr - /// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.expose_addr + /// [`ptr::expose_provenance`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.expose_provenance pub LOSSY_PROVENANCE_CASTS, Allow, "a lossy pointer to integer cast is used", diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 947764307e49..069c8019cb2c 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -409,7 +409,7 @@ impl<'tcx> Rvalue<'tcx> { // Pointer to int casts may be side-effects due to exposing the provenance. // While the model is undecided, we should be conservative. See // - Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false, + Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => false, Rvalue::Use(_) | Rvalue::CopyForDeref(_) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 1f6165babdfb..7ce48036a684 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1309,8 +1309,8 @@ pub enum Rvalue<'tcx> { pub enum CastKind { /// An exposing pointer to address cast. A cast between a pointer and an integer type, or /// between a function pointer and an integer type. - /// See the docs on `expose_addr` for more details. - PointerExposeAddress, + /// See the docs on `expose_provenance` for more details. + PointerExposeProvenance, /// An address-to-pointer cast that picks up an exposed provenance. /// See the docs on `with_exposed_provenance` for more details. PointerWithExposedProvenance, diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index 9bdc679d4e5b..c9fd20bc1126 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -83,7 +83,7 @@ pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKin let cast = CastTy::from_ty(cast_ty); let cast_kind = match (from, cast) { (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => { - mir::CastKind::PointerExposeAddress + mir::CastKind::PointerExposeProvenance } (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PointerWithExposedProvenance, (_, Some(CastTy::DynStar)) => mir::CastKind::DynStar, diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index d64cb9b12b2b..a9d4b860b7ad 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -434,7 +434,7 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::ThreadLocalRef(_) => return Err(Unpromotable), // ptr-to-int casts are not possible in consts and thus not promotable - Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable), + Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => return Err(Unpromotable), // all other casts including int-to-ptr casts are fine, they just use the integer value // at pointer type. diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index b60ee7649b24..93bad8826255 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -985,7 +985,7 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t let locals = local_decls_for_sig(&sig, span); let source_info = SourceInfo::outermost(span); - // FIXME: use `expose_addr` once we figure out whether function pointers have meaningful provenance. + // FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful provenance. let rvalue = Rvalue::Cast( CastKind::FnPtrToPtr, Operand::Move(Place::from(Local::new(1))), diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 9d91032c1d2c..c9f666125902 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -267,7 +267,7 @@ impl<'tcx> Stable<'tcx> for mir::CastKind { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { use rustc_middle::mir::CastKind::*; match self { - PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress, + PointerExposeProvenance => stable_mir::mir::CastKind::PointerExposeAddress, PointerWithExposedProvenance => stable_mir::mir::CastKind::PointerWithExposedProvenance, PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)), DynStar => stable_mir::mir::CastKind::DynStar, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b1d4a63812f4..a13c9c9b2784 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1659,7 +1659,7 @@ symbols! { simd_cttz, simd_div, simd_eq, - simd_expose_addr, + simd_expose_provenance, simd_extract, simd_fabs, simd_fcos, diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 0d866f27dadf..8f77a19fc0e5 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -971,6 +971,7 @@ pub enum PointerCoercion { #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum CastKind { + // FIXME(smir-rename): rename this to PointerExposeProvenance PointerExposeAddress, PointerWithExposedProvenance, PointerCoercion(PointerCoercion), diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index e880d5758ec0..287f6c23c899 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2438,8 +2438,8 @@ impl Display for char { #[stable(feature = "rust1", since = "1.0.0")] impl Pointer for *const T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - // Cast is needed here because `.expose_addr()` requires `T: Sized`. - pointer_fmt_inner((*self as *const ()).expose_addr(), f) + // Cast is needed here because `.expose_provenance()` requires `T: Sized`. + pointer_fmt_inner((*self as *const ()).expose_provenance(), f) } } diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 614b4b589d37..eeff4ec609a3 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -540,6 +540,10 @@ extern "rust-intrinsic" { /// `T` must be a vector of pointers. /// /// `U` must be a vector of `usize` with the same length as `T`. + #[cfg(not(bootstrap))] + #[rustc_nounwind] + pub fn simd_expose_provenance(ptr: T) -> U; + #[cfg(bootstrap)] #[rustc_nounwind] pub fn simd_expose_addr(ptr: T) -> U; @@ -660,5 +664,7 @@ extern "rust-intrinsic" { pub fn simd_flog(a: T) -> T; } +#[cfg(bootstrap)] +pub use simd_expose_addr as simd_expose_provenance; #[cfg(bootstrap)] pub use simd_from_exposed_addr as simd_with_exposed_provenance; diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index e5713ee89df9..01db050e666f 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -136,7 +136,7 @@ impl *const T { #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[deprecated( since = "1.67.0", - note = "replaced by the `expose_addr` method, or update your code \ + note = "replaced by the `expose_provenance` method, or update your code \ to follow the strict provenance rules using its APIs" )] #[inline(always)] @@ -187,7 +187,7 @@ impl *const T { /// /// If using those APIs is not possible because there is no way to preserve a pointer with the /// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts - /// or [`expose_addr`][pointer::expose_addr] and [`with_exposed_provenance`][with_exposed_provenance] + /// or [`expose_provenance`][pointer::expose_provenance] and [`with_exposed_provenance`][with_exposed_provenance] /// instead. However, note that this makes your code less portable and less amenable to tools /// that check for compliance with the Rust memory model. /// @@ -210,8 +210,8 @@ impl *const T { unsafe { mem::transmute(self.cast::<()>()) } } - /// Gets the "address" portion of the pointer, and 'exposes' the "provenance" part for future - /// use in [`with_exposed_provenance`][]. + /// Exposes the "provenance" part of the pointer for future use in + /// [`with_exposed_provenance`][] and returns the "address" portion. /// /// This is equivalent to `self as usize`, which semantically discards *provenance* and /// *address-space* information. Furthermore, this (like the `as` cast) has the implicit @@ -238,7 +238,7 @@ impl *const T { #[must_use] #[inline(always)] #[unstable(feature = "exposed_provenance", issue = "95228")] - pub fn expose_addr(self) -> usize { + pub fn expose_provenance(self) -> usize { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. self.cast::<()>() as usize } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 28df2b04c88c..f12ab3d50cdd 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -340,8 +340,8 @@ //! clear where a satisfying unambiguous semantics can be defined for Exposed Provenance. //! Furthermore, Exposed Provenance will not work (well) with tools like [Miri] and [CHERI]. //! -//! Exposed Provenance is provided by the [`expose_addr`] and [`with_exposed_provenance`] methods, which -//! are meant to replace `as` casts between pointers and integers. [`expose_addr`] is a lot like +//! Exposed Provenance is provided by the [`expose_provenance`] and [`with_exposed_provenance`] methods, +//! which are meant to replace `as` casts between pointers and integers. [`expose_provenance`] is a lot like //! [`addr`], but additionally adds the provenance of the pointer to a global list of 'exposed' //! provenances. (This list is purely conceptual, it exists for the purpose of specifying Rust but //! is not materialized in actual executions, except in tools like [Miri].) [`with_exposed_provenance`] @@ -355,9 +355,9 @@ //! there is *no* previously 'exposed' provenance that justifies the way the returned pointer will //! be used, the program has undefined behavior. //! -//! Using [`expose_addr`] or [`with_exposed_provenance`] (or the `as` casts) means that code is +//! Using [`expose_provenance`] or [`with_exposed_provenance`] (or the `as` casts) means that code is //! *not* following Strict Provenance rules. The goal of the Strict Provenance experiment is to -//! determine how far one can get in Rust without the use of [`expose_addr`] and +//! determine how far one can get in Rust without the use of [`expose_provenance`] and //! [`with_exposed_provenance`], and to encourage code to be written with Strict Provenance APIs only. //! Maximizing the amount of such code is a major win for avoiding specification complexity and to //! facilitate adoption of tools like [CHERI] and [Miri] that can be a big help in increasing the @@ -374,7 +374,7 @@ //! [`map_addr`]: pointer::map_addr //! [`addr`]: pointer::addr //! [`ptr::dangling`]: core::ptr::dangling -//! [`expose_addr`]: pointer::expose_addr +//! [`expose_provenance`]: pointer::expose_provenance //! [`with_exposed_provenance`]: with_exposed_provenance //! [Miri]: https://github.com/rust-lang/miri //! [CHERI]: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/ @@ -663,7 +663,7 @@ pub const fn dangling_mut() -> *mut T { /// /// This is a more rigorously specified alternative to `addr as *const T`. The provenance of the /// returned pointer is that of *any* pointer that was previously exposed by passing it to -/// [`expose_addr`][pointer::expose_addr], or a `ptr as usize` cast. In addition, memory which is +/// [`expose_provenance`][pointer::expose_provenance], or a `ptr as usize` cast. In addition, memory which is /// outside the control of the Rust abstract machine (MMIO registers, for example) is always /// considered to be exposed, so long as this memory is disjoint from memory that will be used by /// the abstract machine such as the stack, heap, and statics. @@ -711,7 +711,7 @@ where /// /// This is a more rigorously specified alternative to `addr as *mut T`. The provenance of the /// returned pointer is that of *any* pointer that was previously passed to -/// [`expose_addr`][pointer::expose_addr] or a `ptr as usize` cast. If there is no previously +/// [`expose_provenance`][pointer::expose_provenance] or a `ptr as usize` cast. If there is no previously /// 'exposed' provenance that justifies the way this pointer will be used, the program has undefined /// behavior. Note that there is no algorithm that decides which provenance will be used. You can /// think of this as "guessing" the right provenance, and the guess will be "maximally in your diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 042658fa35f8..41e5ba674582 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -142,7 +142,7 @@ impl *mut T { #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[deprecated( since = "1.67.0", - note = "replaced by the `expose_addr` method, or update your code \ + note = "replaced by the `expose_provenance` method, or update your code \ to follow the strict provenance rules using its APIs" )] #[inline(always)] @@ -194,7 +194,7 @@ impl *mut T { /// /// If using those APIs is not possible because there is no way to preserve a pointer with the /// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts - /// or [`expose_addr`][pointer::expose_addr] and [`with_exposed_provenance`][with_exposed_provenance] + /// or [`expose_provenance`][pointer::expose_provenance] and [`with_exposed_provenance`][with_exposed_provenance] /// instead. However, note that this makes your code less portable and less amenable to tools /// that check for compliance with the Rust memory model. /// @@ -217,8 +217,8 @@ impl *mut T { unsafe { mem::transmute(self.cast::<()>()) } } - /// Gets the "address" portion of the pointer, and 'exposes' the "provenance" part for future - /// use in [`with_exposed_provenance`][]. + /// Exposes the "provenance" part of the pointer for future use in + /// [`with_exposed_provenance`][] and returns the "address" portion. /// /// This is equivalent to `self as usize`, which semantically discards *provenance* and /// *address-space* information. Furthermore, this (like the `as` cast) has the implicit @@ -242,10 +242,9 @@ impl *mut T { /// API and its claimed semantics are part of [Exposed Provenance][super#exposed-provenance]. /// /// [`with_exposed_provenance_mut`]: with_exposed_provenance_mut - #[must_use] #[inline(always)] #[unstable(feature = "exposed_provenance", issue = "95228")] - pub fn expose_addr(self) -> usize { + pub fn expose_provenance(self) -> usize { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. self.cast::<()>() as usize } diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs index 4d2fe999ca6f..0f1719206c9c 100644 --- a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -50,9 +50,9 @@ pub trait SimdConstPtr: Copy + Sealed { /// Equivalent to calling [`pointer::with_addr`] on each element. fn with_addr(self, addr: Self::Usize) -> Self; - /// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use - /// in [`Self::with_exposed_provenance`]. - fn expose_addr(self) -> Self::Usize; + /// Exposes the "provenance" part of the pointer for future use in + /// [`Self::with_exposed_provenance`] and returns the "address" portion. + fn expose_provenance(self) -> Self::Usize; /// Convert an address back to a pointer, picking up a previously "exposed" provenance. /// @@ -131,9 +131,9 @@ where } #[inline] - fn expose_addr(self) -> Self::Usize { + fn expose_provenance(self) -> Self::Usize { // Safety: `self` is a pointer vector - unsafe { core::intrinsics::simd::simd_expose_addr(self) } + unsafe { core::intrinsics::simd::simd_expose_provenance(self) } } #[inline] diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs index b3437b9c4996..7ba996d149c0 100644 --- a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -47,9 +47,9 @@ pub trait SimdMutPtr: Copy + Sealed { /// Equivalent to calling [`pointer::with_addr`] on each element. fn with_addr(self, addr: Self::Usize) -> Self; - /// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use - /// in [`Self::with_exposed_provenance`]. - fn expose_addr(self) -> Self::Usize; + /// Exposes the "provenance" part of the pointer for future use in + /// [`Self::with_exposed_provenance`] and returns the "address" portion. + fn expose_provenance(self) -> Self::Usize; /// Convert an address back to a pointer, picking up a previously "exposed" provenance. /// @@ -128,9 +128,9 @@ where } #[inline] - fn expose_addr(self) -> Self::Usize { + fn expose_provenance(self) -> Self::Usize { // Safety: `self` is a pointer vector - unsafe { core::intrinsics::simd::simd_expose_addr(self) } + unsafe { core::intrinsics::simd::simd_expose_provenance(self) } } #[inline] diff --git a/library/portable-simd/crates/core_simd/tests/pointers.rs b/library/portable-simd/crates/core_simd/tests/pointers.rs index 5984fdae2f9b..90bfc5d5fd6a 100644 --- a/library/portable-simd/crates/core_simd/tests/pointers.rs +++ b/library/portable-simd/crates/core_simd/tests/pointers.rs @@ -32,10 +32,10 @@ macro_rules! common_tests { ); } - fn expose_addr() { + fn expose_provenance() { test_helpers::test_unary_elementwise( - &Simd::<*$constness u32, LANES>::expose_addr, - &<*$constness u32>::expose_addr, + &Simd::<*$constness u32, LANES>::expose_provenance, + &<*$constness u32>::expose_provenance, &|_| true, ); } diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index 62c76a74cd4d..40f88e33d4ad 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -29,7 +29,7 @@ impl Thread { let p = Box::into_raw(Box::new(p)); let tid = abi::spawn2( thread_start, - p.expose_addr(), + p.expose_provenance(), abi::Priority::into(abi::NORMAL_PRIO), stack, core_id, diff --git a/library/std/src/sys/pal/itron/thread.rs b/library/std/src/sys/pal/itron/thread.rs index 1c66bd79ce4f..047513a67927 100644 --- a/library/std/src/sys/pal/itron/thread.rs +++ b/library/std/src/sys/pal/itron/thread.rs @@ -181,7 +181,7 @@ impl Thread { abi::acre_tsk(&abi::T_CTSK { // Activate this task immediately tskatr: abi::TA_ACT, - exinf: p_inner.as_ptr().expose_addr() as abi::EXINF, + exinf: p_inner.as_ptr().expose_provenance() as abi::EXINF, // The entry point task: Some(trampoline), // Inherit the calling task's base priority diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 12b080059970..325c9bee0578 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -149,7 +149,7 @@ fn check_rvalue<'tcx>( Err((span, "unsizing casts are not allowed in const fn".into())) } }, - Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => { + Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => { Err((span, "casting pointers to ints is unstable in const fn".into())) }, Rvalue::Cast(CastKind::DynStar, _, _) => { diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 6b8e1510a6bf..fec39ec2b8e3 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -18,8 +18,8 @@ use reuse_pool::ReusePool; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ProvenanceMode { - /// We support `expose_addr`/`with_exposed_provenance` via "wildcard" provenance. - /// However, we want on `with_exposed_provenance` to alert the user of the precision loss. + /// We support `expose_provenance`/`with_exposed_provenance` via "wildcard" provenance. + /// However, we warn on `with_exposed_provenance` to alert the user of the precision loss. Default, /// Like `Default`, but without the warning. Permissive, diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 9d268f09edb5..a2fc4f0f761a 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -514,7 +514,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { dest.transmute(this.machine.layouts.uint(dest.layout.size).unwrap(), this)?; this.write_int(res, &dest)?; } - "cast" | "as" | "cast_ptr" | "expose_addr" | "with_exposed_provenance" => { + "cast" | "as" | "cast_ptr" | "expose_provenance" | "with_exposed_provenance" => { let [op] = check_arg_count(args)?; let (op, op_len) = this.operand_to_simd(op)?; let (dest, dest_len) = this.mplace_to_simd(dest)?; @@ -524,7 +524,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let unsafe_cast = intrinsic_name == "cast"; let safe_cast = intrinsic_name == "as"; let ptr_cast = intrinsic_name == "cast_ptr"; - let expose_cast = intrinsic_name == "expose_addr"; + let expose_cast = intrinsic_name == "expose_provenance"; let from_exposed_cast = intrinsic_name == "with_exposed_provenance"; for i in 0..dest_len { @@ -557,7 +557,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.ptr_to_ptr(&op, dest.layout)?, // Ptr/Int casts (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => - this.pointer_expose_address_cast(&op, dest.layout)?, + this.pointer_expose_provenance_cast(&op, dest.layout)?, (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => this.pointer_with_exposed_provenance_cast(&op, dest.layout)?, // Error otherwise diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid.rs b/src/tools/miri/tests/fail/provenance/ptr_invalid.rs index 730859684a0c..512473cd8945 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_invalid.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_invalid.rs @@ -4,6 +4,6 @@ fn main() { let x = 42; let xptr = &x as *const i32; - let xptr_invalid = std::ptr::without_provenance::(xptr.expose_addr()); + let xptr_invalid = std::ptr::without_provenance::(xptr.expose_provenance()); let _val = unsafe { *xptr_invalid }; //~ ERROR: is a dangling pointer } diff --git a/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs b/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs index aa05649d550c..608ab7189194 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs @@ -6,7 +6,7 @@ fn main() { let mut x = 0; let _fool = &mut x as *mut i32; // this would have fooled the old untagged pointer logic - let addr = (&x as *const i32).expose_addr(); + let addr = (&x as *const i32).expose_provenance(); let ptr = std::ptr::with_exposed_provenance_mut::(addr); unsafe { *ptr = 0 }; //~ ERROR: /write access using .* no exposed tags have suitable permission in the borrow stack/ } diff --git a/src/tools/miri/tests/pass/portable-simd-ptrs.rs b/src/tools/miri/tests/pass/portable-simd-ptrs.rs index 3b2d221bd8ea..096ec78da1a0 100644 --- a/src/tools/miri/tests/pass/portable-simd-ptrs.rs +++ b/src/tools/miri/tests/pass/portable-simd-ptrs.rs @@ -7,6 +7,6 @@ use std::simd::prelude::*; fn main() { // Pointer casts let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast(); - let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_addr(); + let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_provenance(); let _ptrs = Simd::<*const i32, 4>::with_exposed_provenance(addrs); } diff --git a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs index 8555de986f06..5690d7865bbc 100644 --- a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs +++ b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs @@ -10,7 +10,7 @@ fn ptr_roundtrip_out_of_bounds() { let x: i32 = 3; let x_ptr = &x as *const i32; - let x_usize = x_ptr.wrapping_offset(128).expose_addr(); + let x_usize = x_ptr.wrapping_offset(128).expose_provenance(); let ptr = ptr::with_exposed_provenance::(x_usize).wrapping_offset(-128); assert_eq!(unsafe { *ptr }, 3); @@ -24,8 +24,8 @@ fn ptr_roundtrip_confusion() { let x_ptr = &x as *const i32; let y_ptr = &y as *const i32; - let x_usize = x_ptr.expose_addr(); - let y_usize = y_ptr.expose_addr(); + let x_usize = x_ptr.expose_provenance(); + let y_usize = y_ptr.expose_provenance(); let ptr = ptr::with_exposed_provenance::(y_usize); let ptr = ptr.with_addr(x_usize); @@ -37,7 +37,7 @@ fn ptr_roundtrip_imperfect() { let x: u8 = 3; let x_ptr = &x as *const u8; - let x_usize = x_ptr.expose_addr() + 128; + let x_usize = x_ptr.expose_provenance() + 128; let ptr = ptr::with_exposed_provenance::(x_usize).wrapping_offset(-128); assert_eq!(unsafe { *ptr }, 3); @@ -48,7 +48,7 @@ fn ptr_roundtrip_null() { let x = &42; let x_ptr = x as *const i32; let x_null_ptr = x_ptr.with_addr(0); // addr 0, but still the provenance of x - let null = x_null_ptr.expose_addr(); + let null = x_null_ptr.expose_provenance(); assert_eq!(null, 0); let x_null_ptr_copy = ptr::with_exposed_provenance::(null); // just a roundtrip, so has provenance of x (angelically) diff --git a/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs b/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs index 5622bf186545..c89d79b42e31 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs @@ -17,7 +17,7 @@ fn example(variant: bool) { unsafe { fn not_so_innocent(x: &mut u32) -> usize { let x_raw4 = x as *mut u32; - x_raw4.expose_addr() + x_raw4.expose_provenance() } let mut c = 42u32; @@ -26,7 +26,7 @@ fn example(variant: bool) { // stack: [..., Unique(1)] let x_raw2 = x_unique1 as *mut u32; - let x_raw2_addr = x_raw2.expose_addr(); + let x_raw2_addr = x_raw2.expose_provenance(); // stack: [..., Unique(1), SharedRW(2)] let x_unique3 = &mut *x_raw2; diff --git a/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs b/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs index 6e177a6e4abb..55356814a1a0 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs @@ -9,7 +9,7 @@ fn main() { // Expose the allocation and use the exposed pointer, creating an unknown bottom unsafe { - let p: *mut u8 = ptr::with_exposed_provenance::(ptr.expose_addr()) as *mut u8; + let p: *mut u8 = ptr::with_exposed_provenance::(ptr.expose_provenance()) as *mut u8; *p = 1; } diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-abort.diff similarity index 93% rename from tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff rename to tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-abort.diff index 596eb1a9966d..79a95b618d17 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-abort.diff @@ -19,7 +19,7 @@ StorageLive(_3); _3 = const main::FOO; _2 = &raw const (*_3); - _1 = move _2 as usize (PointerExposeAddress); + _1 = move _2 as usize (PointerExposeProvenance); StorageDead(_2); StorageDead(_3); StorageLive(_4); diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-unwind.diff similarity index 93% rename from tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff rename to tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-unwind.diff index 995f281ecf54..9d1bcd92fef2 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/pointer_expose_provenance.main.GVN.panic-unwind.diff @@ -19,7 +19,7 @@ StorageLive(_3); _3 = const main::FOO; _2 = &raw const (*_3); - _1 = move _2 as usize (PointerExposeAddress); + _1 = move _2 as usize (PointerExposeProvenance); StorageDead(_2); StorageDead(_3); StorageLive(_4); diff --git a/tests/mir-opt/const_prop/pointer_expose_address.rs b/tests/mir-opt/const_prop/pointer_expose_provenance.rs similarity index 72% rename from tests/mir-opt/const_prop/pointer_expose_address.rs rename to tests/mir-opt/const_prop/pointer_expose_provenance.rs index a6b4f8857c37..840a4d65f3d7 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.rs +++ b/tests/mir-opt/const_prop/pointer_expose_provenance.rs @@ -4,12 +4,12 @@ #[inline(never)] fn read(_: usize) { } -// EMIT_MIR pointer_expose_address.main.GVN.diff +// EMIT_MIR pointer_expose_provenance.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: [[ptr:_.*]] = const main::FOO; // CHECK: [[ref:_.*]] = &raw const (*[[ptr]]); - // CHECK: [[x:_.*]] = move [[ref]] as usize (PointerExposeAddress); + // CHECK: [[x:_.*]] = move [[ref]] as usize (PointerExposeProvenance); // CHECK: = read([[x]]) const FOO: &i32 = &1; let x = FOO as *const i32 as usize; diff --git a/tests/mir-opt/const_prop/reify_fn_ptr.main.GVN.diff b/tests/mir-opt/const_prop/reify_fn_ptr.main.GVN.diff index 2f76e74a3f87..e5786bcf701e 100644 --- a/tests/mir-opt/const_prop/reify_fn_ptr.main.GVN.diff +++ b/tests/mir-opt/const_prop/reify_fn_ptr.main.GVN.diff @@ -14,7 +14,7 @@ StorageLive(_2); StorageLive(_3); _3 = main as fn() (PointerCoercion(ReifyFnPointer)); - _2 = move _3 as usize (PointerExposeAddress); + _2 = move _3 as usize (PointerExposeProvenance); StorageDead(_3); _1 = move _2 as *const fn() (PointerWithExposedProvenance); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/reify_fn_ptr.rs b/tests/mir-opt/const_prop/reify_fn_ptr.rs index 4e897d227680..55dca24f3d2e 100644 --- a/tests/mir-opt/const_prop/reify_fn_ptr.rs +++ b/tests/mir-opt/const_prop/reify_fn_ptr.rs @@ -4,7 +4,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: [[ptr:_.*]] = main as fn() (PointerCoercion(ReifyFnPointer)); - // CHECK: [[addr:_.*]] = move [[ptr]] as usize (PointerExposeAddress); + // CHECK: [[addr:_.*]] = move [[ptr]] as usize (PointerExposeProvenance); // CHECK: [[back:_.*]] = move [[addr]] as *const fn() (PointerWithExposedProvenance); let _ = main as usize as *const fn(); } diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff index 9b0dc6b6af67..56d5c24ae1dc 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff @@ -19,12 +19,12 @@ StorageLive(_2); StorageLive(_3); _3 = _1; - _2 = move _3 as usize (PointerExposeAddress); + _2 = move _3 as usize (PointerExposeProvenance); StorageDead(_3); StorageLive(_4); StorageLive(_5); _5 = _1; - _4 = move _5 as isize (PointerExposeAddress); + _4 = move _5 as isize (PointerExposeProvenance); StorageDead(_5); _0 = const (); StorageDead(_4); diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.rs b/tests/mir-opt/dead-store-elimination/provenance_soundness.rs index 96268cd957ef..20517a00489a 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.rs +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.rs @@ -5,8 +5,8 @@ // EMIT_MIR provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff fn pointer_to_int(p: *mut i32) { // CHECK-LABEL: fn pointer_to_int( - // CHECK: {{_.*}} = {{.*}} as usize (PointerExposeAddress); - // CHECK: {{_.*}} = {{.*}} as isize (PointerExposeAddress); + // CHECK: {{_.*}} = {{.*}} as usize (PointerExposeProvenance); + // CHECK: {{_.*}} = {{.*}} as isize (PointerExposeProvenance); let _x = p as usize; let _y = p as isize; } diff --git a/tests/mir-opt/simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff similarity index 54% rename from tests/mir-opt/simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff rename to tests/mir-opt/simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff index 9ebee3df62c6..cc5c642407e9 100644 --- a/tests/mir-opt/simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff @@ -1,7 +1,7 @@ -- // MIR for `expose_addr` before SimplifyLocals-before-const-prop -+ // MIR for `expose_addr` after SimplifyLocals-before-const-prop +- // MIR for `expose_provenance` before SimplifyLocals-before-const-prop ++ // MIR for `expose_provenance` after SimplifyLocals-before-const-prop - fn expose_addr(_1: *const usize) -> () { + fn expose_provenance(_1: *const usize) -> () { debug p => _1; let mut _0: (); let _2: usize; @@ -11,7 +11,7 @@ StorageLive(_2); StorageLive(_3); _3 = _1; - _2 = move _3 as usize (PointerExposeAddress); + _2 = move _3 as usize (PointerExposeProvenance); StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/simplify_locals.rs b/tests/mir-opt/simplify_locals.rs index f95e9185f448..756679e77e39 100644 --- a/tests/mir-opt/simplify_locals.rs +++ b/tests/mir-opt/simplify_locals.rs @@ -63,8 +63,8 @@ fn t4() -> u32 { unsafe { X + 1 } } -// EMIT_MIR simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff -fn expose_addr(p: *const usize) { +// EMIT_MIR simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff +fn expose_provenance(p: *const usize) { // Used pointer to address cast. Has a side effect of exposing the provenance. p as usize; } @@ -78,5 +78,5 @@ fn main() { t2(); t3(); t4(); - expose_addr(&0); + expose_provenance(&0); } diff --git a/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr b/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr index aa151fe2d214..390028b349e5 100644 --- a/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr +++ b/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr @@ -4,7 +4,7 @@ error: under strict provenance it is considered bad style to cast pointer `*cons LL | let addr: usize = &x as *const u8 as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead note: the lint level is defined here --> $DIR/lint-strict-provenance-lossy-casts.rs:2:9 | @@ -21,7 +21,7 @@ error: under strict provenance it is considered bad style to cast pointer `*cons LL | let addr_32bit = &x as *const u8 as u32; | ^^^^^^^^^^^^^^^^^^^^^^ | - = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead help: use `.addr()` to obtain the address of a pointer | LL | let addr_32bit = (&x as *const u8).addr() as u32; @@ -35,7 +35,7 @@ LL | let ptr_addr = ptr as usize; | | | help: use `.addr()` to obtain the address of a pointer: `.addr()` | - = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` --> $DIR/lint-strict-provenance-lossy-casts.rs:16:26 @@ -45,7 +45,7 @@ LL | let ptr_addr_32bit = ptr as u32; | | | help: use `.addr()` to obtain the address of a pointer: `.addr() as u32` | - = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead error: aborting due to 4 previous errors diff --git a/tests/ui/simd/intrinsic/ptr-cast.rs b/tests/ui/simd/intrinsic/ptr-cast.rs index 628203462414..0490734b48ac 100644 --- a/tests/ui/simd/intrinsic/ptr-cast.rs +++ b/tests/ui/simd/intrinsic/ptr-cast.rs @@ -4,7 +4,7 @@ extern "rust-intrinsic" { fn simd_cast_ptr(x: T) -> U; - fn simd_expose_addr(x: T) -> U; + fn simd_expose_provenance(x: T) -> U; fn simd_with_exposed_provenance(x: T) -> U; } @@ -22,7 +22,7 @@ fn main() { // change constness and type let const_ptrs: V<*const u8> = simd_cast_ptr(ptrs); - let exposed_addr: V = simd_expose_addr(const_ptrs); + let exposed_addr: V = simd_expose_provenance(const_ptrs); let with_exposed_provenance: V<*mut i8> = simd_with_exposed_provenance(exposed_addr); From 44b36024786a5e00d55111c1a43a0c8388caefcb Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 3 Apr 2024 17:23:08 +0300 Subject: [PATCH 42/51] hir: Drop owner's own item-local id (zero) from parenting tables --- compiler/rustc_ast_lowering/src/index.rs | 4 +++- compiler/rustc_middle/src/hir/mod.rs | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index a1164008d0da..6e09632d0e33 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -112,7 +112,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } fn insert_nested(&mut self, item: LocalDefId) { - self.parenting.insert(item, self.parent_node); + if self.parent_node.as_u32() != 0 { + self.parenting.insert(item, self.parent_node); + } } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 28f7574f66fc..42a06c968c75 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -174,8 +174,12 @@ pub fn provide(providers: &mut Providers) { let parent_owner_id = tcx.local_def_id_to_hir_id(parent_def_id).owner; HirId { owner: parent_owner_id, - local_id: tcx.hir_crate(()).owners[parent_owner_id.def_id].unwrap().parenting - [&owner_id.def_id], + local_id: tcx.hir_crate(()).owners[parent_owner_id.def_id] + .unwrap() + .parenting + .get(&owner_id.def_id) + .copied() + .unwrap_or(ItemLocalId::from_u32(0)), } }) }; From e3025d6a55b1381802e8d6a85cbd4491dcaaa81d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Mar 2024 12:03:29 -0400 Subject: [PATCH 43/51] Stop chopping off args for no reason --- .../rustc_trait_selection/src/traits/util.rs | 2 -- .../in-trait/span-bug-issue-121457.rs | 1 + .../in-trait/span-bug-issue-121457.stderr | 19 ++++++++++++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 466a53d8ce02..50cc0ed90fb2 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -381,8 +381,6 @@ pub fn check_args_compatible<'tcx>( } let generics = tcx.generics_of(assoc_item.def_id); - // Chop off any additional args (RPITIT) args - let args = &args[0..generics.count().min(args.len())]; check_args_compatible_inner(tcx, generics, args) } diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs index ab21dae7dc50..7a51037324f2 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs @@ -14,6 +14,7 @@ impl<'a, I: 'a + Iterable> Iterable for &'a I { //~^ ERROR binding for associated type `Item` references lifetime `'missing` //~| ERROR binding for associated type `Item` references lifetime `'missing` //~| ERROR `()` is not an iterator + //~| WARNING impl trait in impl method signature does not match trait method signature } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr index d8a2eef94a18..67c4df0f3a9e 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr @@ -32,7 +32,24 @@ LL | fn iter(&self) -> impl for<'missing> Iterator $DIR/span-bug-issue-121457.rs:13:51 + | +LL | fn iter(&self) -> impl Iterator; + | ------------- return type from trait method defined here +... +LL | fn iter(&self) -> impl for<'missing> Iterator> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this bound is stronger than that defined on the trait + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information + = note: `#[warn(refining_impl_trait_reachable)]` on by default +help: replace the return type so that it matches the trait + | +LL | fn iter(&self) -> impl Iterator {} + | ~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0195, E0277, E0582. For more information about an error, try `rustc --explain E0195`. From c9f852979359779ec1c91b91eb477272308a864f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Mar 2024 12:05:14 -0400 Subject: [PATCH 44/51] Uplift and start using check_args_compatible more liberally --- compiler/rustc_middle/src/ty/context.rs | 93 +++++++++++++++---- compiler/rustc_middle/src/ty/sty.rs | 34 +++---- .../src/solve/normalizes_to/mod.rs | 4 +- .../rustc_trait_selection/src/traits/mod.rs | 8 +- .../src/traits/project.rs | 3 +- .../rustc_trait_selection/src/traits/util.rs | 40 -------- compiler/rustc_ty_utils/src/opaque_types.rs | 3 +- 7 files changed, 95 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 23881c4b124d..df792b87056c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1961,33 +1961,90 @@ impl<'tcx> TyCtxt<'tcx> { if pred.kind() != binder { self.mk_predicate(binder) } else { pred } } + pub fn check_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) -> bool { + self.check_args_compatible_inner(def_id, args, false) + } + + fn check_args_compatible_inner( + self, + def_id: DefId, + args: &'tcx [ty::GenericArg<'tcx>], + nested: bool, + ) -> bool { + let generics = self.generics_of(def_id); + + // IATs themselves have a weird arg setup (self + own args), but nested items *in* IATs + // (namely: opaques, i.e. ATPITs) do not. + let own_args = if !nested + && let DefKind::AssocTy = self.def_kind(def_id) + && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) + { + if generics.params.len() + 1 != args.len() { + return false; + } + + if !matches!(args[0].unpack(), ty::GenericArgKind::Type(_)) { + return false; + } + + &args[1..] + } else { + if generics.count() != args.len() { + return false; + } + + let (parent_args, own_args) = args.split_at(generics.parent_count); + + if let Some(parent) = generics.parent + && !self.check_args_compatible_inner(parent, parent_args, true) + { + return false; + } + + own_args + }; + + for (param, arg) in std::iter::zip(&generics.params, own_args) { + match (¶m.kind, arg.unpack()) { + (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_)) + | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_)) + | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {} + _ => return false, + } + } + + true + } + + pub fn assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) { + if !self.check_args_compatible(def_id, args) { + if let DefKind::AssocTy = self.def_kind(def_id) + && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) + { + bug!() + } else { + bug!( + "args not compatible with generics for {}: args={:#?}, generics={:#?}", + self.def_path_str(def_id), + args, + ty::GenericArgs::identity_for_item(self, def_id) + ); + } + } + } + #[inline(always)] pub(crate) fn check_and_mk_args( self, _def_id: DefId, args: impl IntoIterator>>, ) -> GenericArgsRef<'tcx> { - let args = args.into_iter().map(Into::into); + let args = self.mk_args_from_iter(args.into_iter().map(Into::into)); #[cfg(debug_assertions)] { - let generics = self.generics_of(_def_id); - - let n = if let DefKind::AssocTy = self.def_kind(_def_id) - && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(_def_id)) - { - // If this is an inherent projection. - generics.params.len() + 1 - } else { - generics.count() - }; - assert_eq!( - (n, Some(n)), - args.size_hint(), - "wrong number of generic parameters for {_def_id:?}: {:?}", - args.collect::>(), - ); + self.assert_args_compatible(_def_id, args); } - self.mk_args_from_iter(args) + args } #[inline] diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b5e619f1e2a3..dc1ad1da7e1f 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1624,13 +1624,9 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { - debug_assert_eq!( - tcx.generics_of(def.did()).count(), - args.len(), - "wrong number of args for ADT: {:#?} vs {:#?}", - tcx.generics_of(def.did()).params, - args - ); + if cfg!(debug_assertions) { + tcx.assert_args_compatible(def.did(), args); + } Ty::new(tcx, Adt(def, args)) } @@ -1711,11 +1707,9 @@ impl<'tcx> Ty<'tcx> { def_id: DefId, closure_args: GenericArgsRef<'tcx>, ) -> Ty<'tcx> { - debug_assert_eq!( - closure_args.len(), - tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3, - "closure constructed with incorrect generic parameters" - ); + if cfg!(debug_assertions) { + tcx.assert_args_compatible(def_id, closure_args); + } Ty::new(tcx, Closure(def_id, closure_args)) } @@ -1725,11 +1719,9 @@ impl<'tcx> Ty<'tcx> { def_id: DefId, closure_args: GenericArgsRef<'tcx>, ) -> Ty<'tcx> { - debug_assert_eq!( - closure_args.len(), - tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, - "closure constructed with incorrect generic parameters" - ); + if cfg!(debug_assertions) { + tcx.assert_args_compatible(def_id, closure_args); + } Ty::new(tcx, CoroutineClosure(def_id, closure_args)) } @@ -1739,11 +1731,9 @@ impl<'tcx> Ty<'tcx> { def_id: DefId, coroutine_args: GenericArgsRef<'tcx>, ) -> Ty<'tcx> { - debug_assert_eq!( - coroutine_args.len(), - tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 6, - "coroutine constructed with incorrect number of generic parameters" - ); + if cfg!(debug_assertions) { + tcx.assert_args_compatible(def_id, coroutine_args); + } Ty::new(tcx, Coroutine(def_id, coroutine_args)) } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 666888932351..d8aeadd07b3d 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -1,4 +1,4 @@ -use crate::traits::{check_args_compatible, specialization_graph}; +use crate::traits::specialization_graph; use super::assembly::structural_traits::AsyncCallableRelevantTypes; use super::assembly::{self, structural_traits, Candidate}; @@ -247,7 +247,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { assoc_def.defining_node, ); - if !check_args_compatible(tcx, assoc_def.item, args) { + if !tcx.check_args_compatible(assoc_def.item.def_id, args) { return error_response( ecx, "associated item has mismatched generic item arguments", diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 3ab4872fffee..2c8116b779b4 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -61,12 +61,12 @@ pub use self::specialize::{ pub use self::structural_match::search_for_structural_match_violation; pub use self::structural_normalize::StructurallyNormalizeExt; pub use self::util::elaborate; -pub use self::util::{ - check_args_compatible, supertrait_def_ids, supertraits, transitive_bounds, - transitive_bounds_that_define_assoc_item, SupertraitDefIds, -}; pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo}; pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices}; +pub use self::util::{ + supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item, + SupertraitDefIds, +}; pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer}; pub use rustc_infer::traits::*; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c33e24b1094d..9d744d9a0321 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2,7 +2,6 @@ use std::ops::ControlFlow; -use super::check_args_compatible; use super::specialization_graph; use super::translate_args; use super::util; @@ -2030,7 +2029,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( } else { ty.map_bound(|ty| ty.into()) }; - if !check_args_compatible(tcx, assoc_ty.item, args) { + if !tcx.check_args_compatible(assoc_ty.item.def_id, args) { let err = Ty::new_error_with_message( tcx, obligation.cause.span, diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 50cc0ed90fb2..d29fc7921bcb 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -344,46 +344,6 @@ pub enum TupleArgumentsFlag { No, } -// Verify that the trait item and its implementation have compatible args lists -pub fn check_args_compatible<'tcx>( - tcx: TyCtxt<'tcx>, - assoc_item: ty::AssocItem, - args: ty::GenericArgsRef<'tcx>, -) -> bool { - fn check_args_compatible_inner<'tcx>( - tcx: TyCtxt<'tcx>, - generics: &'tcx ty::Generics, - args: &'tcx [ty::GenericArg<'tcx>], - ) -> bool { - if generics.count() != args.len() { - return false; - } - - let (parent_args, own_args) = args.split_at(generics.parent_count); - - if let Some(parent) = generics.parent - && let parent_generics = tcx.generics_of(parent) - && !check_args_compatible_inner(tcx, parent_generics, parent_args) - { - return false; - } - - for (param, arg) in std::iter::zip(&generics.params, own_args) { - match (¶m.kind, arg.unpack()) { - (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_)) - | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_)) - | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {} - _ => return false, - } - } - - true - } - - let generics = tcx.generics_of(assoc_item.def_id); - check_args_compatible_inner(tcx, generics, args) -} - /// Executes `f` on `value` after replacing all escaping bound variables with placeholders /// and then replaces these placeholders with the original bound variables in the result. /// diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index fc16edc6d130..a652bb781161 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -7,7 +7,6 @@ use rustc_middle::ty::util::{CheckRegions, NotUniqueParam}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::Span; -use rustc_trait_selection::traits::check_args_compatible; use crate::errors::{DuplicateArg, NotParam}; @@ -250,7 +249,7 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { ty::GenericArgs::identity_for_item(self.tcx, parent), ); - if check_args_compatible(self.tcx, assoc, impl_args) { + if self.tcx.check_args_compatible(assoc.def_id, impl_args) { self.tcx .type_of(assoc.def_id) .instantiate(self.tcx, impl_args) From 657dadf2cc20d7d48643a300c23388ef026c8c83 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Mar 2024 12:10:47 -0400 Subject: [PATCH 45/51] Simplify some cfging --- compiler/rustc_middle/src/ty/context.rs | 12 +++++++----- compiler/rustc_middle/src/ty/sty.rs | 16 ++++------------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index df792b87056c..09fae0fdd351 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2016,7 +2016,12 @@ impl<'tcx> TyCtxt<'tcx> { true } - pub fn assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) { + pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) { + #[cfg(not(debug_assertions))] + { + return; + } + if !self.check_args_compatible(def_id, args) { if let DefKind::AssocTy = self.def_kind(def_id) && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) @@ -2040,10 +2045,7 @@ impl<'tcx> TyCtxt<'tcx> { args: impl IntoIterator>>, ) -> GenericArgsRef<'tcx> { let args = self.mk_args_from_iter(args.into_iter().map(Into::into)); - #[cfg(debug_assertions)] - { - self.assert_args_compatible(_def_id, args); - } + self.debug_assert_args_compatible(_def_id, args); args } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index dc1ad1da7e1f..30997d1350d9 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1624,9 +1624,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { - if cfg!(debug_assertions) { - tcx.assert_args_compatible(def.did(), args); - } + tcx.debug_assert_args_compatible(def.did(), args); Ty::new(tcx, Adt(def, args)) } @@ -1707,9 +1705,7 @@ impl<'tcx> Ty<'tcx> { def_id: DefId, closure_args: GenericArgsRef<'tcx>, ) -> Ty<'tcx> { - if cfg!(debug_assertions) { - tcx.assert_args_compatible(def_id, closure_args); - } + tcx.debug_assert_args_compatible(def_id, closure_args); Ty::new(tcx, Closure(def_id, closure_args)) } @@ -1719,9 +1715,7 @@ impl<'tcx> Ty<'tcx> { def_id: DefId, closure_args: GenericArgsRef<'tcx>, ) -> Ty<'tcx> { - if cfg!(debug_assertions) { - tcx.assert_args_compatible(def_id, closure_args); - } + tcx.debug_assert_args_compatible(def_id, closure_args); Ty::new(tcx, CoroutineClosure(def_id, closure_args)) } @@ -1731,9 +1725,7 @@ impl<'tcx> Ty<'tcx> { def_id: DefId, coroutine_args: GenericArgsRef<'tcx>, ) -> Ty<'tcx> { - if cfg!(debug_assertions) { - tcx.assert_args_compatible(def_id, coroutine_args); - } + tcx.debug_assert_args_compatible(def_id, coroutine_args); Ty::new(tcx, Coroutine(def_id, coroutine_args)) } From 03163ef9d99a2717edd976174a847293b6f1c8cb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Mar 2024 12:17:21 -0400 Subject: [PATCH 46/51] Don't fill non-ty args with ty::Error --- .../src/hir_ty_lowering/object_safety.rs | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index d3ca35ba481e..97ba946b7e01 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -6,9 +6,10 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::fold::BottomUpFolder; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{DynKind, ToPredicate}; -use rustc_span::Span; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits::error_reporting::report_object_safety_error; use rustc_trait_selection::traits::{self, hir_ty_lowering_object_safety_violations}; @@ -228,12 +229,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if arg == dummy_self.into() { let param = &generics.params[index]; missing_type_params.push(param.name); - return Ty::new_misc_error(tcx).into(); + Ty::new_misc_error(tcx).into() } else if arg.walk().any(|arg| arg == dummy_self.into()) { references_self = true; - return Ty::new_misc_error(tcx).into(); + let guar = tcx.dcx().span_delayed_bug( + span, + "trait object trait bounds reference `Self`", + ); + replace_dummy_self_with_error(tcx, arg, guar) + } else { + arg } - arg }) .collect(); let args = tcx.mk_args(&args); @@ -288,18 +294,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let guar = tcx .dcx() .span_delayed_bug(span, "trait object projection bounds reference `Self`"); - let args: Vec<_> = b - .projection_ty - .args - .iter() - .map(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return Ty::new_error(tcx, guar).into(); - } - arg - }) - .collect(); - b.projection_ty.args = tcx.mk_args(&args); + b.projection_ty = replace_dummy_self_with_error(tcx, b.projection_ty, guar); } ty::ExistentialProjection::erase_self_ty(tcx, b) @@ -357,3 +352,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_dynamic(tcx, existential_predicates, region_bound, representation) } } + +fn replace_dummy_self_with_error<'tcx, T: TypeFoldable>>( + tcx: TyCtxt<'tcx>, + t: T, + guar: ErrorGuaranteed, +) -> T { + t.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| { + if ty == tcx.types.trait_object_dummy_self { Ty::new_error(tcx, guar) } else { ty } + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }) +} From bd8ca780a513a42fe635c6d099ec6f4ba5c22221 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Mar 2024 12:34:15 -0400 Subject: [PATCH 47/51] Fix up error message for debug_assert_args_compat for IATs --- compiler/rustc_middle/src/ty/context.rs | 50 +++++++++++++++---------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 09fae0fdd351..b8d68c1b8be4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2016,24 +2016,36 @@ impl<'tcx> TyCtxt<'tcx> { true } + /// With `cfg(debug_assertions)`, assert that args are compatible with their generics, + /// and print out the args if not. pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) { - #[cfg(not(debug_assertions))] - { - return; - } - - if !self.check_args_compatible(def_id, args) { - if let DefKind::AssocTy = self.def_kind(def_id) - && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) - { - bug!() - } else { - bug!( - "args not compatible with generics for {}: args={:#?}, generics={:#?}", - self.def_path_str(def_id), - args, - ty::GenericArgs::identity_for_item(self, def_id) - ); + if cfg!(debug_assertions) { + if !self.check_args_compatible(def_id, args) { + if let DefKind::AssocTy = self.def_kind(def_id) + && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) + { + bug!( + "args not compatible with generics for {}: args={:#?}, generics={:#?}", + self.def_path_str(def_id), + args, + // Make `[Self, GAT_ARGS...]` (this could be simplified) + self.mk_args_from_iter( + [self.types.self_param.into()].into_iter().chain( + self.generics_of(def_id) + .own_args(ty::GenericArgs::identity_for_item(self, def_id)) + .iter() + .copied() + ) + ) + ); + } else { + bug!( + "args not compatible with generics for {}: args={:#?}, generics={:#?}", + self.def_path_str(def_id), + args, + ty::GenericArgs::identity_for_item(self, def_id) + ); + } } } } @@ -2041,11 +2053,11 @@ impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub(crate) fn check_and_mk_args( self, - _def_id: DefId, + def_id: DefId, args: impl IntoIterator>>, ) -> GenericArgsRef<'tcx> { let args = self.mk_args_from_iter(args.into_iter().map(Into::into)); - self.debug_assert_args_compatible(_def_id, args); + self.debug_assert_args_compatible(def_id, args); args } From b40ea03f8a9a94c294679b9f261b86ded120454f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 3 Apr 2024 17:49:59 +0300 Subject: [PATCH 48/51] rustc_index: Add a `ZERO` constant to index types It is commonly used. --- compiler/rustc_ast_lowering/src/index.rs | 4 ++-- compiler/rustc_ast_lowering/src/item.rs | 4 ++-- compiler/rustc_ast_lowering/src/lib.rs | 8 ++++---- compiler/rustc_borrowck/src/borrow_set.rs | 2 +- .../src/intrinsics/llvm_x86.rs | 2 +- compiler/rustc_codegen_cranelift/src/vtable.rs | 2 +- .../src/graph/dominators/mod.rs | 8 ++++---- compiler/rustc_hir/src/hir.rs | 5 ++--- compiler/rustc_hir/src/hir_id.rs | 6 +++--- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- compiler/rustc_hir_analysis/src/check/intrinsic.rs | 6 +++--- compiler/rustc_hir_analysis/src/check/intrinsicck.rs | 4 ++-- .../rustc_hir_analysis/src/hir_ty_lowering/errors.rs | 2 +- compiler/rustc_hir_typeck/src/check.rs | 2 +- compiler/rustc_hir_typeck/src/intrinsicck.rs | 2 +- compiler/rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_hir_typeck/src/upvar.rs | 5 +---- compiler/rustc_index_macros/src/newtype.rs | 3 +++ compiler/rustc_middle/src/hir/map/mod.rs | 5 ++--- compiler/rustc_middle/src/infer/canonical.rs | 2 +- compiler/rustc_middle/src/mir/coverage.rs | 4 ++-- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_middle/src/ty/typeck_results.rs | 4 ++-- compiler/rustc_mir_build/src/build/custom/parse.rs | 2 +- compiler/rustc_mir_build/src/build/expr/as_rvalue.rs | 2 +- compiler/rustc_mir_build/src/build/scope.rs | 2 +- compiler/rustc_mir_dataflow/src/elaborate_drops.rs | 10 +++++----- compiler/rustc_mir_transform/src/coroutine.rs | 10 +++++----- .../rustc_mir_transform/src/elaborate_box_derefs.rs | 12 +++++------- compiler/rustc_mir_transform/src/gvn.rs | 2 +- .../rustc_mir_transform/src/known_panics_lint.rs | 12 +++++------- compiler/rustc_mir_transform/src/simplify.rs | 2 +- compiler/rustc_query_system/src/dep_graph/graph.rs | 2 +- compiler/rustc_resolve/src/imports.rs | 6 +++--- compiler/rustc_span/src/def_id.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 4 ++-- compiler/rustc_span/src/source_map/tests.rs | 2 +- .../rustc_trait_selection/src/traits/coherence.rs | 6 +----- compiler/rustc_ty_utils/src/layout.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 2 +- 42 files changed, 80 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index a1164008d0da..aaa1c09148b1 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -3,7 +3,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap}; use rustc_hir::intravisit::Visitor; use rustc_hir::*; -use rustc_index::{Idx, IndexVec}; +use rustc_index::IndexVec; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; use rustc_span::{Span, DUMMY_SP}; @@ -31,7 +31,7 @@ pub(super) fn index_hir<'hir>( bodies: &SortedMap>, num_nodes: usize, ) -> (IndexVec>, LocalDefIdMap) { - let zero_id = ItemLocalId::new(0); + let zero_id = ItemLocalId::ZERO; let err_node = ParentedNode { parent: zero_id, node: Node::Err(item.span()) }; let mut nodes = IndexVec::from_elem_n(err_node, num_nodes); // This node's parent should never be accessed: the owner's parent is computed by the diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c9786328565b..abfea6078f21 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -11,7 +11,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::PredicateOrigin; -use rustc_index::{Idx, IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::edit_distance::find_best_match_for_name; @@ -563,7 +563,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs); if let Some(attrs) = attrs { - this.attrs.insert(hir::ItemLocalId::new(0), attrs); + this.attrs.insert(hir::ItemLocalId::ZERO, attrs); } let item = hir::Item { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 833b0e9b5679..8cf347bfa966 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -157,7 +157,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { attrs: SortedMap::default(), children: Vec::default(), current_hir_id_owner: hir::CRATE_OWNER_ID, - item_local_id_counter: hir::ItemLocalId::new(0), + item_local_id_counter: hir::ItemLocalId::ZERO, node_id_to_local_id: Default::default(), trait_map: Default::default(), @@ -583,7 +583,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s. // Always allocate the first `HirId` for the owner itself. - let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::new(0)); + let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO); debug_assert_eq!(_old, None); let item = f(self); @@ -677,7 +677,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { v.insert(local_id); self.item_local_id_counter.increment_by(1); - assert_ne!(local_id, hir::ItemLocalId::new(0)); + assert_ne!(local_id, hir::ItemLocalId::ZERO); if let Some(def_id) = self.opt_local_def_id(ast_node_id) { self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); } @@ -696,7 +696,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn next_id(&mut self) -> hir::HirId { let owner = self.current_hir_id_owner; let local_id = self.item_local_id_counter; - assert_ne!(local_id, hir::ItemLocalId::new(0)); + assert_ne!(local_id, hir::ItemLocalId::ZERO); self.item_local_id_counter.increment_by(1); hir::HirId { owner, local_id } } diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 6a683d129ded..a38dd286be51 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -159,7 +159,7 @@ impl<'tcx> BorrowSet<'tcx> { } pub(crate) fn indices(&self) -> impl Iterator { - BorrowIndex::from_usize(0)..BorrowIndex::from_usize(self.len()) + BorrowIndex::ZERO..BorrowIndex::from_usize(self.len()) } pub(crate) fn iter_enumerated(&self) -> impl Iterator)> { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index 1615dc5de697..8df83c706a10 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -1393,7 +1393,7 @@ fn llvm_add_sub<'tcx>( // c + carry -> c + first intermediate carry or borrow respectively let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b); - let c = int0.value_field(fx, FieldIdx::new(0)); + let c = int0.value_field(fx, FieldIdx::ZERO); let cb0 = int0.value_field(fx, FieldIdx::new(1)).load_scalar(fx); // c + carry -> c + second intermediate carry or borrow respectively diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index 86ebf37d105f..04e24320f913 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -61,7 +61,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>( if ty.is_dyn_star() { let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty); let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout); - let ptr = dyn_star.place_field(fx, FieldIdx::new(0)).to_ptr(); + let ptr = dyn_star.place_field(fx, FieldIdx::ZERO).to_ptr(); let vtable = dyn_star.place_field(fx, FieldIdx::new(1)).to_cvalue(fx).load_scalar(fx); break 'block (ptr, vtable); diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index a45f1dd72a12..30e240cf85b8 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -72,7 +72,7 @@ fn dominators_impl(graph: &G) -> Inner { IndexVec::with_capacity(graph.num_nodes()); let mut stack = vec![PreOrderFrame { - pre_order_idx: PreorderIndex::new(0), + pre_order_idx: PreorderIndex::ZERO, iter: graph.successors(graph.start_node()), }]; let mut pre_order_to_real: IndexVec = @@ -80,8 +80,8 @@ fn dominators_impl(graph: &G) -> Inner { let mut real_to_pre_order: IndexVec> = IndexVec::from_elem_n(None, graph.num_nodes()); pre_order_to_real.push(graph.start_node()); - parent.push(PreorderIndex::new(0)); // the parent of the root node is the root for now. - real_to_pre_order[graph.start_node()] = Some(PreorderIndex::new(0)); + parent.push(PreorderIndex::ZERO); // the parent of the root node is the root for now. + real_to_pre_order[graph.start_node()] = Some(PreorderIndex::ZERO); let mut post_order_idx = 0; // Traverse the graph, collecting a number of things: @@ -111,7 +111,7 @@ fn dominators_impl(graph: &G) -> Inner { let reachable_vertices = pre_order_to_real.len(); - let mut idom = IndexVec::from_elem_n(PreorderIndex::new(0), reachable_vertices); + let mut idom = IndexVec::from_elem_n(PreorderIndex::ZERO, reachable_vertices); let mut semi = IndexVec::from_fn_n(std::convert::identity, reachable_vertices); let mut label = semi.clone(); let mut bucket = IndexVec::from_elem_n(vec![], reachable_vertices); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a0f86565929b..013bb24a7f23 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -846,9 +846,8 @@ pub struct OwnerNodes<'tcx> { impl<'tcx> OwnerNodes<'tcx> { pub fn node(&self) -> OwnerNode<'tcx> { - use rustc_index::Idx; // Indexing must ensure it is an OwnerNode. - self.nodes[ItemLocalId::new(0)].node.as_owner().unwrap() + self.nodes[ItemLocalId::ZERO].node.as_owner().unwrap() } } @@ -856,7 +855,7 @@ impl fmt::Debug for OwnerNodes<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OwnerNodes") // Do not print all the pointers to all the nodes, as it would be unreadable. - .field("node", &self.nodes[ItemLocalId::from_u32(0)]) + .field("node", &self.nodes[ItemLocalId::ZERO]) .field( "parents", &self diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index d339075c171d..0341a482fa8c 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -17,7 +17,7 @@ impl Debug for OwnerId { impl From for HirId { fn from(owner: OwnerId) -> HirId { - HirId { owner, local_id: ItemLocalId::from_u32(0) } + HirId { owner, local_id: ItemLocalId::ZERO } } } @@ -110,7 +110,7 @@ impl HirId { #[inline] pub fn make_owner(owner: LocalDefId) -> Self { - Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::from_u32(0) } + Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::ZERO } } pub fn index(self) -> (usize, usize) { @@ -172,6 +172,6 @@ unsafe impl StableOrd for ItemLocalId { /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`. pub const CRATE_HIR_ID: HirId = - HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) }; + HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::ZERO }; pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID }; diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a880445a27c1..739a70869923 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -899,7 +899,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit(); return; } - let e = fields[FieldIdx::from_u32(0)].ty(tcx, args); + let e = fields[FieldIdx::ZERO].ty(tcx, args); if !fields.iter().all(|f| f.ty(tcx, args) == e) { struct_span_code_err!(tcx.dcx(), sp, E0076, "SIMD vector should be homogeneous") .with_span_label(sp, "SIMD elements must have the same type") diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 00a0fca49072..0dcd98fdec0f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -183,7 +183,7 @@ pub fn check_intrinsic_type( let region = ty::Region::new_bound( tcx, ty::INNERMOST, - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }, + ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BrAnon }, ); let env_region = ty::Region::new_bound( tcx, @@ -495,7 +495,7 @@ pub fn check_intrinsic_type( ); let discriminant_def_id = assoc_items[0]; - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }; + let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BrAnon }; ( 1, 0, @@ -555,7 +555,7 @@ pub fn check_intrinsic_type( } sym::raw_eq => { - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }; + let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BrAnon }; let param_ty_lhs = Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0)); let br = ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon }; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index df4db3ec3fbd..1958a80d47c1 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize), ty::Adt(adt, args) if adt.repr().simd() => { let fields = &adt.non_enum_variant().fields; - let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, args); + let elem_ty = fields[FieldIdx::ZERO].ty(self.tcx, args); let (size, ty) = match elem_ty.kind() { ty::Array(ty, len) => { @@ -146,7 +146,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { "expected first field of `MaybeUnit` to be `ManuallyDrop`" ); let fields = &ty.non_enum_variant().fields; - let ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, args); + let ty = fields[FieldIdx::ZERO].ty(self.tcx, args); self.get_asm_ty(ty) } _ => self.get_asm_ty(ty), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 7a0890e50dac..70f09dd61758 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -628,7 +628,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let projection_ty = pred.skip_binder().projection_ty; let args_with_infer_self = tcx.mk_args_from_iter( - std::iter::once(Ty::new_var(tcx, ty::TyVid::from_u32(0)).into()) + std::iter::once(Ty::new_var(tcx, ty::TyVid::ZERO).into()) .chain(projection_ty.args.iter().skip(1)), ); diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 5841392dbcf1..59a043d1d699 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -182,7 +182,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> ty::Region::new_bound( tcx, ty::INNERMOST, - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }, + ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BrAnon }, ), panic_info_ty, ); diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 9e3867e630d4..62711e40049a 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -17,7 +17,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { let data_idx; let one = VariantIdx::new(1); - let zero = VariantIdx::new(0); + let zero = VariantIdx::ZERO; if def.variant(zero).fields.is_empty() { data_idx = one; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 12f522d1adcf..a199f57aad99 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -774,7 +774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let projection_ty = pred.skip_binder().projection_ty; let args_with_infer_self = tcx.mk_args_from_iter( - iter::once(Ty::new_var(tcx, ty::TyVid::from_u32(0)).into()) + iter::once(Ty::new_var(tcx, ty::TyVid::ZERO).into()) .chain(projection_ty.args.iter().skip(1)), ); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 54344adaabd2..72e5b1ed95bf 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -343,10 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let closure_env_region: ty::Region<'_> = ty::Region::new_bound( self.tcx, ty::INNERMOST, - ty::BoundRegion { - var: ty::BoundVar::from_usize(0), - kind: ty::BoundRegionKind::BrEnv, - }, + ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::BrEnv }, ); let tupled_upvars_ty_for_borrow = Ty::new_tup_from_iter( self.tcx, diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs index e5c2ba424834..fe9a048734fc 100644 --- a/compiler/rustc_index_macros/src/newtype.rs +++ b/compiler/rustc_index_macros/src/newtype.rs @@ -174,6 +174,9 @@ impl Parse for Newtype { /// Maximum value the index can take. #vis const MAX: Self = Self::from_u32(#max); + /// Zero value of the index. + #vis const ZERO: Self = Self::from_u32(0); + /// Creates a new index from a given `usize`. /// /// # Panics diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 53cb05198cd6..72f849b534a8 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -13,7 +13,6 @@ use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit::Visitor; use rustc_hir::*; -use rustc_index::Idx; use rustc_middle::hir::nested_filter; use rustc_span::def_id::StableCrateId; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -69,7 +68,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { fn next(&mut self) -> Option { if self.current_id.local_id.index() != 0 { - self.current_id.local_id = ItemLocalId::new(0); + self.current_id.local_id = ItemLocalId::ZERO; let node = self.map.tcx.hir_owner_node(self.current_id.owner); return Some((self.current_id.owner, node)); } @@ -133,7 +132,7 @@ impl<'tcx> TyCtxt<'tcx> { /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`]. pub fn parent_hir_id(self, hir_id: HirId) -> HirId { let HirId { owner, local_id } = hir_id; - if local_id == ItemLocalId::from_u32(0) { + if local_id == ItemLocalId::ZERO { self.hir_owner_parent(owner) } else { let parent_local_id = self.hir_owner_nodes(owner).nodes[local_id].parent; diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 7b65c11bc3c8..acea89e4aabe 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -82,7 +82,7 @@ impl CanonicalVarValues<'_> { } pub fn is_identity_modulo_regions(&self) -> bool { - let mut var = ty::BoundVar::from_u32(0); + let mut var = ty::BoundVar::ZERO; for arg in self.var_values { match arg.unpack() { ty::GenericArgKind::Lifetime(r) => { diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 588aa1f40d79..0c91dc6d3c68 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -34,7 +34,7 @@ rustc_index::newtype_index! { } impl CounterId { - pub const START: Self = Self::from_u32(0); + pub const START: Self = Self::ZERO; } rustc_index::newtype_index! { @@ -56,7 +56,7 @@ rustc_index::newtype_index! { } impl ExpressionId { - pub const START: Self = Self::from_u32(0); + pub const START: Self = Self::ZERO; } /// Enum that can hold a constant zero value, the ID of an physical coverage diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4e1baaec39ea..ad59778f58fe 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1324,7 +1324,7 @@ impl VariantDef { pub fn single_field(&self) -> &FieldDef { assert!(self.fields.len() == 1); - &self.fields[FieldIdx::from_u32(0)] + &self.fields[FieldIdx::ZERO] } /// Returns the last field in this variant, if present. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5ff98dc8c873..2a898430ce9f 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2589,7 +2589,7 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> { ty::BrAnon | ty::BrEnv => r, _ => { // Index doesn't matter, since this is just for naming and these never get bound - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind }; + let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind }; *self .region_map .entry(br) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b5e619f1e2a3..765f65a04db5 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1954,7 +1954,7 @@ impl<'tcx> Ty<'tcx> { Adt(def, args) => { assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type"); let variant = def.non_enum_variant(); - let f0_ty = variant.fields[FieldIdx::from_u32(0)].ty(tcx, args); + let f0_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args); match f0_ty.kind() { // If the first field is an array, we assume it is the only field and its diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index d60926bf796d..0d74524276fa 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -19,7 +19,7 @@ use rustc_hir::{ hir_id::OwnerId, BindingAnnotation, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability, }; -use rustc_index::{Idx, IndexVec}; +use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_middle::mir::FakeReadCause; use rustc_session::Session; @@ -680,7 +680,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { return false; } - iter::zip(user_args.args, BoundVar::new(0)..).all(|(kind, cvar)| { + iter::zip(user_args.args, BoundVar::ZERO..).all(|(kind, cvar)| { match kind.unpack() { GenericArgKind::Type(ty) => match ty.kind() { ty::Bound(debruijn, b) => { diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index a6f9caada2d1..0384b9bc154e 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -215,7 +215,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_local_decls(&mut self, mut stmts: impl Iterator) -> PResult<()> { let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?; - self.local_map.insert(ret_var, Local::from_u32(0)); + self.local_map.insert(ret_var, Local::ZERO); for stmt in stmts { let (var, ty, span) = self.parse_let_statement(stmt)?; diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 00600f354ca5..260ab058e600 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -573,7 +573,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { result_value, Rvalue::CheckedBinaryOp(op, Box::new((lhs.to_copy(), rhs.to_copy()))), ); - let val_fld = FieldIdx::new(0); + let val_fld = FieldIdx::ZERO; let of_fld = FieldIdx::new(1); let tcx = self.tcx; diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 9ac8c1b44174..2d31e84aba7d 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -190,7 +190,7 @@ rustc_index::newtype_index! { struct DropIdx {} } -const ROOT_NODE: DropIdx = DropIdx::from_u32(0); +const ROOT_NODE: DropIdx = DropIdx::ZERO; /// A tree of drops that we have deferred lowering. It's used for: /// diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 256add3153c9..d63db6ea8edd 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -420,14 +420,14 @@ where ) -> BasicBlock { // drop glue is sent straight to codegen // box cannot be directly dereferenced - let unique_ty = adt.non_enum_variant().fields[FieldIdx::new(0)].ty(self.tcx(), args); + let unique_ty = adt.non_enum_variant().fields[FieldIdx::ZERO].ty(self.tcx(), args); let unique_variant = unique_ty.ty_adt_def().unwrap().non_enum_variant(); - let nonnull_ty = unique_variant.fields[FieldIdx::from_u32(0)].ty(self.tcx(), args); + let nonnull_ty = unique_variant.fields[FieldIdx::ZERO].ty(self.tcx(), args); let ptr_ty = Ty::new_imm_ptr(self.tcx(), args[0].expect_ty()); - let unique_place = self.tcx().mk_place_field(self.place, FieldIdx::new(0), unique_ty); - let nonnull_place = self.tcx().mk_place_field(unique_place, FieldIdx::new(0), nonnull_ty); - let ptr_place = self.tcx().mk_place_field(nonnull_place, FieldIdx::new(0), ptr_ty); + let unique_place = self.tcx().mk_place_field(self.place, FieldIdx::ZERO, unique_ty); + let nonnull_place = self.tcx().mk_place_field(unique_place, FieldIdx::ZERO, nonnull_ty); + let ptr_place = self.tcx().mk_place_field(nonnull_place, FieldIdx::ZERO, ptr_ty); let interior = self.tcx().mk_place_deref(ptr_place); let interior_path = self.elaborator.deref_subpath(self.path); diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index c3f175f150d2..e2a911f0dc7d 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -168,7 +168,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { Place { local: SELF_ARG, projection: self.tcx().mk_place_elems(&[ProjectionElem::Field( - FieldIdx::new(0), + FieldIdx::ZERO, self.ref_coroutine_ty, )]), }, @@ -267,7 +267,7 @@ impl<'tcx> TransformVisitor<'tcx> { Rvalue::Aggregate( Box::new(AggregateKind::Adt( option_def_id, - VariantIdx::from_usize(0), + VariantIdx::ZERO, self.tcx.mk_args(&[self.old_yield_ty.into()]), None, None, @@ -329,7 +329,7 @@ impl<'tcx> TransformVisitor<'tcx> { Rvalue::Aggregate( Box::new(AggregateKind::Adt( poll_def_id, - VariantIdx::from_usize(0), + VariantIdx::ZERO, args, None, None, @@ -358,7 +358,7 @@ impl<'tcx> TransformVisitor<'tcx> { Rvalue::Aggregate( Box::new(AggregateKind::Adt( option_def_id, - VariantIdx::from_usize(0), + VariantIdx::ZERO, args, None, None, @@ -420,7 +420,7 @@ impl<'tcx> TransformVisitor<'tcx> { Rvalue::Aggregate( Box::new(AggregateKind::Adt( coroutine_state_def_id, - VariantIdx::from_usize(0), + VariantIdx::ZERO, args, None, None, diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 96943435bab8..318674f24e7a 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -3,7 +3,6 @@ //! Box is not actually a pointer so it is incorrect to dereference it directly. use rustc_hir::def_id::DefId; -use rustc_index::Idx; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; @@ -32,9 +31,9 @@ pub fn build_projection<'tcx>( ptr_ty: Ty<'tcx>, ) -> [PlaceElem<'tcx>; 3] { [ - PlaceElem::Field(FieldIdx::new(0), unique_ty), - PlaceElem::Field(FieldIdx::new(0), nonnull_ty), - PlaceElem::Field(FieldIdx::new(0), ptr_ty), + PlaceElem::Field(FieldIdx::ZERO, unique_ty), + PlaceElem::Field(FieldIdx::ZERO, nonnull_ty), + PlaceElem::Field(FieldIdx::ZERO, ptr_ty), ] } @@ -91,15 +90,14 @@ pub struct ElaborateBoxDerefs; impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if let Some(def_id) = tcx.lang_items().owned_box() { - let unique_did = - tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::from_u32(0)].did; + let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did; let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() else { span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique") }; - let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::from_u32(0)].did; + let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did; let patch = MirPatch::new(body); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 59d6d89cf1fe..d4f736d2a50f 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -355,7 +355,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } fn insert_tuple(&mut self, values: Vec) -> VnIndex { - self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::from_u32(0), values)) + self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::ZERO, values)) } #[instrument(level = "trace", skip(self), ret)] diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index a20958e74dff..2218154ea5e7 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -13,7 +13,7 @@ use rustc_const_eval::interpret::{ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::DefKind; use rustc_hir::HirId; -use rustc_index::{bit_set::BitSet, Idx, IndexVec}; +use rustc_index::{bit_set::BitSet, IndexVec}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; @@ -124,10 +124,8 @@ impl<'tcx> Value<'tcx> { fields.ensure_contains_elem(*idx, || Value::Uninit) } (PlaceElem::Field(..), val @ Value::Uninit) => { - *val = Value::Aggregate { - variant: VariantIdx::new(0), - fields: Default::default(), - }; + *val = + Value::Aggregate { variant: VariantIdx::ZERO, fields: Default::default() }; val.project_mut(&[*proj])? } _ => return None, @@ -572,7 +570,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { self.use_ecx(|this| this.ecx.overflowing_binary_op(bin_op, &left, &right))?; let overflowed = ImmTy::from_bool(overflowed, self.tcx); Value::Aggregate { - variant: VariantIdx::new(0), + variant: VariantIdx::ZERO, fields: [Value::from(val), overflowed.into()].into_iter().collect(), } } @@ -607,7 +605,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | AggregateKind::Tuple | AggregateKind::Closure(_, _) | AggregateKind::Coroutine(_, _) - | AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0), + | AggregateKind::CoroutineClosure(_, _) => VariantIdx::ZERO, }, } } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 14772080ce5f..5bbe3bb747fd 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -415,7 +415,7 @@ fn make_local_map( used_locals: &UsedLocals, ) -> IndexVec> { let mut map: IndexVec> = IndexVec::from_elem(None, local_decls); - let mut used = Local::new(0); + let mut used = Local::ZERO; for alive_index in local_decls.indices() { // `is_used` treats the `RETURN_PLACE` and arguments as used. diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 9f067273f358..f223f64f2c5d 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -40,7 +40,7 @@ rustc_index::newtype_index! { } impl DepNodeIndex { - const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::from_u32(0); + const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::ZERO; pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1); } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 48711f435186..76fe36a77cb8 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -532,7 +532,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut seen_spans = FxHashSet::default(); let mut errors = vec![]; - let mut prev_root_id: NodeId = NodeId::from_u32(0); + let mut prev_root_id: NodeId = NodeId::ZERO; let determined_imports = mem::take(&mut self.determined_imports); let indeterminate_imports = mem::take(&mut self.indeterminate_imports); @@ -556,8 +556,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - if prev_root_id.as_u32() != 0 - && prev_root_id.as_u32() != import.root_id.as_u32() + if prev_root_id != NodeId::ZERO + && prev_root_id != import.root_id && !errors.is_empty() { // In the case of a new import line, throw a diagnostic message diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 8f721bac9514..8925b7a42d48 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -22,7 +22,7 @@ rustc_index::newtype_index! { /// Item definitions in the currently-compiled crate would have the `CrateNum` /// `LOCAL_CRATE` in their `DefId`. -pub const LOCAL_CRATE: CrateNum = CrateNum::from_u32(0); +pub const LOCAL_CRATE: CrateNum = CrateNum::ZERO; impl CrateNum { #[inline] diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 37fea6c122c7..1df2b357ac12 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -165,7 +165,7 @@ pub enum Transparency { impl LocalExpnId { /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST. - pub const ROOT: LocalExpnId = LocalExpnId::from_u32(0); + pub const ROOT: LocalExpnId = LocalExpnId::ZERO; #[inline] fn from_raw(idx: ExpnIndex) -> LocalExpnId { @@ -242,7 +242,7 @@ impl ExpnId { /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST. /// Invariant: we do not create any ExpnId with local_id == 0 and krate != 0. pub const fn root() -> ExpnId { - ExpnId { krate: LOCAL_CRATE, local_id: ExpnIndex::from_u32(0) } + ExpnId { krate: LOCAL_CRATE, local_id: ExpnIndex::ZERO } } #[inline] diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 81a9e4706883..dcb02da37192 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -243,7 +243,7 @@ fn t10() { src_hash, stable_id, source_len.to_u32(), - CrateNum::new(0), + CrateNum::ZERO, FreezeLock::new(lines.read().clone()), multibyte_chars, non_narrow_chars, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 6e768b23ef8c..90e337a53b65 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -554,11 +554,7 @@ fn plug_infer_with_placeholders<'tcx>( } } - value.visit_with(&mut PlugInferWithPlaceholder { - infcx, - universe, - var: ty::BoundVar::from_u32(0), - }); + value.visit_with(&mut PlugInferWithPlaceholder { infcx, universe, var: ty::BoundVar::ZERO }); } fn try_prove_negated_where_clause<'tcx>( diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 331970ac3623..dd1f2322c414 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -377,7 +377,7 @@ fn layout_of_uncached<'tcx>( } // Type of the first ADT field: - let f0_ty = fields[FieldIdx::from_u32(0)].ty(tcx, args); + let f0_ty = fields[FieldIdx::ZERO].ty(tcx, args); // Heterogeneous SIMD vectors are not supported: // (should be caught by typeck) diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index c01baa58ae78..45e22b12a8b0 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -314,7 +314,7 @@ rustc_index::newtype_index! { } impl UniverseIndex { - pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0); + pub const ROOT: UniverseIndex = UniverseIndex::ZERO; /// Returns the "next" universe index in order -- this new index /// is considered to extend all previous universes. This From 6edb021fd3655df3848f590005e3a688147d2164 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 4 Apr 2024 01:31:04 +0900 Subject: [PATCH 49/51] Fix target name in NetBSD platform-support doc --- src/doc/rustc/src/platform-support/netbsd.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md index 3891d6d3148d..ef9337befa64 100644 --- a/src/doc/rustc/src/platform-support/netbsd.md +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -13,7 +13,7 @@ are currently defined running NetBSD: | Target name | NetBSD Platform | |--------------------------------|-----------------| -| `amd64-unknown-netbsd` | [amd64 / x86_64 systems](https://wiki.netbsd.org/ports/amd64/) | +| `x86_64-unknown-netbsd` | [amd64 / x86_64 systems](https://wiki.netbsd.org/ports/amd64/) | | `armv7-unknown-netbsd-eabihf` | [32-bit ARMv7 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | | `armv6-unknown-netbsd-eabihf` | [32-bit ARMv6 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | | `aarch64-unknown-netbsd` | [64-bit ARM systems, little-endian](https://wiki.netbsd.org/ports/evbarm/) | @@ -22,7 +22,7 @@ are currently defined running NetBSD: | `i686-unknown-netbsd` | [32-bit i386 with SSE](https://wiki.netbsd.org/ports/i386/) | | `mipsel-unknown-netbsd` | [32-bit mips, requires mips32 cpu support](https://wiki.netbsd.org/ports/evbmips/) | | `powerpc-unknown-netbsd` | [Various 32-bit PowerPC systems, e.g. MacPPC](https://wiki.netbsd.org/ports/macppc/) | -| `riscv64gc-unknown-netbsd` | [64-bit RISC-V](https://wiki.netbsd.org/ports/riscv/) +| `riscv64gc-unknown-netbsd` | [64-bit RISC-V](https://wiki.netbsd.org/ports/riscv/) | | `sparc64-unknown-netbsd` | [Sun UltraSPARC systems](https://wiki.netbsd.org/ports/sparc64/) | All use the "native" `stdc++` library which goes along with the natively @@ -43,7 +43,7 @@ bug reporting system. ## Requirements -The `amd64-unknown-netbsd` artifacts is being distributed by the +The `x86_64-unknown-netbsd` artifacts is being distributed by the rust project. The other targets are built by the designated developers (see above), @@ -95,7 +95,7 @@ capable systems we build and test `firefox` (amd64, i386, aarch64). ## Building Rust programs -Rust ships pre-compiled artifacts for the `amd64-unknown-netbsd` +Rust ships pre-compiled artifacts for the `x86_64-unknown-netbsd` target. For the other systems mentioned above, using the `pkgsrc` route is From b0b7c860e13858cbc344dcf2baf860752e3a2dd3 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 4 Apr 2024 00:10:01 -0400 Subject: [PATCH 50/51] Teach MIR inliner query cycle avoidance about const_eval_select --- .../rustc_mir_transform/src/inline/cycle.rs | 18 ++++++++++++++---- tests/ui/mir/const_eval_select_cycle.rs | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 tests/ui/mir/const_eval_select_cycle.rs diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index f2b6dcac5863..85e74a69cced 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -5,6 +5,7 @@ use rustc_middle::mir::TerminatorKind; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, GenericArgsRef, InstanceDef, TyCtxt}; use rustc_session::Limit; +use rustc_span::sym; // FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking // this query ridiculously often. @@ -164,11 +165,20 @@ pub(crate) fn mir_inliner_callees<'tcx>( let mut calls = FxIndexSet::default(); for bb_data in body.basic_blocks.iter() { let terminator = bb_data.terminator(); - if let TerminatorKind::Call { func, .. } = &terminator.kind { + if let TerminatorKind::Call { func, args: call_args, .. } = &terminator.kind { let ty = func.ty(&body.local_decls, tcx); - let call = match ty.kind() { - ty::FnDef(def_id, args) => (*def_id, *args), - _ => continue, + let ty::FnDef(def_id, generic_args) = ty.kind() else { + continue; + }; + let call = if tcx.is_intrinsic(*def_id, sym::const_eval_select) { + let func = &call_args[2].node; + let ty = func.ty(&body.local_decls, tcx); + let ty::FnDef(def_id, generic_args) = ty.kind() else { + continue; + }; + (*def_id, *generic_args) + } else { + (*def_id, *generic_args) }; calls.insert(call); } diff --git a/tests/ui/mir/const_eval_select_cycle.rs b/tests/ui/mir/const_eval_select_cycle.rs new file mode 100644 index 000000000000..0b84455b2f7f --- /dev/null +++ b/tests/ui/mir/const_eval_select_cycle.rs @@ -0,0 +1,18 @@ +// Regression test for #122659 +//@ build-pass +//@ compile-flags: -O --crate-type=lib + +#![feature(core_intrinsics)] +#![feature(const_eval_select)] + +use std::intrinsics::const_eval_select; + +#[inline] +pub const fn f() { + const_eval_select((), g, g) +} + +#[inline] +pub const fn g() { + const_eval_select((), f, f) +} From 20807c0175450bf5bfab0dcd4ab0238cab8a3eac Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 4 Apr 2024 04:55:34 +0000 Subject: [PATCH 51/51] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 90194ec60386..02e2e6459fbf 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -b688d53a1736c17e49328a706a90829a9937a91a +0accf4ec4c07d23aa86f6a97aeb8797941abc30e