about summary refs log tree commit diff
path: root/src/librustc/middle
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-01-26 17:42:52 +0000
committerbors <bors@rust-lang.org>2017-01-26 17:42:52 +0000
commit8430042a49bbd49bbb4fbc54f457feb5fb614f56 (patch)
treea5fb7095092902f3168b86d671f0813d1228eaa4 /src/librustc/middle
parent491b978822a56f23acf9ba46f90861958bc1e36c (diff)
parent82a280597d967dc3ec8686f160a0afea4ad45837 (diff)
downloadrust-8430042a49bbd49bbb4fbc54f457feb5fb614f56.tar.gz
rust-8430042a49bbd49bbb4fbc54f457feb5fb614f56.zip
Auto merge of #39066 - arielb1:lifetime-extension-test, r=nikomatsakis
End temporary lifetimes being extended by `let X: &_` hints

cc #39283

r? @nikomatsakis
Diffstat (limited to 'src/librustc/middle')
-rw-r--r--src/librustc/middle/expr_use_visitor.rs1
-rw-r--r--src/librustc/middle/mem_categorization.rs30
-rw-r--r--src/librustc/middle/region.rs62
3 files changed, 74 insertions, 19 deletions
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 738bd0009ab..2ca0069560c 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -296,6 +296,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 arg.id,
                 arg.pat.span,
                 fn_body_scope_r, // Args live only as long as the fn body.
+                fn_body_scope_r,
                 arg_ty);
 
             self.walk_irrefutable_pat(arg_cmt, &arg.pat);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 126d43aa690..955bec00433 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -88,7 +88,8 @@ use std::rc::Rc;
 
 #[derive(Clone, PartialEq)]
 pub enum Categorization<'tcx> {
-    Rvalue(&'tcx ty::Region),                    // temporary val, argument is its scope
+    // temporary val, argument is its scope
+    Rvalue(&'tcx ty::Region, &'tcx ty::Region),
     StaticItem,
     Upvar(Upvar),                          // upvar referenced by closure env
     Local(ast::NodeId),                    // local variable
@@ -760,11 +761,18 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
 
     /// Returns the lifetime of a temporary created by expr with id `id`.
     /// This could be `'static` if `id` is part of a constant expression.
-    pub fn temporary_scope(&self, id: ast::NodeId) -> &'tcx ty::Region {
-        self.tcx().mk_region(match self.infcx.temporary_scope(id) {
+    pub fn temporary_scope(&self, id: ast::NodeId) -> (&'tcx ty::Region, &'tcx ty::Region)
+    {
+        let (scope, old_scope) =
+            self.tcx().region_maps.old_and_new_temporary_scope(id);
+        (self.tcx().mk_region(match scope {
+            Some(scope) => ty::ReScope(scope),
+            None => ty::ReStatic
+        }),
+         self.tcx().mk_region(match old_scope {
             Some(scope) => ty::ReScope(scope),
             None => ty::ReStatic
-        })
+        }))
     }
 
     pub fn cat_rvalue_node(&self,
@@ -785,12 +793,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         // Compute maximum lifetime of this rvalue. This is 'static if
         // we can promote to a constant, otherwise equal to enclosing temp
         // lifetime.
-        let re = if promotable {
-            self.tcx().mk_region(ty::ReStatic)
+        let (re, old_re) = if promotable {
+            (self.tcx().mk_region(ty::ReStatic),
+             self.tcx().mk_region(ty::ReStatic))
         } else {
             self.temporary_scope(id)
         };
-        let ret = self.cat_rvalue(id, span, re, expr_ty);
+        let ret = self.cat_rvalue(id, span, re, old_re, expr_ty);
         debug!("cat_rvalue_node ret {:?}", ret);
         ret
     }
@@ -799,11 +808,12 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                       cmt_id: ast::NodeId,
                       span: Span,
                       temp_scope: &'tcx ty::Region,
+                      old_temp_scope: &'tcx ty::Region,
                       expr_ty: Ty<'tcx>) -> cmt<'tcx> {
         let ret = Rc::new(cmt_ {
             id:cmt_id,
             span:span,
-            cat:Categorization::Rvalue(temp_scope),
+            cat:Categorization::Rvalue(temp_scope, old_temp_scope),
             mutbl:McDeclared,
             ty:expr_ty,
             note: NoteNone
@@ -1386,7 +1396,9 @@ impl<'tcx> fmt::Debug for Categorization<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             Categorization::StaticItem => write!(f, "static"),
-            Categorization::Rvalue(r) => write!(f, "rvalue({:?})", r),
+            Categorization::Rvalue(r, or) => {
+                write!(f, "rvalue({:?}, {:?})", r, or)
+            }
             Categorization::Local(id) => {
                let name = ty::tls::with(|tcx| tcx.local_var_name_str(id));
                write!(f, "local({})", name)
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 7337c03795b..a19f15a9329 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -272,6 +272,13 @@ pub struct RegionMaps {
     /// block (see `terminating_scopes`).
     rvalue_scopes: RefCell<NodeMap<CodeExtent>>,
 
+    /// Records the value of rvalue scopes before they were shrunk by
+    /// #36082, for error reporting.
+    ///
+    /// FIXME: this should be temporary. Remove this by 1.18.0 or
+    /// so.
+    shrunk_rvalue_scopes: RefCell<NodeMap<CodeExtent>>,
+
     /// Encodes the hierarchy of fn bodies. Every fn body (including
     /// closures) forms its own distinct region hierarchy, rooted in
     /// the block that is the fn body. This map points from the id of
@@ -419,11 +426,7 @@ impl RegionMaps {
             e(child, parent)
         }
     }
-    pub fn each_rvalue_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, &CodeExtent) {
-        for (child, parent) in self.rvalue_scopes.borrow().iter() {
-            e(child, parent)
-        }
-    }
+
     /// Records that `sub_fn` is defined within `sup_fn`. These ids
     /// should be the id of the block that is the fn body, which is
     /// also the root of the region hierarchy for that fn.
@@ -457,6 +460,12 @@ impl RegionMaps {
         self.rvalue_scopes.borrow_mut().insert(var, lifetime);
     }
 
+    fn record_shrunk_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
+        debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
+        assert!(var != lifetime.node_id(self));
+        self.shrunk_rvalue_scopes.borrow_mut().insert(var, lifetime);
+    }
+
     pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
         //! Returns the narrowest scope that encloses `id`, if any.
         self.scope_map.borrow()[id.0 as usize].into_option()
@@ -476,6 +485,30 @@ impl RegionMaps {
         }
     }
 
+    pub fn temporary_scope2(&self, expr_id: ast::NodeId) -> (Option<CodeExtent>, bool) {
+        let temporary_scope = self.temporary_scope(expr_id);
+        let was_shrunk = match self.shrunk_rvalue_scopes.borrow().get(&expr_id) {
+            Some(&s) => {
+                info!("temporary_scope2({:?}, scope={:?}, shrunk={:?})",
+                      expr_id, temporary_scope, s);
+                temporary_scope != Some(s)
+            }
+            _ => false
+        };
+        info!("temporary_scope2({:?}) - was_shrunk={:?}", expr_id, was_shrunk);
+        (temporary_scope, was_shrunk)
+    }
+
+    pub fn old_and_new_temporary_scope(&self, expr_id: ast::NodeId) ->
+        (Option<CodeExtent>, Option<CodeExtent>)
+    {
+        let temporary_scope = self.temporary_scope(expr_id);
+        (temporary_scope,
+         self.shrunk_rvalue_scopes
+             .borrow().get(&expr_id).cloned()
+             .or(temporary_scope))
+    }
+
     pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<CodeExtent> {
         //! Returns the scope when temp created by expr_id will be cleaned up
 
@@ -929,8 +962,10 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
         let is_borrow =
             if let Some(ref ty) = local.ty { is_borrowed_ty(&ty) } else { false };
 
-        if is_binding_pat(&local.pat) || is_borrow {
-            record_rvalue_scope(visitor, &expr, blk_scope);
+        if is_binding_pat(&local.pat) {
+            record_rvalue_scope(visitor, &expr, blk_scope, false);
+        } else if is_borrow {
+            record_rvalue_scope(visitor, &expr, blk_scope, true);
         }
     }
 
@@ -995,7 +1030,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
         match expr.node {
             hir::ExprAddrOf(_, ref subexpr) => {
                 record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id);
-                record_rvalue_scope(visitor, &subexpr, blk_id);
+                record_rvalue_scope(visitor, &subexpr, blk_id, false);
             }
             hir::ExprStruct(_, ref fields, _) => {
                 for field in fields {
@@ -1040,7 +1075,8 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
     /// Note: ET is intended to match "rvalues or lvalues based on rvalues".
     fn record_rvalue_scope<'a>(visitor: &mut RegionResolutionVisitor,
                                expr: &'a hir::Expr,
-                               blk_scope: CodeExtent) {
+                               blk_scope: CodeExtent,
+                               is_shrunk: bool) {
         let mut expr = expr;
         loop {
             // Note: give all the expressions matching `ET` with the
@@ -1048,7 +1084,12 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
             // because in trans if we must compile e.g. `*rvalue()`
             // into a temporary, we request the temporary scope of the
             // outer expression.
-            visitor.region_maps.record_rvalue_scope(expr.id, blk_scope);
+            if is_shrunk {
+                // this changed because of #36082
+                visitor.region_maps.record_shrunk_rvalue_scope(expr.id, blk_scope);
+            } else {
+                visitor.region_maps.record_rvalue_scope(expr.id, blk_scope);
+            }
 
             match expr.node {
                 hir::ExprAddrOf(_, ref subexpr) |
@@ -1225,6 +1266,7 @@ pub fn resolve_crate(sess: &Session, map: &hir_map::Map) -> RegionMaps {
         scope_map: RefCell::new(vec![]),
         var_map: RefCell::new(NodeMap()),
         rvalue_scopes: RefCell::new(NodeMap()),
+        shrunk_rvalue_scopes: RefCell::new(NodeMap()),
         fn_tree: RefCell::new(NodeMap()),
     };
     let root_extent = maps.bogus_code_extent(