diff options
| author | bors <bors@rust-lang.org> | 2017-01-26 17:42:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-01-26 17:42:52 +0000 |
| commit | 8430042a49bbd49bbb4fbc54f457feb5fb614f56 (patch) | |
| tree | a5fb7095092902f3168b86d671f0813d1228eaa4 /src/librustc/middle | |
| parent | 491b978822a56f23acf9ba46f90861958bc1e36c (diff) | |
| parent | 82a280597d967dc3ec8686f160a0afea4ad45837 (diff) | |
| download | rust-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.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/mem_categorization.rs | 30 | ||||
| -rw-r--r-- | src/librustc/middle/region.rs | 62 |
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( |
