From fc1a861558a49013fb6af5e4c36450a3b96ddc03 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Mar 2023 18:13:43 +0000 Subject: [PATCH] Erase lifetimes in SROA. --- .../rustc_mir_dataflow/src/value_analysis.rs | 9 +- compiler/rustc_mir_transform/src/sroa.rs | 8 +- ...mes.foo.ScalarReplacementOfAggregates.diff | 225 ++++++++++++++++++ tests/mir-opt/sroa/lifetimes.rs | 37 +++ 4 files changed, 272 insertions(+), 7 deletions(-) create mode 100644 tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff create mode 100644 tests/mir-opt/sroa/lifetimes.rs diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 401db890a9810..34c60b5ff3c21 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -690,7 +690,7 @@ impl Map { } // Recurse with all fields of this place. - iter_fields(ty, tcx, |variant, field, ty| { + iter_fields(ty, tcx, ty::ParamEnv::reveal_all(), |variant, field, ty| { if let Some(variant) = variant { projection.push(PlaceElem::Downcast(None, variant)); let _ = self.make_place(local, projection); @@ -939,6 +939,7 @@ impl TryFrom> for TrackElem { pub fn iter_fields<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, mut f: impl FnMut(Option, Field, Ty<'tcx>), ) { match ty.kind() { @@ -956,14 +957,14 @@ pub fn iter_fields<'tcx>( for (f_index, f_def) in v_def.fields.iter().enumerate() { let field_ty = f_def.ty(tcx, substs); let field_ty = tcx - .try_normalize_erasing_regions(ty::ParamEnv::reveal_all(), field_ty) - .unwrap_or(field_ty); + .try_normalize_erasing_regions(param_env, field_ty) + .unwrap_or_else(|_| tcx.erase_regions(field_ty)); f(variant, f_index.into(), field_ty); } } } ty::Closure(_, substs) => { - iter_fields(substs.as_closure().tupled_upvars_ty(), tcx, f); + iter_fields(substs.as_closure().tupled_upvars_ty(), tcx, param_env, f); } _ => (), } diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 13168e9a268ed..ca2221520c825 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -4,7 +4,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; pub struct ScalarReplacementOfAggregates; @@ -18,11 +18,12 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); let mut excluded = excluded_locals(body); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); loop { debug!(?excluded); let escaping = escaping_locals(&excluded, body); debug!(?escaping); - let replacements = compute_flattening(tcx, body, escaping); + let replacements = compute_flattening(tcx, param_env, body, escaping); debug!(?replacements); let all_dead_locals = replace_flattened_locals(tcx, body, replacements); if !all_dead_locals.is_empty() { @@ -144,6 +145,7 @@ impl<'tcx> ReplacementMap<'tcx> { /// The replacement will be done later in `ReplacementVisitor`. fn compute_flattening<'tcx>( tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, body: &mut Body<'tcx>, escaping: BitSet, ) -> ReplacementMap<'tcx> { @@ -155,7 +157,7 @@ fn compute_flattening<'tcx>( } let decl = body.local_decls[local].clone(); let ty = decl.ty; - iter_fields(ty, tcx, |variant, field, field_ty| { + iter_fields(ty, tcx, param_env, |variant, field, field_ty| { if variant.is_some() { // Downcasts are currently not supported. return; diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff new file mode 100644 index 0000000000000..d41cdc09cac9d --- /dev/null +++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff @@ -0,0 +1,225 @@ +- // MIR for `foo` before ScalarReplacementOfAggregates ++ // MIR for `foo` after ScalarReplacementOfAggregates + + fn foo() -> () { + let mut _0: (); // return place in scope 0 at $DIR/lifetimes.rs:+0:18: +0:18 + let _1: Foo; // in scope 0 at $DIR/lifetimes.rs:+1:9: +1:12 + let mut _2: std::result::Result, ::Err>; // in scope 0 at $DIR/lifetimes.rs:+2:12: +2:31 + let mut _3: std::boxed::Box<(dyn std::fmt::Display + ReErased)>; // in scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 + let mut _4: std::boxed::Box; // in scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 + let mut _7: isize; // in scope 0 at $DIR/lifetimes.rs:+9:12: +9:17 + let _9: (); // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _10: (); // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _11: std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _12: &ReErased [&ReErased str]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28 + let mut _13: &ReErased [&ReErased str; Const(Value(Leaf(0x0000000000000003)): usize)]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28 + let _14: &ReErased [&ReErased str; Const(Value(Leaf(0x0000000000000003)): usize)]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28 + let _15: [&ReErased str; Const(Value(Leaf(0x0000000000000003)): usize)]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28 + let mut _16: &ReErased [core::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _17: &ReErased [core::fmt::ArgumentV1; Const(Value(Leaf(0x0000000000000002)): usize)]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _18: &ReErased [core::fmt::ArgumentV1; Const(Value(Leaf(0x0000000000000002)): usize)]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _19: [core::fmt::ArgumentV1; Const(Value(Leaf(0x0000000000000002)): usize)]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _20: core::fmt::ArgumentV1; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22 + let mut _21: &ReErased std::boxed::Box<(dyn std::fmt::Display + ReErased)>; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22 + let _22: &ReErased std::boxed::Box<(dyn std::fmt::Display + ReErased)>; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22 + let mut _23: core::fmt::ArgumentV1; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26 + let mut _24: &ReErased u32; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26 + let _25: &ReErased u32; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26 + let mut _27: bool; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 + let mut _28: isize; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 + let mut _29: isize; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 + let mut _30: isize; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 ++ let _31: std::result::Result, ::Err>; // in scope 0 at $DIR/lifetimes.rs:+1:9: +1:12 ++ let _32: u32; // in scope 0 at $DIR/lifetimes.rs:+1:9: +1:12 + scope 1 { +- debug foo => _1; // in scope 1 at $DIR/lifetimes.rs:+1:9: +1:12 ++ debug foo => Foo{ .0 => _31, .1 => _32, }; // in scope 1 at $DIR/lifetimes.rs:+1:9: +1:12 + let _5: std::result::Result, ::Err>; // in scope 1 at $DIR/lifetimes.rs:+6:9: +6:10 + scope 2 { + debug x => _5; // in scope 2 at $DIR/lifetimes.rs:+6:9: +6:10 + let _6: u32; // in scope 2 at $DIR/lifetimes.rs:+7:9: +7:10 + scope 3 { + debug y => _6; // in scope 3 at $DIR/lifetimes.rs:+7:9: +7:10 + scope 4 { + debug x => _8; // in scope 4 at $DIR/lifetimes.rs:+9:15: +9:16 + let _8: std::boxed::Box<(dyn std::fmt::Display + ReErased)>; // in scope 4 at $DIR/lifetimes.rs:+9:15: +9:16 + let mut _26: &ReErased [&ReErased str; Const(Value(Leaf(0x0000000000000003)): usize)]; // in scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 + } + } + } + } + + bb0: { + _27 = const ConstValue(Scalar(0x00): bool); // bb0[0]: scope 0 at $DIR/lifetimes.rs:+1:9: +1:12 +- StorageLive(_1); // bb0[1]: scope 0 at $DIR/lifetimes.rs:+1:9: +1:12 +- StorageLive(_2); // bb0[2]: scope 0 at $DIR/lifetimes.rs:+2:12: +2:31 +- StorageLive(_3); // bb0[3]: scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 +- StorageLive(_4); // bb0[4]: scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 +- _4 = ConstValue(ZeroSized: fn(u32) -> Box {Box::::new})(const ConstValue(Scalar(0x00000005): u32)) -> bb1; // bb0[5]: scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 ++ StorageLive(_31); // bb0[1]: scope 0 at $DIR/lifetimes.rs:+1:9: +1:12 ++ StorageLive(_32); // bb0[2]: scope 0 at $DIR/lifetimes.rs:+1:9: +1:12 ++ nop; // bb0[3]: scope 0 at $DIR/lifetimes.rs:+1:9: +1:12 ++ StorageLive(_2); // bb0[4]: scope 0 at $DIR/lifetimes.rs:+2:12: +2:31 ++ StorageLive(_3); // bb0[5]: scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 ++ StorageLive(_4); // bb0[6]: scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 ++ _4 = ConstValue(ZeroSized: fn(u32) -> Box {Box::::new})(const ConstValue(Scalar(0x00000005): u32)) -> bb1; // bb0[7]: scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 + // mir::Constant + // + span: $DIR/lifetimes.rs:19:15: 19:23 + // + user_ty: UserType(1) + // + literal: Const { ty: fn(u32) -> Box {Box::::new}, val: Value() } + } + + bb1: { + _3 = move _4 as std::boxed::Box<(dyn std::fmt::Display + ReErased)> (Pointer(Unsize)); // bb1[0]: scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 + StorageDead(_4); // bb1[1]: scope 0 at $DIR/lifetimes.rs:+2:29: +2:30 + _2 = Result::, ::Err>::Ok(move _3); // bb1[2]: scope 0 at $DIR/lifetimes.rs:+2:12: +2:31 + StorageDead(_3); // bb1[3]: scope 0 at $DIR/lifetimes.rs:+2:30: +2:31 +- _1 = Foo:: { x: move _2, y: const ConstValue(Scalar(0x00000007): u32) }; // bb1[4]: scope 0 at $DIR/lifetimes.rs:+1:23: +4:6 +- StorageDead(_2); // bb1[5]: scope 0 at $DIR/lifetimes.rs:+4:5: +4:6 +- StorageLive(_5); // bb1[6]: scope 1 at $DIR/lifetimes.rs:+6:9: +6:10 +- _27 = const ConstValue(Scalar(0x01): bool); // bb1[7]: scope 1 at $DIR/lifetimes.rs:+6:13: +6:18 +- _5 = move (_1.0: std::result::Result, ::Err>); // bb1[8]: scope 1 at $DIR/lifetimes.rs:+6:13: +6:18 +- StorageLive(_6); // bb1[9]: scope 2 at $DIR/lifetimes.rs:+7:9: +7:10 +- _6 = (_1.1: u32); // bb1[10]: scope 2 at $DIR/lifetimes.rs:+7:13: +7:18 +- _7 = discriminant(_5); // bb1[11]: scope 4 at $DIR/lifetimes.rs:+9:12: +9:17 +- switchInt(move _7) -> [0: bb2, otherwise: bb7]; // bb1[12]: scope 4 at $DIR/lifetimes.rs:+9:12: +9:17 ++ _31 = move _2; // bb1[4]: scope 0 at $DIR/lifetimes.rs:+1:23: +4:6 ++ _32 = const ConstValue(Scalar(0x00000007): u32); // bb1[5]: scope 0 at $DIR/lifetimes.rs:+1:23: +4:6 ++ nop; // bb1[6]: scope 0 at $DIR/lifetimes.rs:+1:23: +4:6 ++ StorageDead(_2); // bb1[7]: scope 0 at $DIR/lifetimes.rs:+4:5: +4:6 ++ StorageLive(_5); // bb1[8]: scope 1 at $DIR/lifetimes.rs:+6:9: +6:10 ++ _27 = const ConstValue(Scalar(0x01): bool); // bb1[9]: scope 1 at $DIR/lifetimes.rs:+6:13: +6:18 ++ _5 = move _31; // bb1[10]: scope 1 at $DIR/lifetimes.rs:+6:13: +6:18 ++ StorageLive(_6); // bb1[11]: scope 2 at $DIR/lifetimes.rs:+7:9: +7:10 ++ _6 = _32; // bb1[12]: scope 2 at $DIR/lifetimes.rs:+7:13: +7:18 ++ _7 = discriminant(_5); // bb1[13]: scope 4 at $DIR/lifetimes.rs:+9:12: +9:17 ++ switchInt(move _7) -> [0: bb2, otherwise: bb7]; // bb1[14]: scope 4 at $DIR/lifetimes.rs:+9:12: +9:17 + } + + bb2: { + StorageLive(_8); // bb2[0]: scope 4 at $DIR/lifetimes.rs:+9:15: +9:16 + _27 = const ConstValue(Scalar(0x00): bool); // bb2[1]: scope 4 at $DIR/lifetimes.rs:+9:15: +9:16 + _8 = move ((_5 as Ok).0: std::boxed::Box<(dyn std::fmt::Display + ReErased)>); // bb2[2]: scope 4 at $DIR/lifetimes.rs:+9:15: +9:16 + StorageLive(_9); // bb2[3]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_10); // bb2[4]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_11); // bb2[5]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_12); // bb2[6]: scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 + StorageLive(_13); // bb2[7]: scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 + StorageLive(_14); // bb2[8]: scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 + _26 = const _; // bb2[9]: scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 + // mir::Constant + // + span: $DIR/lifetimes.rs:27:19: 27:28 + // + literal: Const { ty: &ReErased [&ReErased str; Const(Value(Leaf(0x0000000000000003)): usize)], val: Unevaluated(foo, [T], Some(promoted[0])) } + _14 = &ReErased (*_26); // bb2[10]: scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 + _13 = &ReErased (*_14); // bb2[11]: scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 + _12 = move _13 as &ReErased [&ReErased str] (Pointer(Unsize)); // bb2[12]: scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 + StorageDead(_13); // bb2[13]: scope 4 at $DIR/lifetimes.rs:+10:27: +10:28 + StorageLive(_16); // bb2[14]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_17); // bb2[15]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_18); // bb2[16]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_19); // bb2[17]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_20); // bb2[18]: scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 + StorageLive(_21); // bb2[19]: scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 + StorageLive(_22); // bb2[20]: scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 + _22 = &ReErased _8; // bb2[21]: scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 + _21 = &ReErased (*_22); // bb2[22]: scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 + _20 = ConstValue(ZeroSized: for fn(&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(2:49824 ~ core[0bcc]::fmt::{impl#3}::new_display::'b), 'b) }) Box<(dyn std::fmt::Display + ReErased)>) -> core::fmt::ArgumentV1 {core::fmt::ArgumentV1::::new_display::>})(move _21) -> bb3; // bb2[23]: scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 + // mir::Constant + // + span: $DIR/lifetimes.rs:27:21: 27:22 + // + user_ty: UserType(4) + // + literal: Const { ty: for fn(&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(2:49824 ~ core[0bcc]::fmt::{impl#3}::new_display::'b), 'b) }) Box<(dyn std::fmt::Display + ReErased)>) -> core::fmt::ArgumentV1 {core::fmt::ArgumentV1::::new_display::>}, val: Value() } + } + + bb3: { + StorageDead(_21); // bb3[0]: scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 + StorageLive(_23); // bb3[1]: scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 + StorageLive(_24); // bb3[2]: scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 + StorageLive(_25); // bb3[3]: scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 + _25 = &ReErased _6; // bb3[4]: scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 + _24 = &ReErased (*_25); // bb3[5]: scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 + _23 = ConstValue(ZeroSized: for fn(&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(2:49824 ~ core[0bcc]::fmt::{impl#3}::new_display::'b), 'b) }) u32) -> core::fmt::ArgumentV1 {core::fmt::ArgumentV1::::new_display::})(move _24) -> bb4; // bb3[6]: scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 + // mir::Constant + // + span: $DIR/lifetimes.rs:27:25: 27:26 + // + user_ty: UserType(5) + // + literal: Const { ty: for fn(&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(2:49824 ~ core[0bcc]::fmt::{impl#3}::new_display::'b), 'b) }) u32) -> core::fmt::ArgumentV1 {core::fmt::ArgumentV1::::new_display::}, val: Value() } + } + + bb4: { + StorageDead(_24); // bb4[0]: scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 + _19 = [move _20, move _23]; // bb4[1]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_23); // bb4[2]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_20); // bb4[3]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _18 = &ReErased _19; // bb4[4]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _17 = &ReErased (*_18); // bb4[5]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _16 = move _17 as &ReErased [core::fmt::ArgumentV1] (Pointer(Unsize)); // bb4[6]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_17); // bb4[7]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _11 = ConstValue(ZeroSized: fn(&ReErased [&ReStatic str], &ReErased [core::fmt::ArgumentV1]) -> Arguments {Arguments::::new_v1})(move _12, move _16) -> bb5; // bb4[8]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/std/src/macros.rs:LL:COL + // + user_ty: UserType(3) + // + literal: Const { ty: fn(&ReErased [&ReStatic str], &ReErased [core::fmt::ArgumentV1]) -> Arguments {Arguments::::new_v1}, val: Value() } + } + + bb5: { + StorageDead(_16); // bb5[0]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_12); // bb5[1]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _10 = ConstValue(ZeroSized: for fn(Arguments) {_eprint})(move _11) -> bb6; // bb5[2]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/std/src/macros.rs:LL:COL + // + literal: Const { ty: for fn(Arguments) {_eprint}, val: Value() } + } + + bb6: { + StorageDead(_11); // bb6[0]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_25); // bb6[1]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_22); // bb6[2]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_19); // bb6[3]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_18); // bb6[4]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_14); // bb6[5]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_10); // bb6[6]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _9 = const ConstValue(ZeroSized: ()); // bb6[7]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_9); // bb6[8]: scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _0 = const ConstValue(ZeroSized: ()); // bb6[9]: scope 4 at $DIR/lifetimes.rs:+9:22: +11:6 + drop(_8) -> bb8; // bb6[10]: scope 3 at $DIR/lifetimes.rs:+11:5: +11:6 + } + + bb7: { + _0 = const ConstValue(ZeroSized: ()); // bb7[0]: scope 3 at $DIR/lifetimes.rs:+11:6: +11:6 + goto -> bb9; // bb7[1]: scope 3 at $DIR/lifetimes.rs:+9:5: +11:6 + } + + bb8: { + StorageDead(_8); // bb8[0]: scope 3 at $DIR/lifetimes.rs:+11:5: +11:6 + goto -> bb9; // bb8[1]: scope 3 at $DIR/lifetimes.rs:+9:5: +11:6 + } + + bb9: { + StorageDead(_6); // bb9[0]: scope 2 at $DIR/lifetimes.rs:+12:1: +12:2 + _28 = discriminant(_5); // bb9[1]: scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 + switchInt(move _28) -> [0: bb11, otherwise: bb13]; // bb9[2]: scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 + } + + bb10: { + _27 = const ConstValue(Scalar(0x00): bool); // bb10[0]: scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 + StorageDead(_5); // bb10[1]: scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 +- StorageDead(_1); // bb10[2]: scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 +- return; // bb10[3]: scope 0 at $DIR/lifetimes.rs:+12:2: +12:2 ++ StorageDead(_31); // bb10[2]: scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 ++ StorageDead(_32); // bb10[3]: scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 ++ nop; // bb10[4]: scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 ++ return; // bb10[5]: scope 0 at $DIR/lifetimes.rs:+12:2: +12:2 + } + + bb11: { + switchInt(_27) -> [0: bb10, otherwise: bb12]; // bb11[0]: scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 + } + + bb12: { + drop(((_5 as Ok).0: std::boxed::Box<(dyn std::fmt::Display + ReErased)>)) -> bb10; // bb12[0]: scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 + } + + bb13: { + drop(_5) -> bb10; // bb13[0]: scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 + } + } + diff --git a/tests/mir-opt/sroa/lifetimes.rs b/tests/mir-opt/sroa/lifetimes.rs new file mode 100644 index 0000000000000..bf9b57fbfbd7f --- /dev/null +++ b/tests/mir-opt/sroa/lifetimes.rs @@ -0,0 +1,37 @@ +// unit-test: ScalarReplacementOfAggregates +// compile-flags: -Zverbose -Cpanic=abort +// no-prefer-dynamic + +trait Err { + type Err; +} + +struct Foo { + // Check that the `'static` lifetime is erased when creating the local for `x`, + // even if we fail to normalize the type. + x: Result, ::Err>, + y: u32, +} + +// EMIT_MIR lifetimes.foo.ScalarReplacementOfAggregates.diff +fn foo() { + let foo: Foo = Foo { + x: Ok(Box::new(5_u32)), + y: 7_u32, + }; + + let x = foo.x; + let y = foo.y; + + if let Ok(x) = x { + eprintln!("{x} {y}"); + } +} + +impl Err for () { + type Err = (); +} + +fn main() { + foo::<()>() +}