1
Fork 0

remove ROOT_CODE_EXTENT and DUMMY_CODE_EXTENT

Instead, thread around `Option<CodeExtent>` where applicable.
This commit is contained in:
Niko Matsakis 2017-04-19 16:45:07 -04:00
parent 119c38ea91
commit 55d6066c05
22 changed files with 137 additions and 158 deletions

View file

@ -69,6 +69,7 @@ use traits::{ObligationCause, ObligationCauseCode};
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 @@ impl<'a, 'gcx, '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(_)) |

View file

@ -938,18 +938,19 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
// 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)) => {

View file

@ -138,9 +138,14 @@ impl FreeRegionMap {
(&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 @@ impl FreeRegionMap {
#[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]

View file

@ -1441,7 +1441,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// 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() {

View file

@ -796,7 +796,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// 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
}));

View file

@ -34,7 +34,7 @@ use ty::maps::Providers;
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 @@ impl fmt::Debug for CodeExtent {
}
}
/// 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 @@ impl CodeExtentData {
}
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 @@ impl RegionMaps {
}
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 @@ impl RegionMaps {
// 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 @@ impl RegionMaps {
}
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 @@ impl RegionMaps {
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 @@ impl RegionMaps {
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 @@ impl RegionMaps {
// 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 @@ impl RegionMaps {
-> 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 @@ impl RegionMaps {
}
}
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 @@ impl RegionMaps {
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 @@ impl<'hir, 'a> RegionResolutionVisitor<'hir, 'a> {
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 @@ impl<'hir, 'a> RegionResolutionVisitor<'hir, 'a> {
// 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 @@ impl<'hir, 'a> Visitor<'hir> for RegionResolutionVisitor<'hir, 'a> {
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()
};

View file

@ -206,8 +206,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
};
// 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)

View file

@ -23,7 +23,6 @@ use super::util::impl_trait_ref_and_oblig;
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);

View file

@ -330,7 +330,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// 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>

View file

@ -1268,9 +1268,8 @@ impl<'a, 'gcx, 'tcx> Layout {
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)

View file

@ -23,7 +23,7 @@ use ich::StableHashingContext;
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::rc::Rc;
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 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
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 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
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 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
tcx.construct_parameter_environment(
trait_item.span,
tcx.hir.local_def_id(id),
extent)
Some(extent))
}
}
}
@ -1268,7 +1270,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
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 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
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 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
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 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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)
}

View 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,
}

View file

@ -353,7 +353,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
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,

View 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);

View 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);

View 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);

View 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(..) =>

View file

@ -133,7 +133,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
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)
}))

View file

@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
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);

View 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);

View file

@ -1614,7 +1614,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, '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)
}

View file

@ -343,7 +343,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
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 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
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 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
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