From bb27b051046712c903670f7401a32e990a950f05 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 30 Nov 2021 10:14:50 -0800 Subject: [PATCH 1/8] Separate `RemoveFalseEdges` from `SimplifyBranches` Otherwise dataflow state will propagate along false edges and cause things to be marked as maybe init unnecessarily. These should be separate, since `SimplifyBranches` also makes `if true {} else {}` into a `goto`, which means we wouldn't lint anything in the `else` block. --- compiler/rustc_mir_transform/src/lib.rs | 7 +++-- .../src/remove_false_edges.rs | 29 +++++++++++++++++++ .../src/simplify_branches.rs | 17 ++++------- 3 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/remove_false_edges.rs diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index f9ef314627807..5ae06a3ececdc 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -60,6 +60,7 @@ mod match_branches; mod multiple_return_terminators; mod normalize_array_len; mod nrvo; +mod remove_false_edges; mod remove_noop_landing_pads; mod remove_storage_markers; mod remove_unneeded_drops; @@ -456,7 +457,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[ // Remove all things only needed by analysis - &simplify_branches::SimplifyBranches::new("initial"), + &simplify_branches::SimplifyConstCondition::new("initial"), &remove_noop_landing_pads::RemoveNoopLandingPads, &cleanup_post_borrowck::CleanupNonCodegenStatements, &simplify::SimplifyCfg::new("early-opt"), @@ -515,13 +516,13 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &instcombine::InstCombine, &separate_const_switch::SeparateConstSwitch, &const_prop::ConstProp, - &simplify_branches::SimplifyBranches::new("after-const-prop"), + &simplify_branches::SimplifyConstCondition::new("after-const-prop"), &early_otherwise_branch::EarlyOtherwiseBranch, &simplify_comparison_integral::SimplifyComparisonIntegral, &simplify_try::SimplifyArmIdentity, &simplify_try::SimplifyBranchSame, &dest_prop::DestinationPropagation, - &simplify_branches::SimplifyBranches::new("final"), + &simplify_branches::SimplifyConstCondition::new("final"), &remove_noop_landing_pads::RemoveNoopLandingPads, &simplify::SimplifyCfg::new("final"), &nrvo::RenameReturnPlace, diff --git a/compiler/rustc_mir_transform/src/remove_false_edges.rs b/compiler/rustc_mir_transform/src/remove_false_edges.rs new file mode 100644 index 0000000000000..71f5ccf7e2465 --- /dev/null +++ b/compiler/rustc_mir_transform/src/remove_false_edges.rs @@ -0,0 +1,29 @@ +use rustc_middle::mir::{Body, TerminatorKind}; +use rustc_middle::ty::TyCtxt; + +use crate::MirPass; + +/// Removes `FalseEdge` and `FalseUnwind` terminators from the MIR. +/// +/// These are only needed for borrow checking, and can be removed afterwards. +/// +/// FIXME: This should probably have its own MIR phase. +pub struct RemoveFalseEdges; + +impl<'tcx> MirPass<'tcx> for RemoveFalseEdges { + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + for block in body.basic_blocks_mut() { + let terminator = block.terminator_mut(); + terminator.kind = match terminator.kind { + TerminatorKind::FalseEdge { real_target, .. } => { + TerminatorKind::Goto { target: real_target } + } + TerminatorKind::FalseUnwind { real_target, .. } => { + TerminatorKind::Goto { target: real_target } + } + + _ => continue, + } + } + } +} diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index df90cfa318df0..4b261334f3e54 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -1,22 +1,21 @@ -//! A pass that simplifies branches when their condition is known. - use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use std::borrow::Cow; -pub struct SimplifyBranches { +/// A pass that replaces a branch with a goto when its condition is known. +pub struct SimplifyConstCondition { label: String, } -impl SimplifyBranches { +impl SimplifyConstCondition { pub fn new(label: &str) -> Self { - SimplifyBranches { label: format!("SimplifyBranches-{}", label) } + SimplifyConstCondition { label: format!("SimplifyConstCondition-{}", label) } } } -impl<'tcx> MirPass<'tcx> for SimplifyBranches { +impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } @@ -53,12 +52,6 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { Some(v) if v == expected => TerminatorKind::Goto { target }, _ => continue, }, - TerminatorKind::FalseEdge { real_target, .. } => { - TerminatorKind::Goto { target: real_target } - } - TerminatorKind::FalseUnwind { real_target, .. } => { - TerminatorKind::Goto { target: real_target } - } _ => continue, }; } From d7077073648041ec505629b2f1df9ab800c422e2 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 30 Nov 2021 14:56:26 -0800 Subject: [PATCH 2/8] Add "is" methods for projections to a given index --- compiler/rustc_middle/src/mir/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index a05b8a1da8d7f..9fc12ad4a0b91 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1803,6 +1803,16 @@ impl ProjectionElem { | Self::Downcast(_, _) => false, } } + + /// Returns `true` if this is a `Downcast` projection with the given `VariantIdx`. + pub fn is_downcast_to(&self, v: VariantIdx) -> bool { + matches!(*self, Self::Downcast(_, x) if x == v) + } + + /// Returns `true` if this is a `Field` projection with the given index. + pub fn is_field_to(&self, f: Field) -> bool { + matches!(*self, Self::Field(x, _) if x == f) + } } /// Alias for projections as they appear in places, where the base is a place From 4f7605b6fdb81c1f5be62446f56b25a7cbaa8eeb Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 30 Nov 2021 15:04:49 -0800 Subject: [PATCH 3/8] Add `RemoveUninitDrops` MIR pass --- compiler/rustc_mir_transform/src/lib.rs | 1 + .../src/remove_uninit_drops.rs | 171 ++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 compiler/rustc_mir_transform/src/remove_uninit_drops.rs diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 5ae06a3ececdc..b9d670e651cd4 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -63,6 +63,7 @@ mod nrvo; mod remove_false_edges; mod remove_noop_landing_pads; mod remove_storage_markers; +mod remove_uninit_drops; mod remove_unneeded_drops; mod remove_zsts; mod required_consts; diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs new file mode 100644 index 0000000000000..c219f26732441 --- /dev/null +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -0,0 +1,171 @@ +use rustc_index::bit_set::BitSet; +use rustc_middle::mir::{Body, Field, Rvalue, Statement, StatementKind, TerminatorKind}; +use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef}; +use rustc_mir_dataflow::impls::MaybeInitializedPlaces; +use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; +use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataParamEnv}; + +use crate::MirPass; + +/// Removes `Drop` and `DropAndReplace` terminators whose target is known to be uninitialized at +/// that point. +/// +/// This is redundant with drop elaboration, but we need to do it prior to const-checking, and +/// running const-checking after drop elaboration makes it opimization dependent, causing issues +/// like [#90770]. +/// +/// [#90770]: https://github.com/rust-lang/rust/issues/90770 +pub struct RemoveUninitDrops; + +impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env(body.source.def_id()); + let Ok(move_data) = MoveData::gather_moves(body, tcx, param_env) else { + // We could continue if there are move errors, but there's not much point since our + // init data isn't complete. + return; + }; + + let mdpe = MoveDataParamEnv { move_data, param_env }; + let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) + .into_engine(tcx, body) + .pass_name("remove_uninit_drops") + .iterate_to_fixpoint() + .into_results_cursor(body); + + let mut to_remove = vec![]; + for (bb, block) in body.basic_blocks().iter_enumerated() { + let terminator = block.terminator(); + let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. }) + = &terminator.kind + else { continue }; + + maybe_inits.seek_before_primary_effect(body.terminator_loc(bb)); + + // If there's no move path for the dropped place, it's probably a `Deref`. Let it alone. + let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else { + continue; + }; + + let should_keep = is_needs_drop_and_init( + tcx, + param_env, + maybe_inits.get(), + &mdpe.move_data, + place.ty(body, tcx).ty, + mpi, + ); + if !should_keep { + to_remove.push(bb) + } + } + + for bb in to_remove { + let block = &mut body.basic_blocks_mut()[bb]; + + let (TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. }) + = &block.terminator().kind + else { unreachable!() }; + + // Replace block terminator with `Goto`. + let target = *target; + let old_terminator_kind = std::mem::replace( + &mut block.terminator_mut().kind, + TerminatorKind::Goto { target }, + ); + + // If this is a `DropAndReplace`, we need to emulate the assignment to the return place. + if let TerminatorKind::DropAndReplace { place, value, .. } = old_terminator_kind { + block.statements.push(Statement { + source_info: block.terminator().source_info, + kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value)))), + }); + } + } + } +} + +fn is_needs_drop_and_init( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + maybe_inits: &BitSet, + move_data: &MoveData<'tcx>, + ty: Ty<'tcx>, + mpi: MovePathIndex, +) -> bool { + // No need to look deeper if the root is definitely uninit or if it has no `Drop` impl. + if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, param_env) { + return false; + } + + let field_needs_drop_and_init = |(f, f_ty, mpi)| { + let child = move_path_children_matching(move_data, mpi, |x| x.is_field_to(f)); + let Some(mpi) = child else { + return f_ty.needs_drop(tcx, param_env); + }; + + is_needs_drop_and_init(tcx, param_env, maybe_inits, move_data, f_ty, mpi) + }; + + // This pass is only needed for const-checking, so it doesn't handle as many cases as + // `DropCtxt::open_drop`, since they aren't relevant in a const-context. + match ty.kind() { + ty::Adt(adt, substs) => { + let dont_elaborate = adt.is_union() || adt.is_manually_drop() || adt.has_dtor(tcx); + if dont_elaborate { + return true; + } + + // Look at all our fields, or if we are an enum all our variants and their fields. + // + // If a field's projection *is not* present in `MoveData`, it has the same + // initializedness as its parent (maybe init). + // + // If its projection *is* present in `MoveData`, then the field may have been moved + // from separate from its parent. Recurse. + adt.variants.iter_enumerated().any(|(vid, variant)| { + // Enums have multiple variants, which are discriminated with a `Downcast` projection. + // Structs have a single variant, and don't use a `Downcast` projection. + let mpi = if adt.is_enum() { + let downcast = + move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid)); + let Some(dc_mpi) = downcast else { + return variant_needs_drop(tcx, param_env, substs, variant); + }; + + dc_mpi + } else { + mpi + }; + + variant + .fields + .iter() + .enumerate() + .map(|(f, field)| (Field::from_usize(f), field.ty(tcx, substs), mpi)) + .any(field_needs_drop_and_init) + }) + } + + ty::Tuple(_) => ty + .tuple_fields() + .enumerate() + .map(|(f, f_ty)| (Field::from_usize(f), f_ty, mpi)) + .any(field_needs_drop_and_init), + + _ => true, + } +} + +fn variant_needs_drop( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + substs: SubstsRef<'tcx>, + variant: &VariantDef, +) -> bool { + variant.fields.iter().any(|field| { + let f_ty = field.ty(tcx, substs); + f_ty.needs_drop(tcx, param_env) + }) +} From ce2959da97aa98596ee041a3e42d30e50e3f2d7b Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 30 Nov 2021 15:03:43 -0800 Subject: [PATCH 4/8] Add rationale for `RemoveUnneededDrops` ...since its name is very close to `RemoveUninitDrops`. --- compiler/rustc_mir_transform/src/remove_unneeded_drops.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index c71bc512c31b5..39f78e9555e2f 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -1,4 +1,8 @@ -//! This pass replaces a drop of a type that does not need dropping, with a goto +//! This pass replaces a drop of a type that does not need dropping, with a goto. +//! +//! When the MIR is built, we check `needs_drop` before emitting a `Drop` for a place. This pass is +//! useful because (unlike MIR building) it runs after type checking, so it can make use of +//! `Reveal::All` to provide more precies type information. use crate::MirPass; use rustc_middle::mir::*; From 3e0e8be037f79a8d2da521e75e52795727474beb Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 30 Nov 2021 15:45:16 -0800 Subject: [PATCH 5/8] Handle `DropAndReplace` in const-checking It runs before the real drop elaboration pass. --- .../src/transform/check_consts/post_drop_elaboration.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index 7a2be3c3bad32..c1d47baa40531 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -80,7 +80,8 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { trace!("visit_terminator: terminator={:?} location={:?}", terminator, location); match &terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } => { + mir::TerminatorKind::Drop { place: dropped_place, .. } + | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) { // Instead of throwing a bug, we just return here. This is because we have to @@ -104,11 +105,6 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { } } - mir::TerminatorKind::DropAndReplace { .. } => span_bug!( - terminator.source_info.span, - "`DropAndReplace` should be removed by drop elaboration", - ), - mir::TerminatorKind::Abort | mir::TerminatorKind::Call { .. } | mir::TerminatorKind::Assert { .. } From 58c996c3a768446a39d72265bac626bc0a89adee Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 30 Nov 2021 17:05:40 -0800 Subject: [PATCH 6/8] Move post-elaboration const-checking earlier in the pipeline Instead we run `RemoveFalseEdges` and `RemoveUninitDrops` at the appropriate time. The extra `SimplifyCfg` avoids visiting unreachable blocks during `RemoveUninitDrops`. --- compiler/rustc_mir_transform/src/lib.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b9d670e651cd4..d15ee3e32b785 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -77,7 +77,7 @@ mod simplify_try; mod uninhabited_enum_branching; mod unreachable_prop; -use rustc_const_eval::transform::check_consts; +use rustc_const_eval::transform::check_consts::{self, ConstCx}; use rustc_const_eval::transform::promote_consts; use rustc_const_eval::transform::validate; pub use rustc_const_eval::transform::MirPass; @@ -447,8 +447,20 @@ fn mir_drops_elaborated_and_const_checked<'tcx>( let (body, _) = tcx.mir_promoted(def); let mut body = body.steal(); + // IMPORTANT + remove_false_edges::RemoveFalseEdges.run_pass(tcx, &mut body); + + // Do a little drop elaboration before const-checking if `const_precise_live_drops` is enabled. + // + // FIXME: Can't use `run_passes` for these, since `run_passes` SILENTLY DOES NOTHING IF THE MIR + // PHASE DOESN'T CHANGE. + if check_consts::post_drop_elaboration::checking_enabled(&ConstCx::new(tcx, &body)) { + simplify::SimplifyCfg::new("remove-false-edges").run_pass(tcx, &mut body); + remove_uninit_drops::RemoveUninitDrops.run_pass(tcx, &mut body); + check_consts::post_drop_elaboration::check_live_drops(tcx, &body); + } + run_post_borrowck_cleanup_passes(tcx, &mut body); - check_consts::post_drop_elaboration::check_live_drops(tcx, &body); tcx.alloc_steal_mir(body) } From 9aaca1d38ea3218b7f5030bd486cbbdf8917985b Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 30 Nov 2021 18:54:37 -0800 Subject: [PATCH 7/8] Update MIR opt tests with new name --- ...tch_int.main.SimplifyConstCondition-after-const-prop.diff} | 4 ++-- src/test/mir-opt/const_prop/switch_int.rs | 2 +- src/test/mir-opt/early_otherwise_branch_68867.rs | 2 +- ...wiseBranch.before-SimplifyConstCondition-final.after.diff} | 2 +- ...lify_if.main.SimplifyConstCondition-after-const-prop.diff} | 4 ++-- src/test/mir-opt/simplify_if.rs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) rename src/test/mir-opt/const_prop/{switch_int.main.SimplifyBranches-after-const-prop.diff => switch_int.main.SimplifyConstCondition-after-const-prop.diff} (92%) rename src/test/mir-opt/{early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff => early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff} (99%) rename src/test/mir-opt/{simplify_if.main.SimplifyBranches-after-const-prop.diff => simplify_if.main.SimplifyConstCondition-after-const-prop.diff} (93%) diff --git a/src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff similarity index 92% rename from src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff rename to src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff index 6a5b88c4a7f0d..f2b02551146eb 100644 --- a/src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff +++ b/src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before SimplifyBranches-after-const-prop -+ // MIR for `main` after SimplifyBranches-after-const-prop +- // MIR for `main` before SimplifyConstCondition-after-const-prop ++ // MIR for `main` after SimplifyConstCondition-after-const-prop fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/switch_int.rs:6:11: 6:11 diff --git a/src/test/mir-opt/const_prop/switch_int.rs b/src/test/mir-opt/const_prop/switch_int.rs index 9e7c73404487a..d7319eca18e2d 100644 --- a/src/test/mir-opt/const_prop/switch_int.rs +++ b/src/test/mir-opt/const_prop/switch_int.rs @@ -2,7 +2,7 @@ fn foo(_: i32) { } // EMIT_MIR switch_int.main.ConstProp.diff -// EMIT_MIR switch_int.main.SimplifyBranches-after-const-prop.diff +// EMIT_MIR switch_int.main.SimplifyConstCondition-after-const-prop.diff fn main() { match 1 { 1 => foo(0), diff --git a/src/test/mir-opt/early_otherwise_branch_68867.rs b/src/test/mir-opt/early_otherwise_branch_68867.rs index 02221c4cf4a1f..ca298e9211d48 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.rs +++ b/src/test/mir-opt/early_otherwise_branch_68867.rs @@ -11,7 +11,7 @@ pub enum ViewportPercentageLength { } // EMIT_MIR early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff -// EMIT_MIR early_otherwise_branch_68867.try_sum EarlyOtherwiseBranch.before SimplifyBranches-final.after +// EMIT_MIR early_otherwise_branch_68867.try_sum EarlyOtherwiseBranch.before SimplifyConstCondition-final.after #[no_mangle] pub extern "C" fn try_sum( x: &ViewportPercentageLength, diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff similarity index 99% rename from src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff rename to src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff index f23d035545eec..44294030439f3 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff +++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff @@ -1,5 +1,5 @@ - // MIR for `try_sum` before EarlyOtherwiseBranch -+ // MIR for `try_sum` after SimplifyBranches-final ++ // MIR for `try_sum` after SimplifyConstCondition-final fn try_sum(_1: &ViewportPercentageLength, _2: &ViewportPercentageLength) -> Result { debug x => _1; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:17:5: 17:6 diff --git a/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff similarity index 93% rename from src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff rename to src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff index def6f835131c9..d11c70b1efec6 100644 --- a/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff +++ b/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before SimplifyBranches-after-const-prop -+ // MIR for `main` after SimplifyBranches-after-const-prop +- // MIR for `main` before SimplifyConstCondition-after-const-prop ++ // MIR for `main` after SimplifyConstCondition-after-const-prop fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_if.rs:5:11: 5:11 diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs index 67b2027b710c9..2d093d9266bb5 100644 --- a/src/test/mir-opt/simplify_if.rs +++ b/src/test/mir-opt/simplify_if.rs @@ -1,7 +1,7 @@ #[inline(never)] fn noop() {} -// EMIT_MIR simplify_if.main.SimplifyBranches-after-const-prop.diff +// EMIT_MIR simplify_if.main.SimplifyConstCondition-after-const-prop.diff fn main() { if false { noop(); From 37fa92552586a9f91fefd92518b66dfde4c64771 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 1 Dec 2021 10:04:21 -0800 Subject: [PATCH 8/8] Add regression test for #90770 --- src/test/ui/consts/drop_zst.rs | 17 +++++++++++++++++ src/test/ui/consts/drop_zst.stderr | 9 +++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/test/ui/consts/drop_zst.rs create mode 100644 src/test/ui/consts/drop_zst.stderr diff --git a/src/test/ui/consts/drop_zst.rs b/src/test/ui/consts/drop_zst.rs new file mode 100644 index 0000000000000..f7c70d3978b7f --- /dev/null +++ b/src/test/ui/consts/drop_zst.rs @@ -0,0 +1,17 @@ +// check-fail + +#![feature(const_precise_live_drops)] + +struct S; + +impl Drop for S { + fn drop(&mut self) { + println!("Hello!"); + } +} + +const fn foo() { + let s = S; //~ destructor +} + +fn main() {} diff --git a/src/test/ui/consts/drop_zst.stderr b/src/test/ui/consts/drop_zst.stderr new file mode 100644 index 0000000000000..d4be5aa56d9af --- /dev/null +++ b/src/test/ui/consts/drop_zst.stderr @@ -0,0 +1,9 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop_zst.rs:14:9 + | +LL | let s = S; + | ^ constant functions cannot evaluate destructors + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`.