Also generate StorageDead
in constants
This commit is contained in:
parent
db85512bd8
commit
84fe7cf24e
@ -4,7 +4,7 @@ use std::mem;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_hir::{self as hir, def::DefKind, def_id::DefId, definitions::DefPathData};
|
||||
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::ich::StableHashingContext;
|
||||
@ -700,21 +700,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let mut locals = IndexVec::from_elem(dummy, &body.local_decls);
|
||||
|
||||
// Now mark those locals as dead that we do not want to initialize
|
||||
match self.tcx.def_kind(instance.def_id()) {
|
||||
// statics and constants don't have `Storage*` statements, no need to look for them
|
||||
//
|
||||
// FIXME: The above is likely untrue. See
|
||||
// <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it
|
||||
// okay to ignore `StorageDead`/`StorageLive` annotations during CTFE?
|
||||
DefKind::Static | DefKind::Const | DefKind::AssocConst => {}
|
||||
_ => {
|
||||
// Mark locals that use `Storage*` annotations as dead on function entry.
|
||||
let always_live = AlwaysLiveLocals::new(self.body());
|
||||
for local in locals.indices() {
|
||||
if !always_live.contains(local) {
|
||||
locals[local].value = LocalValue::Dead;
|
||||
}
|
||||
}
|
||||
// Mark locals that use `Storage*` annotations as dead on function entry.
|
||||
let always_live = AlwaysLiveLocals::new(self.body());
|
||||
for local in locals.indices() {
|
||||
if !always_live.contains(local) {
|
||||
locals[local].value = LocalValue::Dead;
|
||||
}
|
||||
}
|
||||
// done
|
||||
|
@ -19,7 +19,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
M: Mirror<'tcx, Output = Expr<'tcx>>,
|
||||
{
|
||||
let local_scope = self.local_scope();
|
||||
self.as_operand(block, local_scope, expr)
|
||||
self.as_operand(block, Some(local_scope), expr)
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
M: Mirror<'tcx, Output = Expr<'tcx>>,
|
||||
{
|
||||
let local_scope = self.local_scope();
|
||||
self.as_call_operand(block, local_scope, expr)
|
||||
self.as_call_operand(block, Some(local_scope), expr)
|
||||
}
|
||||
|
||||
/// Compile `expr` into a value that can be used as an operand.
|
||||
|
@ -25,7 +25,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
M: Mirror<'tcx, Output = Expr<'tcx>>,
|
||||
{
|
||||
let local_scope = self.local_scope();
|
||||
self.as_rvalue(block, local_scope, expr)
|
||||
self.as_rvalue(block, Some(local_scope), expr)
|
||||
}
|
||||
|
||||
/// Compile `expr`, yielding an rvalue.
|
||||
@ -445,9 +445,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
Rvalue::Ref(this.hir.tcx().lifetimes.re_erased, borrow_kind, arg_place),
|
||||
);
|
||||
|
||||
// In constants, temp_lifetime is None. We should not need to drop
|
||||
// anything because no values with a destructor can be created in
|
||||
// a constant at this time, even if the type may need dropping.
|
||||
// See the comment in `expr_as_temp` and on the `rvalue_scopes` field for why
|
||||
// this can be `None`.
|
||||
if let Some(temp_lifetime) = temp_lifetime {
|
||||
this.schedule_drop_storage_and_value(upvar_span, temp_lifetime, temp);
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
// (#66975) Source could be a const of type `!`, so has to
|
||||
// exist in the generated MIR.
|
||||
unpack!(block = this.as_temp(block, this.local_scope(), source, Mutability::Mut,));
|
||||
unpack!(block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut,));
|
||||
|
||||
// This is an optimization. If the expression was a call then we already have an
|
||||
// unreachable block. Don't bother to terminate it and create a new one.
|
||||
@ -300,7 +300,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// (evaluating them in order given by user)
|
||||
let fields_map: FxHashMap<_, _> = fields
|
||||
.into_iter()
|
||||
.map(|f| (f.name, unpack!(block = this.as_operand(block, scope, f.expr))))
|
||||
.map(|f| (f.name, unpack!(block = this.as_operand(block, Some(scope), f.expr))))
|
||||
.collect();
|
||||
|
||||
let field_names = this.hir.all_fields(adt_def, variant_index);
|
||||
@ -468,7 +468,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
ExprKind::Yield { value } => {
|
||||
let scope = this.local_scope();
|
||||
let value = unpack!(block = this.as_operand(block, scope, value));
|
||||
let value = unpack!(block = this.as_operand(block, Some(scope), value));
|
||||
let resume = this.cfg.start_new_block();
|
||||
this.record_operands_moved(slice::from_ref(&value));
|
||||
this.cfg.terminate(
|
||||
|
@ -85,7 +85,6 @@ use crate::build::matches::{ArmHasGuard, Candidate};
|
||||
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
|
||||
use crate::thir::{Arm, Expr, ExprRef, LintLevel};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir as hir;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::*;
|
||||
@ -740,18 +739,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// We would allocate the box but then free it on the unwinding
|
||||
/// path; we would also emit a free on the 'success' path from
|
||||
/// panic, but that will turn out to be removed as dead-code.
|
||||
///
|
||||
/// When building statics/constants, returns `None` since
|
||||
/// intermediate values do not have to be dropped in that case.
|
||||
crate fn local_scope(&self) -> Option<region::Scope> {
|
||||
match self.hir.body_owner_kind {
|
||||
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) =>
|
||||
// No need to free storage in this context.
|
||||
{
|
||||
None
|
||||
}
|
||||
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => Some(self.scopes.topmost()),
|
||||
}
|
||||
crate fn local_scope(&self) -> region::Scope {
|
||||
self.scopes.topmost()
|
||||
}
|
||||
|
||||
// Scheduling drops
|
||||
@ -938,23 +927,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// not the `DROP(_X)` itself, but the (spurious) unwind pathways
|
||||
/// that it creates. See #64391 for an example.
|
||||
crate fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
|
||||
let scope = match self.local_scope() {
|
||||
None => {
|
||||
// if there is no local scope, operands won't be dropped anyway
|
||||
return;
|
||||
}
|
||||
let local_scope = self.local_scope();
|
||||
let scope = self.scopes.scopes.last_mut().unwrap();
|
||||
|
||||
Some(local_scope) => {
|
||||
let top_scope = self.scopes.scopes.last_mut().unwrap();
|
||||
assert!(
|
||||
top_scope.region_scope == local_scope,
|
||||
"local scope ({:?}) is not the topmost scope!",
|
||||
local_scope
|
||||
);
|
||||
|
||||
top_scope
|
||||
}
|
||||
};
|
||||
assert_eq!(
|
||||
scope.region_scope, local_scope,
|
||||
"local scope is not the topmost scope!",
|
||||
);
|
||||
|
||||
// look for moves of a local variable, like `MOVE(_X)`
|
||||
let locals_moved = operands
|
||||
@ -993,9 +972,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
match cond {
|
||||
// Don't try to drop a constant
|
||||
Operand::Constant(_) => (),
|
||||
// If constants and statics, we don't generate StorageLive for this
|
||||
// temporary, so don't try to generate StorageDead for it either.
|
||||
_ if self.local_scope().is_none() => (),
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
if let Some(cond_temp) = place.as_local() {
|
||||
// Manually drop the condition on both branches.
|
||||
|
@ -12,4 +12,7 @@ static mut BAR: *const &i32 = [&Y].as_ptr();
|
||||
// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir
|
||||
static mut FOO: *const &i32 = [unsafe { &X }].as_ptr();
|
||||
|
||||
// EMIT_MIR const_promotion_extern_static.BOP.mir_map.0.mir
|
||||
static BOP: &i32 = &13;
|
||||
|
||||
fn main() {}
|
||||
|
@ -33,6 +33,8 @@
|
||||
+ // + 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])) }
|
||||
+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
|
||||
_1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
|
||||
- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
|
||||
StorageDead(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
|
||||
_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
|
||||
// mir::Constant
|
||||
// + span: $DIR/const-promotion-extern-static.rs:9:36: 9:42
|
||||
@ -42,6 +44,7 @@
|
||||
bb1: {
|
||||
- StorageDead(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44
|
||||
- StorageDead(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44
|
||||
StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44
|
||||
return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:45
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
// MIR for `BOP` 0 mir_map
|
||||
|
||||
static BOP: &i32 = {
|
||||
let mut _0: &i32; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:16:13: 16:17
|
||||
let _1: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23
|
||||
let _2: i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:16:21: 16:23
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23
|
||||
StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:16:21: 16:23
|
||||
_2 = const 13_i32; // scope 0 at $DIR/const-promotion-extern-static.rs:16:21: 16:23
|
||||
_1 = &_2; // scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23
|
||||
_0 = &(*_1); // scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23
|
||||
StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:16:22: 16:23
|
||||
return; // scope 0 at $DIR/const-promotion-extern-static.rs:16:1: 16:24
|
||||
}
|
||||
}
|
@ -35,6 +35,8 @@
|
||||
+ // + 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])) }
|
||||
+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
|
||||
_1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
|
||||
- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
|
||||
StorageDead(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
|
||||
_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
|
||||
// mir::Constant
|
||||
// + span: $DIR/const-promotion-extern-static.rs:13:47: 13:53
|
||||
@ -44,6 +46,7 @@
|
||||
bb1: {
|
||||
- StorageDead(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55
|
||||
- StorageDead(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55
|
||||
StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55
|
||||
return; // scope 0 at $DIR/const-promotion-extern-static.rs:13:1: 13:56
|
||||
}
|
||||
|
||||
|
@ -143,9 +143,52 @@ static XXX: &Foo = {
|
||||
StorageLive(_48); // scope 0 at $DIR/storage_live_dead_in_statics.rs:21:25: 21:31
|
||||
_48 = (const 0_u32, const 3_u32); // scope 0 at $DIR/storage_live_dead_in_statics.rs:21:25: 21:31
|
||||
_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
|
||||
StorageDead(_48); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_47); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_46); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_45); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_44); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_43); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_42); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_41); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_40); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_39); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_38); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_37); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_36); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_35); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_34); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_33); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_32); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_31); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_30); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_29); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_28); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_27); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_26); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_25); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_24); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_23); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_22); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_21); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_20); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_19); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_18); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_17); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_16); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_15); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_14); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_13); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_12); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_11); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_10); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_9); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_8); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
StorageDead(_7); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
_5 = &_6; // scope 0 at $DIR/storage_live_dead_in_statics.rs:7:11: 22:6
|
||||
_4 = &(*_5); // scope 0 at $DIR/storage_live_dead_in_statics.rs:7:11: 22:6
|
||||
_3 = move _4 as &[(u32, u32)] (Pointer(Unsize)); // scope 0 at $DIR/storage_live_dead_in_statics.rs:7:11: 22:6
|
||||
StorageDead(_4); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6
|
||||
_2 = Foo { tup: const "hi", data: move _3 }; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:29: 23:2
|
||||
// ty::Const
|
||||
// + ty: &str
|
||||
@ -153,6 +196,7 @@ static XXX: &Foo = {
|
||||
// mir::Constant
|
||||
// + span: $DIR/storage_live_dead_in_statics.rs:6:10: 6:14
|
||||
// + 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 }) }
|
||||
StorageDead(_3); // scope 0 at $DIR/storage_live_dead_in_statics.rs:23:1: 23:2
|
||||
_1 = &_2; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:28: 23:2
|
||||
_0 = &(*_1); // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:28: 23:2
|
||||
StorageDead(_5); // scope 0 at $DIR/storage_live_dead_in_statics.rs:23:1: 23:2
|
||||
|
Loading…
Reference in New Issue
Block a user