Skip to content

Commit cc03ee6

Browse files
committed
Auto merge of #78679 - oli-obk:temp_lifetime, r=eddyb
Also generate `StorageDead` in constants r? `@eddyb` None of this special casing is actually necessary since we started promoting within constants and statics. We may want to keep some of it around out of perf reasons, but it's not required for user visible behaviour somewhat related: #68622
2 parents c0bfe34 + 84fe7cf commit cc03ee6

10 files changed

+92
-57
lines changed

compiler/rustc_mir/src/interpret/eval_context.rs

+6-16
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::mem;
44

55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
7-
use rustc_hir::{self as hir, def::DefKind, def_id::DefId, definitions::DefPathData};
7+
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
88
use rustc_index::vec::IndexVec;
99
use rustc_macros::HashStable;
1010
use rustc_middle::ich::StableHashingContext;
@@ -700,21 +700,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
700700
let mut locals = IndexVec::from_elem(dummy, &body.local_decls);
701701

702702
// Now mark those locals as dead that we do not want to initialize
703-
match self.tcx.def_kind(instance.def_id()) {
704-
// statics and constants don't have `Storage*` statements, no need to look for them
705-
//
706-
// FIXME: The above is likely untrue. See
707-
// <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it
708-
// okay to ignore `StorageDead`/`StorageLive` annotations during CTFE?
709-
DefKind::Static | DefKind::Const | DefKind::AssocConst => {}
710-
_ => {
711-
// Mark locals that use `Storage*` annotations as dead on function entry.
712-
let always_live = AlwaysLiveLocals::new(self.body());
713-
for local in locals.indices() {
714-
if !always_live.contains(local) {
715-
locals[local].value = LocalValue::Dead;
716-
}
717-
}
703+
// Mark locals that use `Storage*` annotations as dead on function entry.
704+
let always_live = AlwaysLiveLocals::new(self.body());
705+
for local in locals.indices() {
706+
if !always_live.contains(local) {
707+
locals[local].value = LocalValue::Dead;
718708
}
719709
}
720710
// done

compiler/rustc_mir_build/src/build/expr/as_operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1919
M: Mirror<'tcx, Output = Expr<'tcx>>,
2020
{
2121
let local_scope = self.local_scope();
22-
self.as_operand(block, local_scope, expr)
22+
self.as_operand(block, Some(local_scope), expr)
2323
}
2424

2525
/// Returns an operand suitable for use until the end of the current scope expression and
@@ -79,7 +79,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7979
M: Mirror<'tcx, Output = Expr<'tcx>>,
8080
{
8181
let local_scope = self.local_scope();
82-
self.as_call_operand(block, local_scope, expr)
82+
self.as_call_operand(block, Some(local_scope), expr)
8383
}
8484

8585
/// Compile `expr` into a value that can be used as an operand.

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2525
M: Mirror<'tcx, Output = Expr<'tcx>>,
2626
{
2727
let local_scope = self.local_scope();
28-
self.as_rvalue(block, local_scope, expr)
28+
self.as_rvalue(block, Some(local_scope), expr)
2929
}
3030

3131
/// Compile `expr`, yielding an rvalue.
@@ -445,9 +445,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
445445
Rvalue::Ref(this.hir.tcx().lifetimes.re_erased, borrow_kind, arg_place),
446446
);
447447

448-
// In constants, temp_lifetime is None. We should not need to drop
449-
// anything because no values with a destructor can be created in
450-
// a constant at this time, even if the type may need dropping.
448+
// See the comment in `expr_as_temp` and on the `rvalue_scopes` field for why
449+
// this can be `None`.
451450
if let Some(temp_lifetime) = temp_lifetime {
452451
this.schedule_drop_storage_and_value(upvar_span, temp_lifetime, temp);
453452
}

compiler/rustc_mir_build/src/build/expr/into.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7979

8080
// (#66975) Source could be a const of type `!`, so has to
8181
// exist in the generated MIR.
82-
unpack!(block = this.as_temp(block, this.local_scope(), source, Mutability::Mut,));
82+
unpack!(block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut,));
8383

8484
// This is an optimization. If the expression was a call then we already have an
8585
// unreachable block. Don't bother to terminate it and create a new one.
@@ -300,7 +300,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
300300
// (evaluating them in order given by user)
301301
let fields_map: FxHashMap<_, _> = fields
302302
.into_iter()
303-
.map(|f| (f.name, unpack!(block = this.as_operand(block, scope, f.expr))))
303+
.map(|f| (f.name, unpack!(block = this.as_operand(block, Some(scope), f.expr))))
304304
.collect();
305305

306306
let field_names = this.hir.all_fields(adt_def, variant_index);
@@ -468,7 +468,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
468468

469469
ExprKind::Yield { value } => {
470470
let scope = this.local_scope();
471-
let value = unpack!(block = this.as_operand(block, scope, value));
471+
let value = unpack!(block = this.as_operand(block, Some(scope), value));
472472
let resume = this.cfg.start_new_block();
473473
this.record_operands_moved(slice::from_ref(&value));
474474
this.cfg.terminate(

compiler/rustc_mir_build/src/build/scope.rs

+8-32
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ use crate::build::matches::{ArmHasGuard, Candidate};
8585
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
8686
use crate::thir::{Arm, Expr, ExprRef, LintLevel};
8787
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
88-
use rustc_hir as hir;
8988
use rustc_index::vec::IndexVec;
9089
use rustc_middle::middle::region;
9190
use rustc_middle::mir::*;
@@ -740,18 +739,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
740739
/// We would allocate the box but then free it on the unwinding
741740
/// path; we would also emit a free on the 'success' path from
742741
/// panic, but that will turn out to be removed as dead-code.
743-
///
744-
/// When building statics/constants, returns `None` since
745-
/// intermediate values do not have to be dropped in that case.
746-
crate fn local_scope(&self) -> Option<region::Scope> {
747-
match self.hir.body_owner_kind {
748-
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) =>
749-
// No need to free storage in this context.
750-
{
751-
None
752-
}
753-
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => Some(self.scopes.topmost()),
754-
}
742+
crate fn local_scope(&self) -> region::Scope {
743+
self.scopes.topmost()
755744
}
756745

757746
// Scheduling drops
@@ -938,23 +927,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
938927
/// not the `DROP(_X)` itself, but the (spurious) unwind pathways
939928
/// that it creates. See #64391 for an example.
940929
crate fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
941-
let scope = match self.local_scope() {
942-
None => {
943-
// if there is no local scope, operands won't be dropped anyway
944-
return;
945-
}
930+
let local_scope = self.local_scope();
931+
let scope = self.scopes.scopes.last_mut().unwrap();
946932

947-
Some(local_scope) => {
948-
let top_scope = self.scopes.scopes.last_mut().unwrap();
949-
assert!(
950-
top_scope.region_scope == local_scope,
951-
"local scope ({:?}) is not the topmost scope!",
952-
local_scope
953-
);
954-
955-
top_scope
956-
}
957-
};
933+
assert_eq!(
934+
scope.region_scope, local_scope,
935+
"local scope is not the topmost scope!",
936+
);
958937

959938
// look for moves of a local variable, like `MOVE(_X)`
960939
let locals_moved = operands
@@ -993,9 +972,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
993972
match cond {
994973
// Don't try to drop a constant
995974
Operand::Constant(_) => (),
996-
// If constants and statics, we don't generate StorageLive for this
997-
// temporary, so don't try to generate StorageDead for it either.
998-
_ if self.local_scope().is_none() => (),
999975
Operand::Copy(place) | Operand::Move(place) => {
1000976
if let Some(cond_temp) = place.as_local() {
1001977
// Manually drop the condition on both branches.

src/test/mir-opt/const-promotion-extern-static.rs

+3
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@ static mut BAR: *const &i32 = [&Y].as_ptr();
1212
// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir
1313
static mut FOO: *const &i32 = [unsafe { &X }].as_ptr();
1414

15+
// EMIT_MIR const_promotion_extern_static.BOP.mir_map.0.mir
16+
static BOP: &i32 = &13;
17+
1518
fn main() {}

src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, [], Some(promoted[0])) }
3434
+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
3535
_1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
36+
- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
37+
StorageDead(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
3638
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44
3739
// mir::Constant
3840
// + span: $DIR/const-promotion-extern-static.rs:9:36: 9:42
@@ -42,6 +44,7 @@
4244
bb1: {
4345
- StorageDead(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44
4446
- StorageDead(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44
47+
StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44
4548
return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:45
4649
}
4750

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// MIR for `BOP` 0 mir_map
2+
3+
static BOP: &i32 = {
4+
let mut _0: &i32; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:16:13: 16:17
5+
let _1: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23
6+
let _2: i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:16:21: 16:23
7+
8+
bb0: {
9+
StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23
10+
StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:16:21: 16:23
11+
_2 = const 13_i32; // scope 0 at $DIR/const-promotion-extern-static.rs:16:21: 16:23
12+
_1 = &_2; // scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23
13+
_0 = &(*_1); // scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23
14+
StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:16:22: 16:23
15+
return; // scope 0 at $DIR/const-promotion-extern-static.rs:16:1: 16:24
16+
}
17+
}

src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, [], Some(promoted[0])) }
3636
+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
3737
_1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
38+
- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
39+
StorageDead(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
3840
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55
3941
// mir::Constant
4042
// + span: $DIR/const-promotion-extern-static.rs:13:47: 13:53
@@ -44,6 +46,7 @@
4446
bb1: {
4547
- StorageDead(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55
4648
- StorageDead(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55
49+
StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55
4750
return; // scope 0 at $DIR/const-promotion-extern-static.rs:13:1: 13:56
4851
}
4952

src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir

+44
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,60 @@ static XXX: &Foo = {
143143
StorageLive(_48); // scope 0 at $DIR/storage_live_dead_in_statics.rs:21:25: 21:31
144144
_48 = (const 0_u32, const 3_u32); // scope 0 at $DIR/storage_live_dead_in_statics.rs:21:25: 21:31
145145
_6 = [move _7, move _8, move _9, move _10, move _11, move _12, move _13, move _14, move _15, move _16, move _17, move _18, move _19, move _20, move _21, move _22, move _23, move _24, move _25, move _26, move _27, move _28, move _29, move _30, move _31, move _32, move _33, move _34, move _35, move _36, move _37, move _38, move _39, move _40, move _41, move _42, move _43, move _44, move _45, move _46, move _47, move _48]; // scope 0 at $DIR/storage_live_dead_in_statics.rs:7:12: 22:6
146+
StorageDead(_48); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
147+
StorageDead(_47); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
148+
StorageDead(_46); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
149+
StorageDead(_45); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
150+
StorageDead(_44); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
151+
StorageDead(_43); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
152+
StorageDead(_42); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
153+
StorageDead(_41); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
154+
StorageDead(_40); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
155+
StorageDead(_39); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
156+
StorageDead(_38); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
157+
StorageDead(_37); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
158+
StorageDead(_36); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
159+
StorageDead(_35); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
160+
StorageDead(_34); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
161+
StorageDead(_33); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
162+
StorageDead(_32); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
163+
StorageDead(_31); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
164+
StorageDead(_30); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
165+
StorageDead(_29); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
166+
StorageDead(_28); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
167+
StorageDead(_27); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
168+
StorageDead(_26); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
169+
StorageDead(_25); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
170+
StorageDead(_24); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
171+
StorageDead(_23); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
172+
StorageDead(_22); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
173+
StorageDead(_21); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
174+
StorageDead(_20); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
175+
StorageDead(_19); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
176+
StorageDead(_18); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
177+
StorageDead(_17); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
178+
StorageDead(_16); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
179+
StorageDead(_15); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
180+
StorageDead(_14); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
181+
StorageDead(_13); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
182+
StorageDead(_12); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
183+
StorageDead(_11); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
184+
StorageDead(_10); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
185+
StorageDead(_9); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
186+
StorageDead(_8); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
187+
StorageDead(_7); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
146188
_5 = &_6; // scope 0 at $DIR/storage_live_dead_in_statics.rs:7:11: 22:6
147189
_4 = &(*_5); // scope 0 at $DIR/storage_live_dead_in_statics.rs:7:11: 22:6
148190
_3 = move _4 as &[(u32, u32)] (Pointer(Unsize)); // scope 0 at $DIR/storage_live_dead_in_statics.rs:7:11: 22:6
191+
StorageDead(_4); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
149192
_2 = Foo { tup: const "hi", data: move _3 }; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:29: 23:2
150193
// ty::Const
151194
// + ty: &str
152195
// + val: Value(Slice { data: Allocation { bytes: [104, 105], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, size: Size { raw: 2 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 2 })
153196
// mir::Constant
154197
// + span: $DIR/storage_live_dead_in_statics.rs:6:10: 6:14
155198
// + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 105], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, size: Size { raw: 2 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 2 }) }
199+
StorageDead(_3); // scope 0 at $DIR/storage_live_dead_in_statics.rs:23:1: 23:2
156200
_1 = &_2; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:28: 23:2
157201
_0 = &(*_1); // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:28: 23:2
158202
StorageDead(_5); // scope 0 at $DIR/storage_live_dead_in_statics.rs:23:1: 23:2

0 commit comments

Comments
 (0)