From: Niko Matsakis Date: Wed, 19 Apr 2017 20:45:07 +0000 (-0400) Subject: remove ROOT_CODE_EXTENT and DUMMY_CODE_EXTENT X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=55d6066c05fea0e0787ac5add67e26283468116c;p=rust.git remove ROOT_CODE_EXTENT and DUMMY_CODE_EXTENT Instead, thread around `Option` where applicable. --- diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index febf6af8763..10712f5ec70 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -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(_)) | diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index 19752f3363a..f9aab59acaf 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -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)) => { diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index f622dfc683b..9701595a9d8 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -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] diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 73c8d1db312..508dfe9cfcd 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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() { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index b398255aede..92777bb1604 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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 })); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 0c35d38d684..e381a904478 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -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 { - 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, + scope_map: Vec>, /// `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, /// the scope that contains any new variables declared - var_parent: CodeExtent, + var_parent: Option, /// region parent of expressions etc - parent: CodeExtent + parent: Option, } 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 { } pub fn intern_code_extent(&mut self, e: CodeExtentData, - parent: CodeExtent) -> CodeExtent { + parent: Option) -> 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 { 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 { //! 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 { return Some(s); } - let scope_map : &[CodeExtent] = &self.scope_map; + let scope_map : &[Option] = &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 { // 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 = 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 = 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] = &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], scope: CodeExtent, buf: &'a mut [CodeExtent; 32], - vec: &'a mut Vec) -> &'a [CodeExtent] { + vec: &'a mut Vec) + -> &'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() }; diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 98b502f5608..ea1a2f9a982 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -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) diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 6c685851e25..d5d17e3c812 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -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); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 969d040e7a6..1cf6c3f334f 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -330,7 +330,7 @@ pub fn replace_late_bound_regions(self, /// Replace any late-bound regions bound in `value` with free variants attached to scope-id /// `scope_id`. pub fn liberate_late_bound_regions(self, - all_outlive_scope: region::CodeExtent, + all_outlive_scope: Option, value: &Binder) -> T where T : TypeFoldable<'tcx> diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 49cc4e7c993..480b8967a79 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -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) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c0b340ad544..fd0b1308c95 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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>, - /// 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, /// A cache for `moves_by_default`. pub is_copy_cache: RefCell, 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) -> &'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) -> 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) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 7857d07ed09..02c4bad8e4e 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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, pub bound_region: BoundRegion, } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 41fab1f3a4f..f5cdd40714c 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -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, diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 2afaaaf0878..f3a258a8ca5 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -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); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index ae63828f0ac..ad51530b191 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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); diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index d8604f65dff..cbd88733e82 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -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); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 9e57472c236..f2a550ec23a 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -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(..) => diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index eb897d10d25..d672637649e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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) })) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index c74d71babc2..5d24df136ff 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -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); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e40d8f6cafc..8b366fd5a27 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 16297709b19..a6f72898a54 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -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) } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 08024c9e9e6..f306d5dd70f 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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, implied_bounds: &mut Vec>) { 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, self_ty: ty::Ty<'tcx>) { // check that the type of the method's receiver matches the