remove ROOT_CODE_EXTENT and DUMMY_CODE_EXTENT
Instead, thread around `Option<CodeExtent>` where applicable.
This commit is contained in:
parent
119c38ea91
commit
55d6066c05
22 changed files with 137 additions and 158 deletions
|
@ -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(_)) |
|
||||
|
|
|
@ -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)) => {
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
}));
|
||||
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(..) =>
|
||||
|
|
|
@ -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)
|
||||
}))
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue