about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2017-05-15 21:09:01 -0400
committerNiko Matsakis <niko@alum.mit.edu>2017-05-17 07:39:57 -0400
commit19bf544b25c5a68d4fef5b948d6dc03613966f14 (patch)
treebb3b1a6dd3645222544d690d6e3cfb7ba9b21864
parentabe11831358f2c37a11ffddd679dd3e0a67827c8 (diff)
downloadrust-19bf544b25c5a68d4fef5b948d6dc03613966f14.tar.gz
rust-19bf544b25c5a68d4fef5b948d6dc03613966f14.zip
introduce local-scope to prevent storagelive/storagedead in statics
cc #36799
-rw-r--r--src/librustc_mir/build/expr/as_operand.rs4
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs6
-rw-r--r--src/librustc_mir/build/expr/as_temp.rs3
-rw-r--r--src/librustc_mir/build/mod.rs8
-rw-r--r--src/librustc_mir/build/scope.rs28
-rw-r--r--src/librustc_mir/hair/cx/mod.rs8
-rw-r--r--src/test/mir-opt/storage_live_dead_in_statics.rs100
7 files changed, 146 insertions, 11 deletions
diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs
index a3680214432..5178963179d 100644
--- a/src/librustc_mir/build/expr/as_operand.rs
+++ b/src/librustc_mir/build/expr/as_operand.rs
@@ -27,8 +27,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                              -> BlockAnd<Operand<'tcx>>
         where M: Mirror<'tcx, Output = Expr<'tcx>>
     {
-        let topmost_scope = self.topmost_scope(); // FIXME(#6393)
-        self.as_operand(block, Some(topmost_scope), expr)
+        let local_scope = self.local_scope();
+        self.as_operand(block, local_scope, expr)
     }
 
     /// Compile `expr` into a value that can be used as an operand.
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 7b29cd970d7..e1832e0a0af 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -33,8 +33,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                              -> BlockAnd<Rvalue<'tcx>>
         where M: Mirror<'tcx, Output = Expr<'tcx>>
     {
-        let topmost_scope = self.topmost_scope(); // FIXME(#6393)
-        self.as_rvalue(block, Some(topmost_scope), expr)
+        let local_scope = self.local_scope();
+        self.as_rvalue(block, local_scope, expr)
     }
 
     /// Compile `expr`, yielding an rvalue.
@@ -51,7 +51,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                       scope: Option<CodeExtent>,
                       expr: Expr<'tcx>)
                       -> BlockAnd<Rvalue<'tcx>> {
-        debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
+        debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr);
 
         let this = self;
         let expr_span = expr.span;
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index a334923546f..ab27a1a9c24 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -35,7 +35,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     temp_lifetime: Option<CodeExtent>,
                     expr: Expr<'tcx>)
                     -> BlockAnd<Lvalue<'tcx>> {
-        debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
+        debug!("expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?})",
+               block, temp_lifetime, expr);
         let this = self;
 
         if let ExprKind::Scope { extent, value } = expr.kind {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index fb173e2487b..9b1db2193e6 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -392,9 +392,9 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     mir
 }
 
-pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
-                                       body_id: hir::BodyId)
-                                       -> Mir<'tcx> {
+fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
+                                   body_id: hir::BodyId)
+                                   -> Mir<'tcx> {
     let tcx = hir.tcx();
     let ast_expr = &tcx.hir.body(body_id).value;
     let ty = hir.tables().expr_ty_adjusted(ast_expr);
@@ -415,7 +415,7 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
     builder.finish(vec![], ty)
 }
 
-pub fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
+fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
                                        body_id: hir::BodyId)
                                        -> Mir<'tcx> {
     let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id));
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index ae47f4c4244..0b1d411d96e 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -93,6 +93,7 @@ use rustc::middle::const_val::ConstVal;
 use rustc::ty::subst::{Kind, Subst};
 use rustc::ty::{Ty, TyCtxt};
 use rustc::mir::*;
+use rustc::mir::transform::MirSource;
 use syntax_pos::Span;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::fx::FxHashMap;
@@ -428,6 +429,33 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         self.scopes.last().expect("topmost_scope: no scopes present").extent
     }
 
+    /// Returns the scope that we should use as the lifetime of an
+    /// operand. Basically, an operand must live until it is consumed.
+    /// This is similar to, but not quite the same as, the temporary
+    /// scope (which can be larger or smaller).
+    ///
+    /// Consider:
+    ///
+    ///     let x = foo(bar(X, Y));
+    ///
+    /// We wish to pop the storage for X and Y after `bar()` is
+    /// called, not after the whole `let` is completed.
+    ///
+    /// When building statics/constants, returns `None` since
+    /// intermediate values do not have to be dropped in that case.
+    pub fn local_scope(&self) -> Option<CodeExtent> {
+        match self.hir.src {
+            MirSource::Const(_) |
+            MirSource::Static(..) =>
+                // No need to free storage in this context.
+                None,
+            MirSource::Fn(_) =>
+                Some(self.topmost_scope()),
+            MirSource::Promoted(..) =>
+                bug!(),
+        }
+    }
+
     // Scheduling drops
     // ================
     /// Indicates that `lvalue` should be dropped on exit from
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 9ffce18fe15..11b511ca47b 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -36,8 +36,14 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     pub region_maps: Rc<RegionMaps>,
+
+    /// This is `Constness::Const` if we are compiling a `static`,
+    /// `const`, or the body of a `const fn`.
     constness: hir::Constness,
 
+    /// What are we compiling?
+    pub src: MirSource,
+
     /// True if this constant/function needs overflow checks.
     check_overflow: bool,
 }
@@ -74,7 +80,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         // Constants and const fn's always need overflow checks.
         check_overflow |= constness == hir::Constness::Const;
 
-        Cx { tcx, infcx, region_maps, constness, check_overflow }
+        Cx { tcx, infcx, region_maps, constness, src, check_overflow }
     }
 }
 
diff --git a/src/test/mir-opt/storage_live_dead_in_statics.rs b/src/test/mir-opt/storage_live_dead_in_statics.rs
new file mode 100644
index 00000000000..9fb725a980e
--- /dev/null
+++ b/src/test/mir-opt/storage_live_dead_in_statics.rs
@@ -0,0 +1,100 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that when we compile the static `XXX` into MIR, we do not
+// generate `StorageStart` or `StorageEnd` statements.
+
+// ignore-tidy-linelength
+
+static XXX: &'static Foo = &Foo {
+    tup: "hi",
+    data: &[
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+    ]
+};
+
+#[derive(Debug)]
+struct Foo {
+    tup: &'static str,
+    data: &'static [(u32, u32)]
+}
+
+fn main() {
+    println!("{:?}", XXX);
+}
+
+// END RUST SOURCE
+// START rustc.node4.mir_map.0.mir
+//    bb0: {
+//        _7 = (const 0u32, const 1u32);   // scope 0 at src/test/mir-opt/basic_assignment.rs:29:9: 29:15
+//        _8 = (const 0u32, const 2u32);   // scope 0 at src/test/mir-opt/basic_assignment.rs:29:17: 29:23
+//        _9 = (const 0u32, const 3u32);   // scope 0 at src/test/mir-opt/basic_assignment.rs:29:25: 29:31
+//        _10 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:30:9: 30:15
+//        _11 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:30:17: 30:23
+//        _12 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:30:25: 30:31
+//        _13 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:31:9: 31:15
+//        _14 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:31:17: 31:23
+//        _15 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:31:25: 31:31
+//        _16 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:32:9: 32:15
+//        _17 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:32:17: 32:23
+//        _18 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:32:25: 32:31
+//        _19 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:33:9: 33:15
+//        _20 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:33:17: 33:23
+//        _21 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:33:25: 33:31
+//        _22 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:34:9: 34:15
+//        _23 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:34:17: 34:23
+//        _24 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:34:25: 34:31
+//        _25 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:35:9: 35:15
+//        _26 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:35:17: 35:23
+//        _27 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:35:25: 35:31
+//        _28 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:36:9: 36:15
+//        _29 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:36:17: 36:23
+//        _30 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:36:25: 36:31
+//        _31 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:37:9: 37:15
+//        _32 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:37:17: 37:23
+//        _33 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:37:25: 37:31
+//        _34 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:38:9: 38:15
+//        _35 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:38:17: 38:23
+//        _36 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:38:25: 38:31
+//        _37 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:39:9: 39:15
+//        _38 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:39:17: 39:23
+//        _39 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:39:25: 39:31
+//        _40 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:40:9: 40:15
+//        _41 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:40:17: 40:23
+//        _42 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:40:25: 40:31
+//        _43 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:41:9: 41:15
+//        _44 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:41:17: 41:23
+//        _45 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:41:25: 41:31
+//        _46 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:42:9: 42:15
+//        _47 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:42:17: 42:23
+//        _48 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:42:25: 42:31
+//        _6 = [_7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48]; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:12: 43:6
+//        _5 = &_6;                        // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+//        _4 = &(*_5);                     // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+//        _3 = _4 as &'static [(u32, u32)] (Unsize); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+//        _2 = Foo { tup: const "hi", data: _3 }; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:29: 44:2
+//        _1 = &_2;                        // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
+//        _0 = &(*_1);                     // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
+//        return;                          // scope 0 at src/test/mir-opt/basic_assignment.rs:26:1: 44:3
+//    }
+// END rustc.node4.mir_map.0.mir