]> git.lizzy.rs Git - rust.git/commitdiff
Also generate `StorageDead` in constants
authoroli <github35764891676564198441@oli-obk.de>
Wed, 9 Dec 2020 10:50:34 +0000 (10:50 +0000)
committeroli <github35764891676564198441@oli-obk.de>
Wed, 9 Dec 2020 10:59:10 +0000 (10:59 +0000)
compiler/rustc_mir/src/interpret/eval_context.rs
compiler/rustc_mir_build/src/build/expr/as_operand.rs
compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/scope.rs
src/test/mir-opt/const-promotion-extern-static.rs
src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir [new file with mode: 0644]
src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir

index 05b4d1c410d18bf18af8267bdc61d630a69894f2..d48b7fb3b9247f13f105e77e9c36114d293a2a6b 100644 (file)
@@ -4,7 +4,7 @@
 
 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 @@ pub fn push_stack_frame(
         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
index cf075abc94bf5f776ce52bd142cb012aed361cb9..60f8d8c8a9f36fd1c1c104723cbf87d29261d7bd 100644 (file)
@@ -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.
index c0e4141a558d96c90163526e6cdfc43ca4e2ea38..6537ba745c17a66954fa05465ac8168f251862db 100644 (file)
@@ -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 @@ fn limit_capture_mutability(
             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);
         }
index 5f9743b7f598ae886b914a57895765321a4dec62..1f70fdb5ae30b4d2475376820a7c7353c516bbcf 100644 (file)
@@ -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(
index 468b3484ca5ea653a19aaa7a73ce8ce4301c8da3..e137f77ffbb0b0bd0cfa45a279175b166e2f4575 100644 (file)
@@ -85,7 +85,6 @@
 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 @@ fn leave_top_scope(&mut self, block: BasicBlock) -> BasicBlock {
     /// 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 @@ fn unschedule_drop(&mut self, region_scope: region::Scope, local: Local) {
     /// 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 @@ fn unschedule_drop(&mut self, region_scope: region::Scope, local: Local) {
         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.
index 9c30e0400312adc9889242428cc402a1394a421f..0f13fe1b48c8a15b150fb313fe7a4ef8790c3302 100644 (file)
@@ -12,4 +12,7 @@
 // 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() {}
index bbce9c288efa933d59d66c7ec333435ca7a844be..5ba76c4f0bd70906101943976df344f1499bff62 100644 (file)
@@ -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
       }
   
diff --git a/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir b/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir
new file mode 100644 (file)
index 0000000..4d24387
--- /dev/null
@@ -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
+    }
+}
index 82277b2a21cbef3515c527e46a6b18f860c37626..1565cc7d5e72f776f5e1c1bb314325138b1cf56d 100644 (file)
@@ -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
       }
   
index 6d05e8278ba527b20f047794063017a64a9b35a2..6c22af787d341ad99efcda22918ba0939fff9bbc 100644 (file)
@@ -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