Instead, thread around `Option<CodeExtent>` where applicable.
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};
}
};
- 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(_)) |
// 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)) => {
(&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),
#[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]
// 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() {
// 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
}));
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)]
}
}
-/// 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.
///
}
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()
}
/// 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.
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> {
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,
}
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 {
// 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)
}
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 {
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
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
// 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]",
-> 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;
}
}
- 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]
}
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
}
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),
}
}
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),
};
{
);
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)
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;
}
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;
}
hir::ExprMatch(..) => {
- visitor.cx.var_parent = expr_extent;
+ visitor.cx.var_parent = Some(expr_extent);
}
hir::ExprAssignOp(..) | hir::ExprIndex(..) |
// 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
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);
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 });
// 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);
// 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);
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)
}
// 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);
}
}
}
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);
}
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,
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()
};
};
// 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)
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};
// 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);
/// 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>
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)
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;
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};
/// 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>>,
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)))
}
}
}
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
tcx.construct_parameter_environment(
trait_item.span,
tcx.hir.local_def_id(id),
- extent)
+ Some(extent))
}
}
}
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(..) |
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,
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()
}
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(): \
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()),
/// 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, _| {
pub fn construct_parameter_environment(self,
span: Span,
def_id: DefId,
- free_id_outlive: CodeExtent)
+ free_id_outlive: Option<CodeExtent>)
-> ParameterEnvironment<'gcx>
{
//
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()),
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)
}
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,
}
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,
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;
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);
// 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);
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);
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;
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(..) =>
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)
}))
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);
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);
// 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)
}
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
})
}
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;
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