]> git.lizzy.rs Git - rust.git/commitdiff
remove ROOT_CODE_EXTENT and DUMMY_CODE_EXTENT
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 19 Apr 2017 20:45:07 +0000 (16:45 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Sun, 30 Apr 2017 21:02:58 +0000 (17:02 -0400)
Instead, thread around `Option<CodeExtent>` where applicable.

22 files changed:
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/region_inference/mod.rs
src/librustc/middle/free_region.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/region.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/specialize/mod.rs
src/librustc/ty/fold.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/sty.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/mir_map.rs
src/librustc_mir/shim.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wfcheck.rs

index febf6af8763b290e713cc80f66792e34e2eb24f7..10712f5ec704790cddd1978801b685f7ee46d0c2 100644 (file)
@@ -69,6 +69,7 @@
 use ty::{self, TyCtxt, TypeFoldable};
 use ty::{Region, Issue32330};
 use ty::error::TypeError;
+use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::{Pos, Span};
 use errors::{DiagnosticBuilder, DiagnosticStyledString};
 
@@ -183,7 +184,8 @@ fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     }
                 };
 
-                let node = fr.scope.node_id(&self.region_maps());
+                let node = fr.scope.map(|s| s.node_id(&self.region_maps()))
+                                   .unwrap_or(DUMMY_NODE_ID);
                 let unknown;
                 let tag = match self.hir.find(node) {
                     Some(hir_map::NodeBlock(_)) |
index 19752f3363ad7fdadb814919009419ccfd5aca91..f9aab59acaf6cf262c73d0665e8f4094258c1658 100644 (file)
@@ -938,18 +938,19 @@ fn lub_concrete_regions(&self,
                 // A "free" region can be interpreted as "some region
                 // at least as big as the block fr.scope_id".  So, we can
                 // reasonably compare free regions and scopes:
-                let r_id = self.tcx.region_maps().nearest_common_ancestor(fr.scope, s_id);
-
-                if r_id == fr.scope {
-                    // if the free region's scope `fr.scope_id` is bigger than
-                    // the scope region `s_id`, then the LUB is the free
-                    // region itself:
-                    self.tcx.mk_region(ReFree(fr))
-                } else {
-                    // otherwise, we don't know what the free region is,
-                    // so we must conservatively say the LUB is static:
-                    self.tcx.types.re_static
+                if let Some(fr_scope) = fr.scope {
+                    let r_id = self.tcx.region_maps().nearest_common_ancestor(fr_scope, s_id);
+                    if r_id == fr_scope {
+                        // if the free region's scope `fr.scope_id` is bigger than
+                        // the scope region `s_id`, then the LUB is the free
+                        // region itself:
+                        return self.tcx.mk_region(ReFree(fr));
+                    }
                 }
+
+                // otherwise, we don't know what the free region is,
+                // so we must conservatively say the LUB is static:
+                self.tcx.types.re_static
             }
 
             (&ReScope(a_id), &ReScope(b_id)) => {
index f622dfc683b60b34e0c596c12da94e755069b075..9701595a9d87296db448dd8de624d994c7734bbd 100644 (file)
@@ -138,9 +138,14 @@ pub fn is_subregion_of(&self,
                 (&ty::ReScope(sub_scope), &ty::ReScope(super_scope)) =>
                     tcx.region_maps().is_subscope_of(sub_scope, super_scope),
 
-                (&ty::ReScope(sub_scope), &ty::ReFree(fr)) =>
-                    tcx.region_maps().is_subscope_of(sub_scope, fr.scope) ||
-                    self.is_static(fr),
+                (&ty::ReScope(sub_scope), &ty::ReFree(fr)) => {
+                    // 1. It is safe to unwrap `fr.scope` because we
+                    // should only ever wind up comparing against
+                    // `ReScope` in the context of a method or fn
+                    // body, where `fr.scope` should be `Some`.
+                    tcx.region_maps().is_subscope_of(sub_scope, fr.scope.unwrap() /*1*/) ||
+                        self.is_static(fr)
+                }
 
                 (&ty::ReFree(sub_fr), &ty::ReFree(super_fr)) =>
                     self.sub_free_region(sub_fr, super_fr),
@@ -166,9 +171,7 @@ pub fn is_static(&self, super_region: ty::FreeRegion) -> bool {
 
 #[cfg(test)]
 fn free_region(index: u32) -> FreeRegion {
-    use middle::region::DUMMY_CODE_EXTENT;
-    FreeRegion { scope: DUMMY_CODE_EXTENT,
-                 bound_region: ty::BoundRegion::BrAnon(index) }
+    FreeRegion { scope: None, bound_region: ty::BoundRegion::BrAnon(index) }
 }
 
 #[test]
index 73c8d1db312bb4f6fd25fb89da6f69bfe111e9fa..508dfe9cfcd8b717721e4c588f6ee01a62d526ff 100644 (file)
@@ -1441,7 +1441,7 @@ fn check_ret(&self,
         // and must outlive the *call-site* of the function.
         let fn_ret =
             self.ir.tcx.liberate_late_bound_regions(
-                self.ir.tcx.region_maps().call_site_extent(id, body.value.id),
+                Some(self.ir.tcx.region_maps().call_site_extent(id, body.value.id)),
                 &fn_ret);
 
         if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
index b398255aedeb16880b09e73dd4708b81b54562a7..92777bb160463df2379612b39d4536aa58a61211 100644 (file)
@@ -796,7 +796,7 @@ fn env_deref(&self,
             // The environment of a closure is guaranteed to
             // outlive any bindings introduced in the body of the
             // closure itself.
-            scope: self.tcx().region_maps().item_extent(fn_body_id),
+            scope: Some(self.tcx().region_maps().item_extent(fn_body_id)),
             bound_region: ty::BrEnv
         }));
 
index 0c35d38d68498037b192b0675041e18a4ae68110..e381a904478b78d7408e6d4b297b464c3013d941 100644 (file)
@@ -34,7 +34,7 @@
 use hir;
 use hir::def_id::{CrateNum, LOCAL_CRATE};
 use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
-use hir::{Block, Item, FnDecl, Arm, Pat, PatKind, Stmt, Expr, Local};
+use hir::{Body, Block, Item, FnDecl, Arm, Pat, PatKind, Stmt, Expr, Local};
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
            RustcDecodable, Copy)]
@@ -62,12 +62,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-/// The root of everything. I should be using NonZero or profiling
-/// instead of this (probably).
-pub const ROOT_CODE_EXTENT : CodeExtent = CodeExtent(0);
-/// A placeholder used in trans to stand for real code extents
-pub const DUMMY_CODE_EXTENT : CodeExtent = CodeExtent(1);
-
 /// CodeExtent represents a statically-describable extent that can be
 /// used to bound the lifetime/region for values.
 ///
@@ -209,14 +203,6 @@ pub fn node_id(&self) -> ast::NodeId {
 }
 
 impl CodeExtent {
-    #[inline]
-    fn into_option(self) -> Option<CodeExtent> {
-        if self == ROOT_CODE_EXTENT {
-            None
-        } else {
-            Some(self)
-        }
-    }
     pub fn node_id(&self, region_maps: &RegionMaps) -> ast::NodeId {
         region_maps.code_extent_data(*self).node_id()
     }
@@ -265,7 +251,7 @@ pub struct RegionMaps {
     /// conditional expression or repeating block. (Note that the
     /// enclosing scope id for the block associated with a closure is
     /// the closure itself.)
-    scope_map: Vec<CodeExtent>,
+    scope_map: Vec<Option<CodeExtent>>,
 
     /// `var_map` maps from a variable or binding id to the block in
     /// which that variable is declared.
@@ -310,10 +296,10 @@ pub struct Context {
     root_id: Option<ast::NodeId>,
 
     /// the scope that contains any new variables declared
-    var_parent: CodeExtent,
+    var_parent: Option<CodeExtent>,
 
     /// region parent of expressions etc
-    parent: CodeExtent
+    parent: Option<CodeExtent>,
 }
 
 struct RegionResolutionVisitor<'hir: 'a, 'a> {
@@ -351,11 +337,6 @@ struct RegionResolutionVisitor<'hir: 'a, 'a> {
 
 
 impl RegionMaps {
-    /// create a bogus code extent for the regions in astencode types. Nobody
-    /// really cares about the contents of these.
-    pub fn bogus_code_extent(&mut self, e: CodeExtentData) -> CodeExtent {
-        self.intern_code_extent(e, DUMMY_CODE_EXTENT)
-    }
     pub fn lookup_code_extent(&self, e: CodeExtentData) -> CodeExtent {
         match self.code_extent_interner.get(&e) {
             Some(&d) => d,
@@ -378,26 +359,10 @@ pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent> {
     }
     pub fn intern_code_extent(&mut self,
                               e: CodeExtentData,
-                              parent: CodeExtent) -> CodeExtent {
+                              parent: Option<CodeExtent>) -> CodeExtent {
         match self.code_extent_interner.entry(e) {
-            Entry::Occupied(o) => {
-                // this can happen when the bogus code extents from tydecode
-                // have (bogus) NodeId-s that overlap items created during
-                // inlining.
-                // We probably shouldn't be creating bogus code extents
-                // though.
-                let idx = *o.get();
-                if parent == DUMMY_CODE_EXTENT {
-                    info!("CodeExtent({}) = {:?} [parent={}] BOGUS!",
-                          idx.0, e, parent.0);
-                } else {
-                    assert_eq!(self.scope_map[idx.0 as usize],
-                               DUMMY_CODE_EXTENT);
-                    info!("CodeExtent({}) = {:?} [parent={}] RECLAIMED!",
-                          idx.0, e, parent.0);
-                    self.scope_map[idx.0 as usize] = parent;
-                }
-                idx
+            Entry::Occupied(_) => {
+                bug!("intern_code_extent: already exists")
             }
             Entry::Vacant(v) => {
                 if self.code_extents.len() > 0xffffffffusize {
@@ -405,7 +370,7 @@ pub fn intern_code_extent(&mut self,
                            // but this isn't the only place
                 }
                 let idx = CodeExtent(self.code_extents.len() as u32);
-                debug!("CodeExtent({}) = {:?} [parent={}]", idx.0, e, parent.0);
+                debug!("CodeExtent({:?}) = {:?} [parent={:?}]", idx, e, parent);
                 self.code_extents.push(e);
                 self.scope_map.push(parent);
                 *v.insert(idx)
@@ -414,7 +379,7 @@ pub fn intern_code_extent(&mut self,
     }
     pub fn intern_node(&mut self,
                        n: ast::NodeId,
-                       parent: CodeExtent) -> CodeExtent {
+                       parent: Option<CodeExtent>) -> CodeExtent {
         self.intern_code_extent(CodeExtentData::Misc(n), parent)
     }
     pub fn code_extent_data(&self, e: CodeExtent) -> CodeExtentData {
@@ -474,7 +439,7 @@ fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent)
 
     pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
         //! Returns the narrowest scope that encloses `id`, if any.
-        self.scope_map[id.0 as usize].into_option()
+        self.scope_map[id.0 as usize]
     }
 
     #[allow(dead_code)] // used in cfg
@@ -524,7 +489,7 @@ pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<CodeExtent> {
             return Some(s);
         }
 
-        let scope_map : &[CodeExtent] = &self.scope_map;
+        let scope_map : &[Option<CodeExtent>] = &self.scope_map;
         let code_extents: &[CodeExtentData] = &self.code_extents;
 
         // else, locate the innermost terminating scope
@@ -533,7 +498,7 @@ pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<CodeExtent> {
         // returned.
         let mut id = self.node_extent(expr_id);
 
-        while let Some(p) = scope_map[id.0 as usize].into_option() {
+        while let Some(p) = scope_map[id.0 as usize] {
             match code_extents[p.0 as usize] {
                 CodeExtentData::DestructionScope(..) => {
                     debug!("temporary_scope({:?}) = {:?} [enclosing]",
@@ -595,15 +560,17 @@ pub fn nearest_common_ancestor(&self,
                                    -> CodeExtent {
         if scope_a == scope_b { return scope_a; }
 
-        let mut a_buf: [CodeExtent; 32] = [ROOT_CODE_EXTENT; 32];
+        /// [1] The initial values for `a_buf` and `b_buf` are not used.
+        /// The `ancestors_of` function will return some prefix that
+        /// is re-initialized with new values (or else fallback to a
+        /// heap-allocated vector).
+        let mut a_buf: [CodeExtent; 32] = [scope_a /* [1] */; 32];
         let mut a_vec: Vec<CodeExtent> = vec![];
-        let mut b_buf: [CodeExtent; 32] = [ROOT_CODE_EXTENT; 32];
+        let mut b_buf: [CodeExtent; 32] = [scope_b /* [1] */; 32];
         let mut b_vec: Vec<CodeExtent> = vec![];
-        let scope_map : &[CodeExtent] = &self.scope_map;
-        let a_ancestors = ancestors_of(scope_map,
-                                       scope_a, &mut a_buf, &mut a_vec);
-        let b_ancestors = ancestors_of(scope_map,
-                                       scope_b, &mut b_buf, &mut b_vec);
+        let scope_map : &[Option<CodeExtent>] = &self.scope_map;
+        let a_ancestors = ancestors_of(scope_map, scope_a, &mut a_buf, &mut a_vec);
+        let b_ancestors = ancestors_of(scope_map, scope_b, &mut b_buf, &mut b_vec);
         let mut a_index = a_ancestors.len() - 1;
         let mut b_index = b_ancestors.len() - 1;
 
@@ -656,17 +623,18 @@ pub fn nearest_common_ancestor(&self,
             }
         }
 
-        fn ancestors_of<'a>(scope_map: &[CodeExtent],
+        fn ancestors_of<'a>(scope_map: &[Option<CodeExtent>],
                             scope: CodeExtent,
                             buf: &'a mut [CodeExtent; 32],
-                            vec: &'a mut Vec<CodeExtent>) -> &'a [CodeExtent] {
+                            vec: &'a mut Vec<CodeExtent>)
+                            -> &'a [CodeExtent] {
             // debug!("ancestors_of(scope={:?})", scope);
             let mut scope = scope;
 
             let mut i = 0;
             while i < 32 {
                 buf[i] = scope;
-                match scope_map[scope.0 as usize].into_option() {
+                match scope_map[scope.0 as usize] {
                     Some(superscope) => scope = superscope,
                     _ => return &buf[..i+1]
                 }
@@ -677,7 +645,7 @@ fn ancestors_of<'a>(scope_map: &[CodeExtent],
             vec.extend_from_slice(buf);
             loop {
                 vec.push(scope);
-                match scope_map[scope.0 as usize].into_option() {
+                match scope_map[scope.0 as usize] {
                     Some(superscope) => scope = superscope,
                     _ => return &*vec
                 }
@@ -691,12 +659,12 @@ fn record_var_lifetime(visitor: &mut RegionResolutionVisitor,
                        var_id: ast::NodeId,
                        _sp: Span) {
     match visitor.cx.var_parent {
-        ROOT_CODE_EXTENT => {
+        None => {
             // this can happen in extern fn declarations like
             //
             // extern fn isalnum(c: c_int) -> c_int
         }
-        parent_scope =>
+        Some(parent_scope) =>
             visitor.region_maps.record_var_scope(var_id, parent_scope),
     }
 }
@@ -734,8 +702,8 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, blk:
 
     visitor.cx = Context {
         root_id: prev_cx.root_id,
-        var_parent: block_extent,
-        parent: block_extent,
+        var_parent: Some(block_extent),
+        parent: Some(block_extent),
     };
 
     {
@@ -760,8 +728,8 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, blk:
                 );
                 visitor.cx = Context {
                     root_id: prev_cx.root_id,
-                    var_parent: stmt_extent,
-                    parent: stmt_extent,
+                    var_parent: Some(stmt_extent),
+                    parent: Some(stmt_extent),
                 };
             }
             visitor.visit_stmt(statement)
@@ -806,7 +774,7 @@ fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, stmt:
     let stmt_extent = visitor.new_node_extent_with_dtor(stmt_id);
 
     let prev_parent = visitor.cx.parent;
-    visitor.cx.parent = stmt_extent;
+    visitor.cx.parent = Some(stmt_extent);
     intravisit::walk_stmt(visitor, stmt);
     visitor.cx.parent = prev_parent;
 }
@@ -816,7 +784,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, expr:
 
     let expr_extent = visitor.new_node_extent_with_dtor(expr.id);
     let prev_cx = visitor.cx;
-    visitor.cx.parent = expr_extent;
+    visitor.cx.parent = Some(expr_extent);
 
     {
         let terminating_scopes = &mut visitor.terminating_scopes;
@@ -856,7 +824,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, expr:
             }
 
             hir::ExprMatch(..) => {
-                visitor.cx.var_parent = expr_extent;
+                visitor.cx.var_parent = Some(expr_extent);
             }
 
             hir::ExprAssignOp(..) | hir::ExprIndex(..) |
@@ -898,7 +866,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
     // scope that will be used for any bindings declared in this
     // pattern.
     let blk_scope = visitor.cx.var_parent;
-    assert!(blk_scope != ROOT_CODE_EXTENT); // locals must be within a block
+    let blk_scope = blk_scope.expect("locals must be within a block");
     visitor.region_maps.record_var_scope(local.id, blk_scope);
 
     // As an exception to the normal rules governing temporary
@@ -1123,8 +1091,8 @@ fn resolve_item_like<'a, 'tcx, F>(visitor: &mut RegionResolutionVisitor<'tcx, 'a
     let prev_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet());
     visitor.cx = Context {
         root_id: None,
-        var_parent: ROOT_CODE_EXTENT,
-        parent: ROOT_CODE_EXTENT
+        var_parent: None,
+        parent: None,
     };
     walk(visitor);
     visitor.create_item_scope_if_needed(id);
@@ -1147,8 +1115,8 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
            body_id,
            visitor.cx.parent);
 
-    visitor.cx.parent = visitor.new_code_extent(
-        CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
+    visitor.cx.parent = Some(visitor.new_code_extent(
+        CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id }));
 
     let fn_decl_scope = visitor.new_code_extent(
         CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id });
@@ -1164,8 +1132,8 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
     // The arguments and `self` are parented to the fn.
     visitor.cx = Context {
         root_id: Some(body_id.node_id),
-        parent: ROOT_CODE_EXTENT,
-        var_parent: fn_decl_scope,
+        parent: None,
+        var_parent: Some(fn_decl_scope),
     };
 
     intravisit::walk_fn_decl(visitor, decl);
@@ -1174,8 +1142,8 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
     // The body of the every fn is a root scope.
     visitor.cx = Context {
         root_id: Some(body_id.node_id),
-        parent: fn_decl_scope,
-        var_parent: fn_decl_scope
+        parent: Some(fn_decl_scope),
+        var_parent: Some(fn_decl_scope),
     };
     visitor.visit_nested_body(body_id);
 
@@ -1202,7 +1170,7 @@ fn new_node_extent_with_dtor(&mut self, id: ast::NodeId) -> CodeExtent {
         if self.terminating_scopes.contains(&id) {
             let ds = self.new_code_extent(
                 CodeExtentData::DestructionScope(id));
-            self.region_maps.intern_node(id, ds)
+            self.region_maps.intern_node(id, Some(ds))
         } else {
             self.new_node_extent(id)
         }
@@ -1215,7 +1183,7 @@ fn create_item_scope_if_needed(&mut self, id: ast::NodeId) {
         // scopes.
         let scope = CodeExtentData::DestructionScope(id);
         if !self.region_maps.code_extent_interner.contains_key(&scope) {
-            self.region_maps.intern_code_extent(scope, ROOT_CODE_EXTENT);
+            self.region_maps.intern_code_extent(scope, None);
         }
     }
 }
@@ -1225,6 +1193,15 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
         NestedVisitorMap::OnlyBodies(&self.map)
     }
 
+    fn visit_body(&mut self, b: &'hir Body) {
+        // make sure that every body owner has an item scope, since
+        // MIR construction wants that
+        let owner = self.map.body_owner(b.id());
+        self.create_item_scope_if_needed(owner);
+
+        intravisit::walk_body(self, b);
+    }
+
     fn visit_block(&mut self, b: &'hir Block) {
         resolve_block(self, b);
     }
@@ -1285,12 +1262,6 @@ fn region_resolve_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateN
         shrunk_rvalue_scopes: NodeMap(),
         fn_tree: NodeMap(),
     };
-    let root_extent = maps.bogus_code_extent(
-        CodeExtentData::DestructionScope(ast::DUMMY_NODE_ID));
-    assert_eq!(root_extent, ROOT_CODE_EXTENT);
-    let bogus_extent = maps.bogus_code_extent(
-        CodeExtentData::Misc(ast::DUMMY_NODE_ID));
-    assert_eq!(bogus_extent, DUMMY_CODE_EXTENT);
     {
         let mut visitor = RegionResolutionVisitor {
             sess: sess,
@@ -1298,8 +1269,8 @@ fn region_resolve_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateN
             map: hir_map,
             cx: Context {
                 root_id: None,
-                parent: ROOT_CODE_EXTENT,
-                var_parent: ROOT_CODE_EXTENT
+                parent: None,
+                var_parent: None,
             },
             terminating_scopes: NodeSet()
         };
index 98b502f5608e75b445d2e21cb805e4b0d5790e9d..ea1a2f9a982c93d51322d2bb361b4f44faa9b533 100644 (file)
@@ -206,8 +206,7 @@ fn generics_require_sized_self(self, def_id: DefId) -> bool {
         };
 
         // Search for a predicate like `Self : Sized` amongst the trait bounds.
-        let free_substs = self.construct_free_substs(def_id,
-            self.region_maps().node_extent(ast::DUMMY_NODE_ID));
+        let free_substs = self.construct_free_substs(def_id, None);
         let predicates = self.predicates_of(def_id);
         let predicates = predicates.instantiate(self, free_substs).predicates;
         elaborate_predicates(self, predicates)
index 6c685851e2593dc31c48ec3d9ed98b2971119dc8..d5d17e3c81214901b8f3a6b7cbb9fabced4d7f54 100644 (file)
@@ -23,7 +23,6 @@
 use rustc_data_structures::fx::FxHashMap;
 use hir::def_id::DefId;
 use infer::{InferCtxt, InferOk};
-use middle::region;
 use ty::subst::{Subst, Substs};
 use traits::{self, Reveal, ObligationCause};
 use ty::{self, TyCtxt, TypeFoldable};
@@ -182,7 +181,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // create a parameter environment corresponding to a (skolemized) instantiation of impl1
     let penv = tcx.construct_parameter_environment(DUMMY_SP,
                                                    impl1_def_id,
-                                                   region::DUMMY_CODE_EXTENT);
+                                                   None);
     let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
                              .unwrap()
                              .subst(tcx, &penv.free_substs);
index 969d040e7a6e8f94e92fdd724be49dbce6769907..1cf6c3f334f6a76dd9f9bf3987b4f318ad7fa3fa 100644 (file)
@@ -330,7 +330,7 @@ pub fn replace_late_bound_regions<T,F>(self,
     /// Replace any late-bound regions bound in `value` with free variants attached to scope-id
     /// `scope_id`.
     pub fn liberate_late_bound_regions<T>(self,
-        all_outlive_scope: region::CodeExtent,
+        all_outlive_scope: Option<region::CodeExtent>,
         value: &Binder<T>)
         -> T
         where T : TypeFoldable<'tcx>
index 49cc4e7c993a53de08f46a0c11feab317722c3ec..480b8967a79e9e907ac44964f5cfbfbdc01933b2 100644 (file)
@@ -1268,9 +1268,8 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
                         StructKind::AlwaysSizedUnivariant
                     } else {
-                        use middle::region::ROOT_CODE_EXTENT;
                         let param_env = tcx.construct_parameter_environment(DUMMY_SP,
-                          def.did, ROOT_CODE_EXTENT);
+                          def.did, None);
                         let fields = &def.variants[0].fields;
                         let last_field = &fields[fields.len()-1];
                         let always_sized = last_field.ty(tcx, param_env.free_substs)
index c0b340ad54455d329fcbf65f4c21d3b60094eab5..fd0b1308c9572e44ebfc290541fac6d0c4610079 100644 (file)
@@ -23,7 +23,7 @@
 use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::privacy::AccessLevels;
-use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
+use middle::region::CodeExtent;
 use middle::resolve_lifetime::ObjectLifetimeDefault;
 use mir::Mir;
 use traits;
@@ -46,7 +46,7 @@
 use std::slice;
 use std::vec::IntoIter;
 use std::mem;
-use syntax::ast::{self, Name, NodeId};
+use syntax::ast::{self, DUMMY_NODE_ID, Name, NodeId};
 use syntax::attr;
 use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
@@ -1164,22 +1164,24 @@ pub struct ParameterEnvironment<'tcx> {
     /// Each type parameter has an implicit region bound that
     /// indicates it must outlive at least the function body (the user
     /// may specify stronger requirements). This field indicates the
-    /// region of the callee.
-    pub implicit_region_bound: &'tcx ty::Region,
+    /// region of the callee. If it is `None`, then the parameter
+    /// environment is for an item or something where the "callee" is
+    /// not clear.
+    pub implicit_region_bound: Option<&'tcx ty::Region>,
 
     /// Obligations that the caller must satisfy. This is basically
     /// the set of bounds on the in-scope type parameters, translated
     /// into Obligations, and elaborated and normalized.
     pub caller_bounds: Vec<ty::Predicate<'tcx>>,
 
-    /// Scope that is attached to free regions for this scope. This
-    /// is usually the id of the fn body, but for more abstract scopes
-    /// like structs we often use the node-id of the struct.
+    /// Scope that is attached to free regions for this scope. This is
+    /// usually the id of the fn body, but for more abstract scopes
+    /// like structs we use None or the item extent.
     ///
     /// FIXME(#3696). It would be nice to refactor so that free
     /// regions don't have this implicit scope and instead introduce
     /// relationships in the environment.
-    pub free_id_outlive: CodeExtent,
+    pub free_id_outlive: Option<CodeExtent>,
 
     /// A cache for `moves_by_default`.
     pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
@@ -1220,13 +1222,13 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         let impl_def_id = tcx.hir.local_def_id(impl_id);
                         tcx.construct_parameter_environment(impl_item.span,
                                                             impl_def_id,
-                                                            tcx.region_maps().item_extent(id))
+                                                            Some(tcx.region_maps().item_extent(id)))
                     }
                     hir::ImplItemKind::Method(_, ref body) => {
                         tcx.construct_parameter_environment(
                             impl_item.span,
                             tcx.hir.local_def_id(id),
-                            tcx.region_maps().call_site_extent(id, body.node_id))
+                            Some(tcx.region_maps().call_site_extent(id, body.node_id)))
                     }
                 }
             }
@@ -1239,7 +1241,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         let trait_def_id = tcx.hir.local_def_id(trait_id);
                         tcx.construct_parameter_environment(trait_item.span,
                                                             trait_def_id,
-                                                            tcx.region_maps().item_extent(id))
+                                                            Some(tcx.region_maps().item_extent(id)))
                     }
                     hir::TraitItemKind::Method(_, ref body) => {
                         // Use call-site for extent (unless this is a
@@ -1255,7 +1257,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         tcx.construct_parameter_environment(
                             trait_item.span,
                             tcx.hir.local_def_id(id),
-                            extent)
+                            Some(extent))
                     }
                 }
             }
@@ -1268,7 +1270,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         tcx.construct_parameter_environment(
                             item.span,
                             fn_def_id,
-                            tcx.region_maps().call_site_extent(id, body_id.node_id))
+                            Some(tcx.region_maps().call_site_extent(id, body_id.node_id)))
                     }
                     hir::ItemEnum(..) |
                     hir::ItemStruct(..) |
@@ -1280,13 +1282,13 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         let def_id = tcx.hir.local_def_id(id);
                         tcx.construct_parameter_environment(item.span,
                                                             def_id,
-                                                            tcx.region_maps().item_extent(id))
+                                                            Some(tcx.region_maps().item_extent(id)))
                     }
                     hir::ItemTrait(..) => {
                         let def_id = tcx.hir.local_def_id(id);
                         tcx.construct_parameter_environment(item.span,
                                                             def_id,
-                                                            tcx.region_maps().item_extent(id))
+                                                            Some(tcx.region_maps().item_extent(id)))
                     }
                     _ => {
                         span_bug!(item.span,
@@ -1304,7 +1306,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                     tcx.construct_parameter_environment(
                         expr.span,
                         base_def_id,
-                        tcx.region_maps().call_site_extent(id, body.node_id))
+                        Some(tcx.region_maps().call_site_extent(id, body.node_id)))
                 } else {
                     tcx.empty_parameter_environment()
                 }
@@ -1313,14 +1315,14 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                 let def_id = tcx.hir.local_def_id(id);
                 tcx.construct_parameter_environment(item.span,
                                                     def_id,
-                                                    ROOT_CODE_EXTENT)
+                                                    None)
             }
             Some(hir_map::NodeStructCtor(..)) |
             Some(hir_map::NodeVariant(..)) => {
                 let def_id = tcx.hir.local_def_id(id);
                 tcx.construct_parameter_environment(tcx.hir.span(id),
                                                     def_id,
-                                                    ROOT_CODE_EXTENT)
+                                                    None)
             }
             it => {
                 bug!("ParameterEnvironment::from_item(): \
@@ -2439,10 +2441,8 @@ pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
         ty::ParameterEnvironment {
             free_substs: self.intern_substs(&[]),
             caller_bounds: Vec::new(),
-            implicit_region_bound: self.types.re_empty,
-            // for an empty parameter environment, there ARE no free
-            // regions, so it shouldn't matter what we use for the free id
-            free_id_outlive: ROOT_CODE_EXTENT,
+            implicit_region_bound: None,
+            free_id_outlive: None,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
             is_freeze_cache: RefCell::new(FxHashMap()),
@@ -2455,7 +2455,7 @@ pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
     /// free parameters. Since we currently represent bound/free type
     /// parameters in the same way, this only has an effect on regions.
     pub fn construct_free_substs(self, def_id: DefId,
-                                 free_id_outlive: CodeExtent)
+                                 free_id_outlive: Option<CodeExtent>)
                                  -> &'gcx Substs<'gcx> {
 
         let substs = Substs::for_item(self.global_tcx(), def_id, |def, _| {
@@ -2479,7 +2479,7 @@ pub fn construct_free_substs(self, def_id: DefId,
     pub fn construct_parameter_environment(self,
                                            span: Span,
                                            def_id: DefId,
-                                           free_id_outlive: CodeExtent)
+                                           free_id_outlive: Option<CodeExtent>)
                                            -> ParameterEnvironment<'gcx>
     {
         //
@@ -2513,7 +2513,7 @@ pub fn construct_parameter_environment(self,
 
         let unnormalized_env = ty::ParameterEnvironment {
             free_substs: free_substs,
-            implicit_region_bound: tcx.mk_region(ty::ReScope(free_id_outlive)),
+            implicit_region_bound: free_id_outlive.map(|f| tcx.mk_region(ty::ReScope(f))),
             caller_bounds: predicates,
             free_id_outlive: free_id_outlive,
             is_copy_cache: RefCell::new(FxHashMap()),
@@ -2521,8 +2521,9 @@ pub fn construct_parameter_environment(self,
             is_freeze_cache: RefCell::new(FxHashMap()),
         };
 
-        let cause = traits::ObligationCause::misc(span,
-                                                  free_id_outlive.node_id(&self.region_maps()));
+        let body_id = free_id_outlive.map(|f| f.node_id(&self.region_maps()))
+                                     .unwrap_or(DUMMY_NODE_ID);
+        let cause = traits::ObligationCause::misc(span, body_id);
         traits::normalize_param_env_or_error(tcx, unnormalized_env, cause)
     }
 
index 7857d07ed0910de41aae5a39d10557eff16664c9..02c4bad8e4e1c49a8cdbc783d667b2d130b23951 100644 (file)
@@ -43,8 +43,12 @@ pub struct TypeAndMut<'tcx> {
          RustcEncodable, RustcDecodable, Copy)]
 /// A "free" region `fr` can be interpreted as "some region
 /// at least as big as the scope `fr.scope`".
+///
+/// If `fr.scope` is None, then this is in some context (e.g., an
+/// impl) where lifetimes are more abstract and the notion of the
+/// caller/callee stack frames are not applicable.
 pub struct FreeRegion {
-    pub scope: region::CodeExtent,
+    pub scope: Option<region::CodeExtent>,
     pub bound_region: BoundRegion,
 }
 
index 41fab1f3a4fc0a6b62f6a9293cd472ee7d2edeb5..f5cdd40714cdb4e893106feaa6aa7490f67d1e87 100644 (file)
@@ -353,7 +353,7 @@ fn guarantee_valid(&mut self,
                 let loan_scope = match *loan_region {
                     ty::ReScope(scope) => scope,
 
-                    ty::ReFree(ref fr) => fr.scope,
+                    ty::ReFree(ref fr) => fr.scope.unwrap_or(self.item_ub),
 
                     ty::ReStatic => self.item_ub,
 
index 2afaaaf0878542378573c05b9aef1f91b9ca0c10..f3a258a8ca58a60d69500457c92dc296f75d4482 100644 (file)
@@ -11,7 +11,7 @@
 use hair::cx::Cx;
 use hair::Pattern;
 
-use rustc::middle::region::{CodeExtent, CodeExtentData, ROOT_CODE_EXTENT};
+use rustc::middle::region::{CodeExtent, CodeExtentData};
 use rustc::ty::{self, Ty};
 use rustc::mir::*;
 use rustc::util::nodemap::NodeMap;
@@ -200,11 +200,13 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
     let tcx = hir.tcx();
     let ast_expr = &tcx.hir.body(body_id).value;
     let ty = hir.tables().expr_ty_adjusted(ast_expr);
-    let span = tcx.hir.span(tcx.hir.body_owner(body_id));
+    let owner_id = tcx.hir.body_owner(body_id);
+    let span = tcx.hir.span(owner_id);
     let mut builder = Builder::new(hir, span, 0, ty);
 
-    let extent = tcx.region_maps().temporary_scope(ast_expr.id)
-                    .unwrap_or(ROOT_CODE_EXTENT);
+    let region_maps = tcx.region_maps();
+    let extent = region_maps.temporary_scope(ast_expr.id)
+                            .unwrap_or(region_maps.item_extent(owner_id));
     let mut block = START_BLOCK;
     let _ = builder.in_scope(extent, block, |builder| {
         let expr = builder.hir.mirror(ast_expr);
index ae63828f0ac76132163048e172d0bb427eda808f..ad51530b19152b1fe69c018830860055a2d58d39 100644 (file)
@@ -828,7 +828,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             // signature will be &self or &mut self and hence will
             // have a bound region with number 0
             let region = ty::Region::ReFree(ty::FreeRegion {
-                scope: cx.tcx.region_maps().node_extent(body_id),
+                scope: Some(cx.tcx.region_maps().node_extent(body_id)),
                 bound_region: ty::BoundRegion::BrAnon(0),
             });
             let region = cx.tcx.mk_region(region);
index d8604f65dff92144c4585eb186db487dd5ac8662..cbd88733e82deb9ff049cdc5b44ea7d3c255f194 100644 (file)
@@ -253,7 +253,7 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
 
     let region = ty::Region::ReFree(ty::FreeRegion {
-        scope: tcx.region_maps().item_extent(body_id.node_id),
+        scope: Some(tcx.region_maps().item_extent(body_id.node_id)),
         bound_region: ty::BoundRegion::BrEnv,
     });
     let region = tcx.mk_region(region);
index 9e57472c23657ca86f2e201acd4a5aedef825e29..f2a550ec23a8e2abb04cea2d2dd1a7c433bed7e0 100644 (file)
@@ -11,7 +11,6 @@
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::infer;
-use rustc::middle::region::ROOT_CODE_EXTENT;
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::transform::MirSource;
@@ -45,8 +44,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
     debug!("make_shim({:?})", instance);
     let did = instance.def_id();
     let span = tcx.def_span(did);
-    let param_env =
-        tcx.construct_parameter_environment(span, did, ROOT_CODE_EXTENT);
+    let param_env = tcx.construct_parameter_environment(span, did, None);
 
     let mut result = match instance {
         ty::InstanceDef::Item(..) =>
index eb897d10d25894f9b014b5c71775a3ae82589cf3..d672637649e85f3e8f7a3f9475290750fd398fdd 100644 (file)
@@ -133,7 +133,7 @@ pub fn ast_region_to_region(&self,
             Some(&rl::Region::Free(scope, id)) => {
                 let name = tcx.hir.name(id);
                 tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                    scope: scope.to_code_extent(&tcx.region_maps()),
+                    scope: Some(scope.to_code_extent(&tcx.region_maps())),
                     bound_region: ty::BrNamed(tcx.hir.local_def_id(id), name)
                 }))
 
index c74d71babc2dfdd608c62f5a8810f18413567d62..5d24df136ff19fd6a464a302b14a0b658e9cdeeb 100644 (file)
@@ -74,7 +74,7 @@ fn check_closure(&self,
         debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
 
         let extent = self.tcx.region_maps().call_site_extent(expr.id, body.value.id);
-        let fn_sig = self.tcx.liberate_late_bound_regions(extent, &sig);
+        let fn_sig = self.tcx.liberate_late_bound_regions(Some(extent), &sig);
         let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
                                                             body.value.id, &fn_sig);
 
index e40d8f6cafca324a4637f66812ffecdd11485567..8b366fd5a277061e374cbdb0a27128fd01b24df9 100644 (file)
@@ -785,7 +785,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let fn_sig =
                 fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
             let fn_sig =
-                inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig);
+                inh.tcx.liberate_late_bound_regions(Some(fn_scope), &fn_sig);
             let fn_sig =
                 inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);
 
index 16297709b194a59d9f171cdc904fc87654b3813f..a6f72898a5495a28c71e8c7b219ff6d256e87af7 100644 (file)
@@ -1614,7 +1614,7 @@ fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
 
         // Add in the default bound of fn body that applies to all in
         // scope type parameters:
-        param_bounds.push(param_env.implicit_region_bound);
+        param_bounds.extend(param_env.implicit_region_bound);
 
         VerifyBound::AnyRegion(param_bounds)
     }
index 08024c9e9e691a9e82bbade0ded9a7ec0703333d..f306d5dd70f29903ae213be1a85c3e3f116980ca 100644 (file)
@@ -343,7 +343,7 @@ fn check_item_fn(&mut self,
             let mut implied_bounds = vec![];
             let free_id_outlive = fcx.tcx.region_maps().call_site_extent(item.id, body_id.node_id);
             this.check_fn_or_method(fcx, item.span, sig, &predicates,
-                                    free_id_outlive, &mut implied_bounds);
+                                    Some(free_id_outlive), &mut implied_bounds);
             implied_bounds
         })
     }
@@ -429,7 +429,7 @@ fn check_fn_or_method<'fcx, 'tcx>(&mut self,
                                       span: Span,
                                       sig: ty::PolyFnSig<'tcx>,
                                       predicates: &ty::InstantiatedPredicates<'tcx>,
-                                      free_id_outlive: CodeExtent,
+                                      free_id_outlive: Option<CodeExtent>,
                                       implied_bounds: &mut Vec<Ty<'tcx>>)
     {
         let free_substs = &fcx.parameter_environment.free_substs;
@@ -453,7 +453,7 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
                                          fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
                                          method_sig: &hir::MethodSig,
                                          method: &ty::AssociatedItem,
-                                         free_id_outlive: CodeExtent,
+                                         free_id_outlive: Option<CodeExtent>,
                                          self_ty: ty::Ty<'tcx>)
     {
         // check that the type of the method's receiver matches the