use rustc_data_structures::graph;
use cfg::*;
+use middle::region::CodeExtent;
use ty::{self, TyCtxt};
use syntax::ast;
use syntax::ptr::P;
scope_id: ast::NodeId,
to_index: CFGIndex) {
let mut data = CFGEdgeData { exiting_scopes: vec![] };
- let mut scope = self.tcx.node_extent(from_expr.id);
- let target_scope = self.tcx.node_extent(scope_id);
+ let mut scope = CodeExtent::Misc(from_expr.id);
+ let target_scope = CodeExtent::Misc(scope_id);
let region_maps = self.tcx.region_maps(self.owner_def_id);
while scope != target_scope {
data.exiting_scopes.push(scope.node_id());
}
}
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind<'tcx> {
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
FnPtrAddrCast
});
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtentData
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtent
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
- use middle::region::CodeExtentData;
+ use middle::region::CodeExtent;
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
- CodeExtentData::Misc(node_id) |
- CodeExtentData::DestructionScope(node_id) => {
+ CodeExtent::Misc(node_id) |
+ CodeExtent::DestructionScope(node_id) => {
node_id.hash_stable(hcx, hasher);
}
- CodeExtentData::CallSiteScope(body_id) |
- CodeExtentData::ParameterScope(body_id) => {
+ CodeExtent::CallSiteScope(body_id) |
+ CodeExtent::ParameterScope(body_id) => {
body_id.hash_stable(hcx, hasher);
}
- CodeExtentData::Remainder(block_remainder) => {
+ CodeExtent::Remainder(block_remainder) => {
block_remainder.hash_stable(hcx, hasher);
}
}
return;
}
};
- let scope_decorated_tag = match *scope {
- region::CodeExtentData::Misc(_) => tag,
- region::CodeExtentData::CallSiteScope(_) => {
+ let scope_decorated_tag = match scope {
+ region::CodeExtent::Misc(_) => tag,
+ region::CodeExtent::CallSiteScope(_) => {
"scope of call-site for function"
}
- region::CodeExtentData::ParameterScope(_) => {
+ region::CodeExtent::ParameterScope(_) => {
"scope of function body"
}
- region::CodeExtentData::DestructionScope(_) => {
+ region::CodeExtent::DestructionScope(_) => {
new_string = format!("destruction scope surrounding {}", tag);
&new_string[..]
}
- region::CodeExtentData::Remainder(r) => {
+ region::CodeExtent::Remainder(r) => {
new_string = format!("block suffix following statement {}",
r.first_statement_index);
&new_string[..]
pub fn resolve_regions_and_report_errors(&self,
region_context: DefId,
- region_map: &RegionMaps<'tcx>,
+ region_map: &RegionMaps,
free_regions: &FreeRegionMap<'tcx>) {
let region_rels = RegionRelations::new(self.tcx,
region_context,
graph_name: String,
region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
- node_ids: FxHashMap<Node<'tcx>, usize>,
+ node_ids: FxHashMap<Node, usize>,
}
#[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
-enum Node<'tcx> {
+enum Node {
RegionVid(ty::RegionVid),
- Region(ty::RegionKind<'tcx>),
+ Region(ty::RegionKind),
}
// type Edge = Constraint;
#[derive(Clone, PartialEq, Eq, Debug, Copy)]
enum Edge<'tcx> {
Constraint(Constraint<'tcx>),
- EnclScope(CodeExtent<'tcx>, CodeExtent<'tcx>),
+ EnclScope(CodeExtent, CodeExtent),
}
impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
}
impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
- type Node = Node<'tcx>;
+ type Node = Node;
type Edge = Edge<'tcx>;
fn graph_id(&self) -> dot::Id {
dot::Id::new(&*self.graph_name).unwrap()
}
}
-fn constraint_to_nodes<'tcx>(c: &Constraint<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
+fn constraint_to_nodes(c: &Constraint) -> (Node, Node) {
match *c {
Constraint::ConstrainVarSubVar(rv_1, rv_2) =>
(Node::RegionVid(rv_1), Node::RegionVid(rv_2)),
}
}
-fn edge_to_nodes<'tcx>(e: &Edge<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
+fn edge_to_nodes(e: &Edge) -> (Node, Node) {
match *e {
Edge::Constraint(ref c) => constraint_to_nodes(c),
Edge::EnclScope(sub, sup) => {
}
impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
- type Node = Node<'tcx>;
+ type Node = Node;
type Edge = Edge<'tcx>;
- fn nodes(&self) -> dot::Nodes<Node<'tcx>> {
+ fn nodes(&self) -> dot::Nodes<Node> {
let mut set = FxHashSet();
for node in self.node_ids.keys() {
set.insert(*node);
debug!("region graph has {} edges", v.len());
Cow::Owned(v)
}
- fn source(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
+ fn source(&self, edge: &Edge<'tcx>) -> Node {
let (n1, _) = edge_to_nodes(edge);
debug!("edge {:?} has source {:?}", edge, n1);
n1
}
- fn target(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
+ fn target(&self, edge: &Edge<'tcx>) -> Node {
let (_, n2) = edge_to_nodes(edge);
debug!("edge {:?} has target {:?}", edge, n2);
n2
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
-> Self
{
pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
options: mc::MemCategorizationOptions)
-> Self
{
pub context: DefId,
/// region maps for the given context
- pub region_maps: &'a RegionMaps<'tcx>,
+ pub region_maps: &'a RegionMaps,
/// free-region relationships
pub free_regions: &'a FreeRegionMap<'tcx>,
pub fn new(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
context: DefId,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
free_regions: &'a FreeRegionMap<'tcx>,
) -> Self {
Self {
#[derive(Clone)]
pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- pub region_maps: &'a RegionMaps<'tcx>,
+ pub region_maps: &'a RegionMaps,
options: MemCategorizationOptions,
}
impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
/// Context should be the `DefId` we use to fetch region-maps.
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps<'tcx>)
+ region_maps: &'a RegionMaps)
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
MemCategorizationContext::with_options(infcx,
region_maps,
}
pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
options: MemCategorizationOptions)
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
MemCategorizationContext {
pub fn temporary_scope(&self, id: ast::NodeId) -> (ty::Region<'tcx>, ty::Region<'tcx>)
{
let (scope, old_scope) =
- self.region_maps.old_and_new_temporary_scope(self.tcx(), id);
+ self.region_maps.old_and_new_temporary_scope(id);
(self.tcx().mk_region(match scope {
Some(scope) => ty::ReScope(scope),
None => ty::ReStatic
use std::mem;
use std::rc::Rc;
-use serialize;
use syntax::codemap;
use syntax::ast;
use syntax_pos::Span;
use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
use mir::transform::MirSource;
-pub type CodeExtent<'tcx> = &'tcx CodeExtentData;
-
-impl<'tcx> serialize::UseSpecializedEncodable for CodeExtent<'tcx> {}
-impl<'tcx> serialize::UseSpecializedDecodable for CodeExtent<'tcx> {}
-
/// CodeExtent represents a statically-describable extent that can be
/// used to bound the lifetime/region for values.
///
/// actually attach a more meaningful ordering to scopes than the one
/// generated via deriving here.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
-pub enum CodeExtentData {
+pub enum CodeExtent {
Misc(ast::NodeId),
// extent of the call-site for a function or closure (outlives
/// * the subscope with `first_statement_index == 0` is scope of both
/// `a` and `b`; it does not include EXPR_1, but does include
/// everything after that first `let`. (If you want a scope that
-/// includes EXPR_1 as well, then do not use `CodeExtentData::Remainder`,
+/// includes EXPR_1 as well, then do not use `CodeExtent::Remainder`,
/// but instead another `CodeExtent` that encompasses the whole block,
-/// e.g. `CodeExtentData::Misc`.
+/// e.g. `CodeExtent::Misc`.
///
/// * the subscope with `first_statement_index == 1` is scope of `c`,
/// and thus does not include EXPR_2, but covers the `...`.
pub first_statement_index: u32,
}
-impl CodeExtentData {
+impl CodeExtent {
/// Returns a node id associated with this scope.
///
/// NB: likely to be replaced as API is refined; e.g. pnkfelix
/// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
pub fn node_id(&self) -> ast::NodeId {
match *self {
- CodeExtentData::Misc(node_id) => node_id,
+ CodeExtent::Misc(node_id) => node_id,
// These cases all return rough approximations to the
// precise extent denoted by `self`.
- CodeExtentData::Remainder(br) => br.block,
- CodeExtentData::DestructionScope(node_id) => node_id,
- CodeExtentData::CallSiteScope(body_id) |
- CodeExtentData::ParameterScope(body_id) => body_id.node_id,
+ CodeExtent::Remainder(br) => br.block,
+ CodeExtent::DestructionScope(node_id) => node_id,
+ CodeExtent::CallSiteScope(body_id) |
+ CodeExtent::ParameterScope(body_id) => body_id.node_id,
}
}
match hir_map.find(self.node_id()) {
Some(hir_map::NodeBlock(ref blk)) => {
match *self {
- CodeExtentData::CallSiteScope(_) |
- CodeExtentData::ParameterScope(_) |
- CodeExtentData::Misc(_) |
- CodeExtentData::DestructionScope(_) => Some(blk.span),
+ CodeExtent::CallSiteScope(_) |
+ CodeExtent::ParameterScope(_) |
+ CodeExtent::Misc(_) |
+ CodeExtent::DestructionScope(_) => Some(blk.span),
- CodeExtentData::Remainder(r) => {
+ CodeExtent::Remainder(r) => {
assert_eq!(r.block, blk.id);
// Want span for extent starting after the
// indexed statement and ending at end of
}
/// The region maps encode information about region relationships.
-pub struct RegionMaps<'tcx> {
+pub struct RegionMaps {
/// If not empty, this body is the root of this region hierarchy.
root_body: Option<hir::BodyId>,
/// conditional expression or repeating block. (Note that the
/// enclosing scope id for the block associated with a closure is
/// the closure itself.)
- scope_map: FxHashMap<CodeExtent<'tcx>, CodeExtent<'tcx>>,
+ scope_map: FxHashMap<CodeExtent, CodeExtent>,
/// `var_map` maps from a variable or binding id to the block in
/// which that variable is declared.
- var_map: NodeMap<CodeExtent<'tcx>>,
+ var_map: NodeMap<CodeExtent>,
/// maps from a node-id to the associated destruction scope (if any)
- destruction_scopes: NodeMap<CodeExtent<'tcx>>,
+ destruction_scopes: NodeMap<CodeExtent>,
/// `rvalue_scopes` includes entries for those expressions whose cleanup scope is
/// larger than the default. The map goes from the expression id
/// table, the appropriate cleanup scope is the innermost
/// enclosing statement, conditional expression, or repeating
/// block (see `terminating_scopes`).
- rvalue_scopes: NodeMap<CodeExtent<'tcx>>,
+ rvalue_scopes: NodeMap<CodeExtent>,
/// Records the value of rvalue scopes before they were shrunk by
/// #36082, for error reporting.
///
/// FIXME: this should be temporary. Remove this by 1.18.0 or
/// so.
- shrunk_rvalue_scopes: NodeMap<CodeExtent<'tcx>>,
+ shrunk_rvalue_scopes: NodeMap<CodeExtent>,
/// Encodes the hierarchy of fn bodies. Every fn body (including
/// closures) forms its own distinct region hierarchy, rooted in
}
#[derive(Debug, Copy, Clone)]
-pub struct Context<'tcx> {
+pub struct Context {
/// the root of the current region tree. This is typically the id
/// of the innermost fn body. Each fn forms its own disjoint tree
/// in the region hierarchy. These fn bodies are themselves
root_id: Option<ast::NodeId>,
/// the scope that contains any new variables declared
- var_parent: Option<CodeExtent<'tcx>>,
+ var_parent: Option<CodeExtent>,
/// region parent of expressions etc
- parent: Option<CodeExtent<'tcx>>,
+ parent: Option<CodeExtent>,
}
struct RegionResolutionVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Generated maps:
- region_maps: &'a mut RegionMaps<'tcx>,
+ region_maps: &'a mut RegionMaps,
- cx: Context<'tcx>,
+ cx: Context,
map: &'a hir_map::Map<'tcx>,
}
-impl<'tcx> RegionMaps<'tcx> {
+impl<'tcx> RegionMaps {
pub fn new() -> Self {
RegionMaps {
root_body: None,
}
pub fn record_code_extent(&mut self,
- child: CodeExtent<'tcx>,
- parent: Option<CodeExtent<'tcx>>) {
+ child: CodeExtent,
+ parent: Option<CodeExtent>) {
debug!("{:?}.parent = {:?}", child, parent);
if let Some(p) = parent {
}
// record the destruction scopes for later so we can query them
- if let &CodeExtentData::DestructionScope(n) = child {
+ if let CodeExtent::DestructionScope(n) = child {
self.destruction_scopes.insert(n, child);
}
}
- pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(CodeExtent<'tcx>, CodeExtent<'tcx>) {
+ pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(CodeExtent, CodeExtent) {
for (&child, &parent) in &self.scope_map {
e(child, parent)
}
}
- pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent<'tcx>) {
- for (child, parent) in self.var_map.iter() {
+ pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent) {
+ for (child, &parent) in self.var_map.iter() {
e(child, parent)
}
}
- pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent<'tcx>> {
+ pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent> {
self.destruction_scopes.get(&n).cloned()
}
}
}
- fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+ fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id());
self.var_map.insert(var, lifetime);
}
- fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+ fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id());
self.rvalue_scopes.insert(var, lifetime);
}
- fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+ fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id());
self.shrunk_rvalue_scopes.insert(var, lifetime);
}
- pub fn opt_encl_scope(&self, id: CodeExtent<'tcx>) -> Option<CodeExtent<'tcx>> {
+ pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
//! Returns the narrowest scope that encloses `id`, if any.
self.scope_map.get(&id).cloned()
}
#[allow(dead_code)] // used in cfg
- pub fn encl_scope(&self, id: CodeExtent<'tcx>) -> CodeExtent<'tcx> {
+ pub fn encl_scope(&self, id: CodeExtent) -> CodeExtent {
//! Returns the narrowest scope that encloses `id`, if any.
self.opt_encl_scope(id).unwrap()
}
/// Returns the lifetime of the local variable `var_id`
- pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent<'tcx> {
+ pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent {
match self.var_map.get(&var_id) {
Some(&r) => r,
None => { bug!("no enclosing scope for id {:?}", var_id); }
}
}
- pub fn temporary_scope2<'a, 'gcx: 'tcx>(&self,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- expr_id: ast::NodeId)
- -> (Option<CodeExtent<'tcx>>, bool) {
- let temporary_scope = self.temporary_scope(tcx, expr_id);
+ pub fn temporary_scope2(&self, expr_id: ast::NodeId)
+ -> (Option<CodeExtent>, bool) {
+ let temporary_scope = self.temporary_scope(expr_id);
let was_shrunk = match self.shrunk_rvalue_scopes.get(&expr_id) {
Some(&s) => {
info!("temporary_scope2({:?}, scope={:?}, shrunk={:?})",
(temporary_scope, was_shrunk)
}
- pub fn old_and_new_temporary_scope<'a, 'gcx: 'tcx>(&self,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- expr_id: ast::NodeId)
- -> (Option<CodeExtent<'tcx>>,
- Option<CodeExtent<'tcx>>)
+ pub fn old_and_new_temporary_scope(&self, expr_id: ast::NodeId)
+ -> (Option<CodeExtent>,
+ Option<CodeExtent>)
{
- let temporary_scope = self.temporary_scope(tcx, expr_id);
+ let temporary_scope = self.temporary_scope(expr_id);
(temporary_scope,
self.shrunk_rvalue_scopes
.get(&expr_id).cloned()
.or(temporary_scope))
}
- pub fn temporary_scope<'a, 'gcx: 'tcx>(&self,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- expr_id: ast::NodeId)
- -> Option<CodeExtent<'tcx>> {
+ pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<CodeExtent> {
//! Returns the scope when temp created by expr_id will be cleaned up
// check for a designated rvalue scope
// if there's one. Static items, for instance, won't
// have an enclosing scope, hence no scope will be
// returned.
- let mut id = tcx.node_extent(expr_id);
+ let mut id = CodeExtent::Misc(expr_id);
- while let Some(&p) = self.scope_map.get(id) {
- match *p {
- CodeExtentData::DestructionScope(..) => {
+ while let Some(&p) = self.scope_map.get(&id) {
+ match p {
+ CodeExtent::DestructionScope(..) => {
debug!("temporary_scope({:?}) = {:?} [enclosing]",
expr_id, id);
return Some(id);
return None;
}
- pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind<'tcx> {
+ pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind {
//! Returns the lifetime of the variable `id`.
let scope = ty::ReScope(self.var_scope(id));
/// Finds the nearest common ancestor (if any) of two scopes. That is, finds the smallest
/// scope which is greater than or equal to both `scope_a` and `scope_b`.
pub fn nearest_common_ancestor(&self,
- scope_a: CodeExtent<'tcx>,
- scope_b: CodeExtent<'tcx>)
- -> CodeExtent<'tcx> {
+ scope_a: CodeExtent,
+ scope_b: CodeExtent)
+ -> CodeExtent {
if scope_a == scope_b { return scope_a; }
/// [1] The initial values for `a_buf` and `b_buf` are not used.
/// 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<'tcx>> = vec![];
+ let mut a_vec: Vec<CodeExtent> = vec![];
let mut b_buf: [CodeExtent; 32] = [scope_b /* [1] */; 32];
- let mut b_vec: Vec<CodeExtent<'tcx>> = vec![];
+ let mut b_vec: Vec<CodeExtent> = vec![];
let scope_map = &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 a_root_scope = a_ancestors[a_index];
let b_root_scope = a_ancestors[a_index];
return match (a_root_scope, b_root_scope) {
- (&CodeExtentData::DestructionScope(a_root_id),
- &CodeExtentData::DestructionScope(b_root_id)) => {
+ (CodeExtent::DestructionScope(a_root_id),
+ CodeExtent::DestructionScope(b_root_id)) => {
if self.fn_is_enclosed_by(a_root_id, b_root_id) {
// `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
scope_b
}
}
- fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent<'tcx>, CodeExtent<'tcx>>,
- scope: CodeExtent<'tcx>,
- buf: &'a mut [CodeExtent<'tcx>; 32],
- vec: &'a mut Vec<CodeExtent<'tcx>>)
- -> &'a [CodeExtent<'tcx>] {
+ fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent, CodeExtent>,
+ scope: CodeExtent,
+ buf: &'a mut [CodeExtent; 32],
+ vec: &'a mut Vec<CodeExtent>)
+ -> &'a [CodeExtent] {
// debug!("ancestors_of(scope={:?})", scope);
let mut scope = scope;
while i < 32 {
buf[i] = scope;
match scope_map.get(&scope) {
- Some(superscope) => scope = superscope,
+ Some(&superscope) => scope = superscope,
_ => return &buf[..i+1]
}
i += 1;
loop {
vec.push(scope);
match scope_map.get(&scope) {
- Some(superscope) => scope = superscope,
+ Some(&superscope) => scope = superscope,
_ => return &*vec
}
}
/// returns the outermost `CodeExtent` that the region outlives.
pub fn early_free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
br: &ty::EarlyBoundRegion)
- -> CodeExtent<'tcx> {
+ -> CodeExtent {
let param_owner = tcx.parent_def_id(br.def_id).unwrap();
let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
self.root_body.unwrap()
});
- tcx.intern_code_extent(CodeExtentData::CallSiteScope(body_id))
+ CodeExtent::CallSiteScope(body_id)
}
/// Assuming that the provided region was defined within this `RegionMaps`,
/// returns the outermost `CodeExtent` that the region outlives.
pub fn free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeRegion)
- -> CodeExtent<'tcx> {
+ -> CodeExtent {
let param_owner = match fr.bound_region {
ty::BoundRegion::BrNamed(def_id, _) => {
tcx.parent_def_id(def_id).unwrap()
assert_eq!(param_owner, fr.scope);
let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
- let body_id = tcx.hir.body_owned_by(param_owner_id);
-
- tcx.intern_code_extent(CodeExtentData::CallSiteScope(body_id))
+ CodeExtent::CallSiteScope(tcx.hir.body_owned_by(param_owner_id))
}
}
debug!("resolve_block(blk.id={:?})", blk.id);
let prev_cx = visitor.cx;
- let block_extent = visitor.new_node_extent_with_dtor(blk.id);
// We treat the tail expression in the block (if any) somewhat
// differently from the statements. The issue has to do with
// `other_argument()` has run and also the call to `quux(..)`
// itself has returned.
- visitor.cx = Context {
- root_id: prev_cx.root_id,
- var_parent: Some(block_extent),
- parent: Some(block_extent),
- };
+ visitor.enter_node_extent_with_dtor(blk.id);
+ visitor.cx.var_parent = visitor.cx.parent;
{
// This block should be kept approximately in sync with
// has the previous subscope in the block as a parent,
// except for the first such subscope, which has the
// block itself as a parent.
- let stmt_extent = visitor.new_code_extent(
- CodeExtentData::Remainder(BlockRemainder {
+ visitor.enter_code_extent(
+ CodeExtent::Remainder(BlockRemainder {
block: blk.id,
first_statement_index: i as u32
})
);
- visitor.cx = Context {
- root_id: prev_cx.root_id,
- var_parent: Some(stmt_extent),
- parent: Some(stmt_extent),
- };
+ visitor.cx.var_parent = visitor.cx.parent;
}
visitor.visit_stmt(statement)
}
}
fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) {
- visitor.new_node_extent(pat.id);
+ visitor.record_code_extent(CodeExtent::Misc(pat.id));
// If this is a binding then record the lifetime of that binding.
if let PatKind::Binding(..) = pat.node {
// statement plus its destructors, and thus the extent for which
// regions referenced by the destructors need to survive.
visitor.terminating_scopes.insert(stmt_id);
- let stmt_extent = visitor.new_node_extent_with_dtor(stmt_id);
let prev_parent = visitor.cx.parent;
- visitor.cx.parent = Some(stmt_extent);
+ visitor.enter_node_extent_with_dtor(stmt_id);
+
intravisit::walk_stmt(visitor, stmt);
+
visitor.cx.parent = prev_parent;
}
fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &'tcx hir::Expr) {
debug!("resolve_expr(expr.id={:?})", expr.id);
- let expr_extent = visitor.new_node_extent_with_dtor(expr.id);
let prev_cx = visitor.cx;
- visitor.cx.parent = Some(expr_extent);
+ visitor.enter_node_extent_with_dtor(expr.id);
{
let terminating_scopes = &mut visitor.terminating_scopes;
}
hir::ExprMatch(..) => {
- visitor.cx.var_parent = Some(expr_extent);
+ visitor.cx.var_parent = visitor.cx.parent;
}
hir::ExprAssignOp(..) | hir::ExprIndex(..) |
fn record_rvalue_scope_if_borrow_expr<'a, 'tcx>(
visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
expr: &hir::Expr,
- blk_id: CodeExtent<'tcx>)
+ blk_id: CodeExtent)
{
match expr.node {
hir::ExprAddrOf(_, ref subexpr) => {
/// Note: ET is intended to match "rvalues or lvalues based on rvalues".
fn record_rvalue_scope<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
expr: &hir::Expr,
- blk_scope: CodeExtent<'tcx>,
+ blk_scope: CodeExtent,
is_shrunk: bool) {
let mut expr = expr;
loop {
}
impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> {
- pub fn intern_code_extent(&mut self,
- data: CodeExtentData,
- parent: Option<CodeExtent<'tcx>>)
- -> CodeExtent<'tcx> {
- let code_extent = self.tcx.intern_code_extent(data);
- self.region_maps.record_code_extent(code_extent, parent);
- code_extent
- }
-
- pub fn intern_node(&mut self,
- n: ast::NodeId,
- parent: Option<CodeExtent<'tcx>>) -> CodeExtent<'tcx> {
- self.intern_code_extent(CodeExtentData::Misc(n), parent)
- }
-
/// Records the current parent (if any) as the parent of `child_scope`.
- fn new_code_extent(&mut self, child_scope: CodeExtentData) -> CodeExtent<'tcx> {
+ fn record_code_extent(&mut self, child_scope: CodeExtent) {
let parent = self.cx.parent;
- self.intern_code_extent(child_scope, parent)
+ self.region_maps.record_code_extent(child_scope, parent);
}
- fn new_node_extent(&mut self, child_scope: ast::NodeId) -> CodeExtent<'tcx> {
- self.new_code_extent(CodeExtentData::Misc(child_scope))
+ /// Records the current parent (if any) as the parent of `child_scope`,
+ /// and sets `child_scope` as the new current parent.
+ fn enter_code_extent(&mut self, child_scope: CodeExtent) {
+ self.record_code_extent(child_scope);
+ self.cx.parent = Some(child_scope);
}
- fn new_node_extent_with_dtor(&mut self, id: ast::NodeId) -> CodeExtent<'tcx> {
+ fn enter_node_extent_with_dtor(&mut self, id: ast::NodeId) {
// If node was previously marked as a terminating scope during the
// recursive visit of its parent node in the AST, then we need to
// account for the destruction scope representing the extent of
// the destructors that run immediately after it completes.
if self.terminating_scopes.contains(&id) {
- let ds = self.new_code_extent(
- CodeExtentData::DestructionScope(id));
- self.intern_node(id, Some(ds))
- } else {
- self.new_node_extent(id)
+ self.enter_code_extent(CodeExtent::DestructionScope(id));
}
+ self.enter_code_extent(CodeExtent::Misc(id));
}
}
}
self.cx.root_id = Some(body_id.node_id);
- self.cx.parent = Some(self.new_code_extent(
- CodeExtentData::CallSiteScope(body_id)));
- self.cx.parent = Some(self.new_code_extent(
- CodeExtentData::ParameterScope(body_id)));
+ self.enter_code_extent(CodeExtent::CallSiteScope(body_id));
+ self.enter_code_extent(CodeExtent::ParameterScope(body_id));
// The arguments and `self` are parented to the fn.
self.cx.var_parent = self.cx.parent.take();
}
fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
- -> Rc<RegionMaps<'tcx>>
+ -> Rc<RegionMaps>
{
let closure_base_def_id = tcx.closure_base_def_id(def_id);
if closure_base_def_id != def_id {
use hir::map::DisambiguatedDefPathData;
use middle::free_region::FreeRegionMap;
use middle::lang_items;
-use middle::region::{CodeExtent, CodeExtentData};
use middle::resolve_lifetime;
use middle::stability;
use mir::Mir;
type_: RefCell<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
type_list: RefCell<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
- region: RefCell<FxHashSet<Interned<'tcx, RegionKind<'tcx>>>>,
+ region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
}
layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
- code_extent_interner: RefCell<FxHashSet<CodeExtent<'tcx>>>,
-
/// A vector of every trait accessible in the whole crate
/// (i.e. including those from subcrates). This is used only for
/// error reporting, and so is lazily initialised and generally
interned
}
- pub fn node_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> {
- self.intern_code_extent(CodeExtentData::Misc(n))
- }
-
- pub fn call_site_extent(self, fn_id: ast::NodeId) -> CodeExtent<'gcx> {
- self.intern_code_extent(CodeExtentData::CallSiteScope(
- self.hir.body_owned_by(fn_id)))
- }
-
- pub fn parameter_extent(self, fn_id: ast::NodeId) -> CodeExtent<'gcx> {
- self.intern_code_extent(CodeExtentData::ParameterScope(
- self.hir.body_owned_by(fn_id)))
- }
-
- pub fn intern_code_extent(self, data: CodeExtentData) -> CodeExtent<'gcx> {
- if let Some(st) = self.code_extent_interner.borrow().get(&data) {
- return st;
- }
-
- let interned = self.global_interners.arena.alloc(data);
- if let Some(prev) = self.code_extent_interner.borrow_mut().replace(interned) {
- bug!("Tried to overwrite interned code-extent: {:?}", prev)
- }
- interned
- }
-
pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
if let Some(layout) = self.layout_interner.borrow().get(&layout) {
return layout;
data_layout: data_layout,
layout_cache: RefCell::new(FxHashMap()),
layout_interner: RefCell::new(FxHashSet()),
- code_extent_interner: RefCell::new(FxHashSet()),
layout_depth: Cell::new(0),
derive_macros: RefCell::new(NodeMap()),
stability_interner: RefCell::new(FxHashSet()),
}
}
-impl<'tcx> Borrow<RegionKind<'tcx>> for Interned<'tcx, RegionKind<'tcx>> {
- fn borrow<'a>(&'a self) -> &'a RegionKind<'tcx> {
+impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
+ fn borrow<'a>(&'a self) -> &'a RegionKind {
&self.0
}
}
&ty::ReVar(_) | &ty::ReSkolemized(..) => true,
_ => false
}
- }) -> RegionKind<'tcx>
+ }) -> RegionKind
);
macro_rules! slice_interners {
// regions. See comment on `shift_regions_through_binders` method in
// `subst.rs` for more details.
-pub fn shift_region<'tcx>(region: ty::RegionKind<'tcx>, amount: u32) -> ty::RegionKind<'tcx> {
+pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
match region {
ty::ReLateBound(debruijn, br) => {
ty::ReLateBound(debruijn.shifted(amount), br)
/// Per-function `RegionMaps`. The `DefId` should be the owner-def-id for the fn body;
/// in the case of closures or "inline" expressions, this will be redirected to the enclosing
/// fn item.
- [] region_maps: RegionMaps(DefId) -> Rc<RegionMaps<'tcx>>,
+ [] region_maps: RegionMaps(DefId) -> Rc<RegionMaps>,
[] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx>,
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::privacy::AccessLevels;
use middle::resolve_lifetime::ObjectLifetimeDefault;
+use middle::region::CodeExtent;
use mir::Mir;
use traits;
use ty;
}
pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> {
- self.mk_region(ty::ReScope(self.node_extent(id)))
+ self.mk_region(ty::ReScope(CodeExtent::Misc(id)))
}
/// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
pub depth: u32,
}
-pub type Region<'tcx> = &'tcx RegionKind<'tcx>;
+pub type Region<'tcx> = &'tcx RegionKind;
/// Representation of regions.
///
/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)]
-pub enum RegionKind<'tcx> {
+pub enum RegionKind {
// Region bound in a type or fn declaration which will be
// substituted 'early' -- that is, at the same time when type
// parameters are substituted.
/// A concrete region naming some statically determined extent
/// (e.g. an expression or sequence of statements) within the
/// current function.
- ReScope(region::CodeExtent<'tcx>),
+ ReScope(region::CodeExtent),
/// Static data that has an "infinite" lifetime. Top in the region lattice.
ReStatic,
}
/// Region utilities
-impl<'tcx> RegionKind<'tcx> {
+impl RegionKind {
pub fn is_late_bound(&self) -> bool {
match *self {
ty::ReLateBound(..) => true,
}
/// Returns the depth of `self` from the (1-based) binding level `depth`
- pub fn from_depth(&self, depth: u32) -> RegionKind<'tcx> {
+ pub fn from_depth(&self, depth: u32) -> RegionKind {
match *self {
ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex {
depth: debruijn.depth - (depth - 1)
}
}
-impl<'tcx> fmt::Debug for ty::RegionKind<'tcx> {
+impl fmt::Debug for ty::RegionKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ty::ReEarlyBound(ref data) => {
}
}
-impl<'tcx> fmt::Display for ty::RegionKind<'tcx> {
+impl<'tcx> fmt::Display for ty::RegionKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if verbose() {
return write!(f, "{:?}", *self);
})
}
- pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent<'tcx>, mut op: F) -> bool where
+ pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent, mut op: F) -> bool where
F: FnMut(&Loan<'tcx>) -> bool,
{
//! Like `each_issued_loan()`, but only considers loans that are
}
fn each_in_scope_loan_affecting_path<F>(&self,
- scope: region::CodeExtent<'tcx>,
+ scope: region::CodeExtent,
loan_path: &LoanPath<'tcx>,
mut op: F)
-> bool where
let mut ret = UseOk;
self.each_in_scope_loan_affecting_path(
- self.tcx().node_extent(expr_id), use_path, |loan| {
+ region::CodeExtent::Misc(expr_id), use_path, |loan| {
if !compatible_borrow_kinds(loan.kind, borrow_kind) {
ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
false
// Check that we don't invalidate any outstanding loans
if let Some(loan_path) = opt_loan_path(&assignee_cmt) {
- let scope = self.tcx().node_extent(assignment_id);
+ let scope = region::CodeExtent::Misc(assignment_id);
self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| {
self.report_illegal_mutation(assignment_span, &loan_path, loan);
false
type R = Result<(),()>;
pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
- item_scope: region::CodeExtent<'tcx>,
+ item_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
cmt: mc::cmt<'tcx>,
bccx: &'a BorrowckCtxt<'a, 'tcx>,
// the scope of the function body for the enclosing item
- item_scope: region::CodeExtent<'tcx>,
+ item_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
bccx: bccx,
infcx: &infcx,
all_loans: Vec::new(),
- item_ub: bccx.tcx.node_extent(body.node_id),
+ item_ub: region::CodeExtent::Misc(body.node_id),
move_data: MoveData::new(),
move_error_collector: move_error::MoveErrorCollector::new(),
};
all_loans: Vec<Loan<'tcx>>,
/// `item_ub` is used as an upper-bound on the lifetime whenever we
/// ask for the scope of an expression categorized as an upvar.
- item_ub: region::CodeExtent<'tcx>,
+ item_ub: region::CodeExtent,
}
impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
};
debug!("loan_scope = {:?}", loan_scope);
- let borrow_scope = self.tcx().node_extent(borrow_id);
+ let borrow_scope = region::CodeExtent::Misc(borrow_id);
let gen_scope = self.compute_gen_scope(borrow_scope, loan_scope);
debug!("gen_scope = {:?}", gen_scope);
}
pub fn compute_gen_scope(&self,
- borrow_scope: region::CodeExtent<'tcx>,
- loan_scope: region::CodeExtent<'tcx>)
- -> region::CodeExtent<'tcx> {
+ borrow_scope: region::CodeExtent,
+ loan_scope: region::CodeExtent)
+ -> region::CodeExtent {
//! Determine when to introduce the loan. Typically the loan
//! is introduced at the point of the borrow, but in some cases,
//! notably method arguments, the loan may be introduced only
}
}
- pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent<'tcx>, lp: &LoanPath<'tcx>)
- -> region::CodeExtent<'tcx> {
+ pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent, lp: &LoanPath<'tcx>)
+ -> region::CodeExtent {
//! Determine when the loan restrictions go out of scope.
//! This is either when the lifetime expires or when the
//! local variable which roots the loan-path goes out of scope,
// Some in `borrowck_fn` and cleared later
tables: &'a ty::TypeckTables<'tcx>,
- region_maps: Rc<RegionMaps<'tcx>>,
+ region_maps: Rc<RegionMaps>,
owner_def_id: DefId,
}
/// cases, notably method arguments, the loan may be introduced
/// only later, once it comes into scope. See also
/// `GatherLoanCtxt::compute_gen_scope`.
- gen_scope: region::CodeExtent<'tcx>,
+ gen_scope: region::CodeExtent,
/// kill_scope indicates when the loan goes out of scope. This is
/// either when the lifetime expires or when the local variable
/// which roots the loan-path goes out of scope, whichever happens
/// faster. See also `GatherLoanCtxt::compute_kill_scope`.
- kill_scope: region::CodeExtent<'tcx>,
+ kill_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
}
}
impl<'a, 'tcx> LoanPath<'tcx> {
- pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent<'tcx> {
+ pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent {
match self.kind {
LpVar(local_id) => bccx.region_maps.var_scope(local_id),
LpUpvar(upvar_id) => {
let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx);
- bccx.tcx.node_extent(block_id)
+ region::CodeExtent::Misc(block_id)
}
LpDowncast(ref base, _) |
LpExtend(ref base, ..) => base.kill_scope(bccx),
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
param_env: &'a ty::ParameterEnvironment<'tcx>,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
}
impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
use rustc::middle::lang_items;
use rustc::middle::free_region::FreeRegionMap;
use rustc::middle::region::{CodeExtent, RegionMaps};
-use rustc::middle::region::CodeExtentData;
use rustc::middle::resolve_lifetime;
use rustc::middle::stability;
use rustc::ty::subst::{Kind, Subst};
struct Env<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
infcx: &'a infer::InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a mut RegionMaps<'tcx>,
+ region_maps: &'a mut RegionMaps,
}
struct RH<'a> {
self.infcx.tcx
}
- pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent<'tcx>) {
- let me = self.tcx().intern_code_extent(CodeExtentData::Misc(rh.id));
+ pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent) {
+ let me = CodeExtent::Misc(rh.id);
self.region_maps.record_code_extent(me, Some(parent));
for child_rh in rh.sub {
self.create_region_hierarchy(child_rh, me);
// children of 1, etc
let node = ast::NodeId::from_u32;
- let dscope = self.tcx().intern_code_extent(CodeExtentData::DestructionScope(node(1)));
+ let dscope = CodeExtent::DestructionScope(node(1));
self.region_maps.record_code_extent(dscope, None);
self.create_region_hierarchy(&RH {
id: node(1),
}
pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> {
- let r = ty::ReScope(self.tcx().node_extent(ast::NodeId::from_u32(id)));
+ let r = ty::ReScope(CodeExtent::Misc(ast::NodeId::from_u32(id)));
self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize)
}
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::middle::lang_items;
-use rustc::middle::region;
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::Substs;
}
}
-impl<'a, 'tcx> SpecializedDecoder<region::CodeExtent<'tcx>> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<region::CodeExtent<'tcx>, Self::Error> {
- Ok(self.tcx().intern_code_extent(Decodable::decode(self)?))
- }
-}
-
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<Ty<'tcx>>> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<Ty<'tcx>>, Self::Error> {
Ok(self.tcx().mk_type_list((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
/// The operand is known to be live until the end of `scope`.
pub fn as_operand<M>(&mut self,
block: BasicBlock,
- scope: Option<CodeExtent<'tcx>>,
+ scope: Option<CodeExtent>,
expr: M) -> BlockAnd<Operand<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
fn expr_as_operand(&mut self,
mut block: BasicBlock,
- scope: Option<CodeExtent<'tcx>>,
+ scope: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Operand<'tcx>> {
debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
}
/// Compile `expr`, yielding an rvalue.
- pub fn as_rvalue<M>(&mut self, block: BasicBlock, scope: Option<CodeExtent<'tcx>>, expr: M)
+ pub fn as_rvalue<M>(&mut self, block: BasicBlock, scope: Option<CodeExtent>, expr: M)
-> BlockAnd<Rvalue<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
fn expr_as_rvalue(&mut self,
mut block: BasicBlock,
- scope: Option<CodeExtent<'tcx>>,
+ scope: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Rvalue<'tcx>> {
debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
/// up rvalues so as to freeze the value that will be consumed.
pub fn as_temp<M>(&mut self,
block: BasicBlock,
- temp_lifetime: Option<CodeExtent<'tcx>>,
+ temp_lifetime: Option<CodeExtent>,
expr: M)
-> BlockAnd<Lvalue<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
fn expr_as_temp(&mut self,
mut block: BasicBlock,
- temp_lifetime: Option<CodeExtent<'tcx>>,
+ temp_lifetime: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Lvalue<'tcx>> {
debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
let span = tcx.hir.span(fn_id);
let mut builder = Builder::new(hir.clone(), span, arguments.len(), return_ty);
- let call_site_extent = tcx.call_site_extent(fn_id);
- let arg_extent = tcx.parameter_extent(fn_id);
+ let call_site_extent = CodeExtent::CallSiteScope(body.id());
+ let arg_extent = CodeExtent::ParameterScope(body.id());
let mut block = START_BLOCK;
unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
unpack!(block = builder.in_scope(arg_extent, block, |builder| {
fn args_and_body(&mut self,
mut block: BasicBlock,
arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
- argument_extent: CodeExtent<'tcx>,
+ argument_extent: CodeExtent,
ast_body: &'gcx hir::Expr)
-> BlockAnd<()>
{
*/
use build::{BlockAnd, BlockAndExtension, Builder, CFG};
-use rustc::middle::region::{CodeExtent, CodeExtentData};
+use rustc::middle::region::CodeExtent;
use rustc::middle::lang_items;
use rustc::middle::const_val::ConstVal;
use rustc::ty::subst::{Kind, Subst};
visibility_scope: VisibilityScope,
/// the extent of this scope within source code.
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
/// Whether there's anything to do for the cleanup path, that is,
/// when unwinding through this scope. This includes destructors,
free: Option<FreeData<'tcx>>,
/// The cache for drop chain on “normal” exit into a particular BasicBlock.
- cached_exits: FxHashMap<(BasicBlock, CodeExtent<'tcx>), BasicBlock>,
+ cached_exits: FxHashMap<(BasicBlock, CodeExtent), BasicBlock>,
}
struct DropData<'tcx> {
#[derive(Clone, Debug)]
pub struct BreakableScope<'tcx> {
/// Extent of the loop
- pub extent: CodeExtent<'tcx>,
+ pub extent: CodeExtent,
/// Where the body of the loop begins. `None` if block
pub continue_block: Option<BasicBlock>,
/// Block to branch into when the loop or block terminates (either by being `break`-en out
/// Convenience wrapper that pushes a scope and then executes `f`
/// to build its contents, popping the scope afterwards.
pub fn in_scope<F, R>(&mut self,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
mut block: BasicBlock,
f: F)
-> BlockAnd<R>
/// scope and call `pop_scope` afterwards. Note that these two
/// calls must be paired; using `in_scope` as a convenience
/// wrapper maybe preferable.
- pub fn push_scope(&mut self, extent: CodeExtent<'tcx>) {
+ pub fn push_scope(&mut self, extent: CodeExtent) {
debug!("push_scope({:?})", extent);
let vis_scope = self.visibility_scope;
self.scopes.push(Scope {
/// drops onto the end of `block` that are needed. This must
/// match 1-to-1 with `push_scope`.
pub fn pop_scope(&mut self,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
mut block: BasicBlock)
-> BlockAnd<()> {
debug!("pop_scope({:?}, {:?})", extent, block);
/// module comment for details.
pub fn exit_scope(&mut self,
span: Span,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
mut block: BasicBlock,
target: BasicBlock) {
debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target);
/// resolving `break` and `continue`.
pub fn find_breakable_scope(&mut self,
span: Span,
- label: CodeExtent<'tcx>)
+ label: CodeExtent)
-> &mut BreakableScope<'tcx> {
// find the loop-scope with the correct id
self.breakable_scopes.iter_mut()
/// Returns the extent of the scope which should be exited by a
/// return.
- pub fn extent_of_return_scope(&self) -> CodeExtent<'tcx> {
+ pub fn extent_of_return_scope(&self) -> CodeExtent {
// The outermost scope (`scopes[0]`) will be the `CallSiteScope`.
// We want `scopes[1]`, which is the `ParameterScope`.
assert!(self.scopes.len() >= 2);
- assert!(match *self.scopes[1].extent {
- CodeExtentData::ParameterScope(_) => true,
+ assert!(match self.scopes[1].extent {
+ CodeExtent::ParameterScope(_) => true,
_ => false,
});
self.scopes[1].extent
/// Returns the topmost active scope, which is known to be alive until
/// the next scope expression.
- pub fn topmost_scope(&self) -> CodeExtent<'tcx> {
+ pub fn topmost_scope(&self) -> CodeExtent {
self.scopes.last().expect("topmost_scope: no scopes present").extent
}
/// `extent`.
pub fn schedule_drop(&mut self,
span: Span,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
lvalue: &Lvalue<'tcx>,
lvalue_ty: Ty<'tcx>) {
let needs_drop = self.hir.needs_drop(lvalue_ty);
/// There may only be one “free” scheduled in any given scope.
pub fn schedule_box_free(&mut self,
span: Span,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
value: &Lvalue<'tcx>,
item_ty: Ty<'tcx>) {
for scope in self.scopes.iter_mut().rev() {
use hair::*;
use hair::cx::Cx;
use hair::cx::to_ref::ToRef;
-use rustc::middle::region::{BlockRemainder, CodeExtentData};
+use rustc::middle::region::{BlockRemainder, CodeExtent};
use rustc::hir;
use syntax::ast;
let stmts = mirror_stmts(cx, self.id, &*self.stmts);
Block {
targeted_by_break: self.targeted_by_break,
- extent: cx.tcx.node_extent(self.id),
+ extent: CodeExtent::Misc(self.id),
span: self.span,
stmts: stmts,
expr: self.expr.to_ref(),
result.push(StmtRef::Mirror(Box::new(Stmt {
span: stmt.span,
kind: StmtKind::Expr {
- scope: cx.tcx.node_extent(id),
+ scope: CodeExtent::Misc(id),
expr: expr.to_ref(),
},
})))
// ignore for purposes of the MIR
}
hir::DeclLocal(ref local) => {
- let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
+ let remainder_extent = CodeExtent::Remainder(BlockRemainder {
block: block_id,
first_statement_index: index as u32,
});
- let remainder_extent =
- cx.tcx.intern_code_extent(remainder_extent);
let pattern = Pattern::from_hir(cx.tcx, cx.tables(), &local.pat);
result.push(StmtRef::Mirror(Box::new(Stmt {
span: stmt.span,
kind: StmtKind::Let {
remainder_scope: remainder_extent,
- init_scope: cx.tcx.node_extent(id),
+ init_scope: CodeExtent::Misc(id),
pattern: pattern,
initializer: local.init.to_ref(),
},
block: &'tcx hir::Block)
-> ExprRef<'tcx> {
let block_ty = cx.tables().node_id_to_type(block.id);
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, block.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(block.id);
let expr = Expr {
ty: block_ty,
temp_lifetime: temp_lifetime,
type Output = Expr<'tcx>;
fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, self.id);
- let expr_extent = cx.tcx.node_extent(self.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(self.id);
+ let expr_extent = CodeExtent::Misc(self.id);
debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
expr: &'tcx hir::Expr)
-> Expr<'tcx> {
let expr_ty = cx.tables().expr_ty(expr);
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
let kind = match expr.node {
// Here comes the interesting stuff:
match dest.target_id {
hir::ScopeTarget::Block(target_id) |
hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(target_id)) => ExprKind::Break {
- label: cx.tcx.node_extent(target_id),
+ label: CodeExtent::Misc(target_id),
value: value.to_ref(),
},
hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
match dest.target_id {
hir::ScopeTarget::Block(_) => bug!("cannot continue to blocks"),
hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => ExprKind::Continue {
- label: cx.tcx.node_extent(loop_id),
+ label: CodeExtent::Misc(loop_id),
},
hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
bug!("invalid loop id for continue: {}", err)
hir::ExprBox(ref value) => {
ExprKind::Box {
value: value.to_ref(),
- value_extents: cx.tcx.node_extent(value.id),
+ value_extents: CodeExtent::Misc(value.id),
}
}
hir::ExprArray(ref fields) => ExprKind::Array { fields: fields.to_ref() },
method_call: ty::MethodCall)
-> Expr<'tcx> {
let callee = cx.tables().method_map[&method_call];
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
expr: &'tcx hir::Expr,
def: Def)
-> ExprKind<'tcx> {
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
match def {
Def::Local(def_id) => {
PassArgs::ByRef => {
let region = cx.tcx.node_scope_region(expr.id);
let (temp_lifetime, was_shrunk) =
- cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ cx.region_maps.temporary_scope2(expr.id);
argrefs.extend(args.iter()
.map(|arg| {
let arg_ty = cx.tables().expr_ty_adjusted(arg);
// construct the complete expression `foo()` for the overloaded call,
// which will yield the &T type
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
let ref_kind = overloaded_operator(cx, expr, method_call, pass_args, receiver, args);
let ref_expr = Expr {
temp_lifetime: temp_lifetime,
closure_expr_id: closure_expr.id,
};
let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap();
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, closure_expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(closure_expr.id);
let var_ty = cx.tables().node_id_to_type(id_var);
let captured_var = Expr {
temp_lifetime: temp_lifetime,
pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- pub region_maps: Rc<RegionMaps<'tcx>>,
+ pub region_maps: Rc<RegionMaps>,
constness: hir::Constness,
/// True if this constant/function needs overflow checks.
#[derive(Clone, Debug)]
pub struct Block<'tcx> {
pub targeted_by_break: bool,
- pub extent: CodeExtent<'tcx>,
+ pub extent: CodeExtent,
pub span: Span,
pub stmts: Vec<StmtRef<'tcx>>,
pub expr: Option<ExprRef<'tcx>>,
pub enum StmtKind<'tcx> {
Expr {
/// scope for this statement; may be used as lifetime of temporaries
- scope: CodeExtent<'tcx>,
+ scope: CodeExtent,
/// expression being evaluated in this statement
expr: ExprRef<'tcx>,
Let {
/// scope for variables bound in this let; covers this and
/// remaining statements in block
- remainder_scope: CodeExtent<'tcx>,
+ remainder_scope: CodeExtent,
/// scope for the initialization itself; might be used as
/// lifetime of temporaries
- init_scope: CodeExtent<'tcx>,
+ init_scope: CodeExtent,
/// let <PAT> = ...
pattern: Pattern<'tcx>,
/// lifetime of this expression if it should be spilled into a
/// temporary; should be None only if in a constant context
- pub temp_lifetime: Option<CodeExtent<'tcx>>,
+ pub temp_lifetime: Option<CodeExtent>,
/// whether this temp lifetime was shrunk by #36082.
pub temp_lifetime_was_shrunk: bool,
#[derive(Clone, Debug)]
pub enum ExprKind<'tcx> {
Scope {
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
value: ExprRef<'tcx>,
},
Box {
value: ExprRef<'tcx>,
- value_extents: CodeExtent<'tcx>,
+ value_extents: CodeExtent,
},
Call {
ty: ty::Ty<'tcx>,
arg: ExprRef<'tcx>,
},
Break {
- label: CodeExtent<'tcx>,
+ label: CodeExtent,
value: Option<ExprRef<'tcx>>,
},
Continue {
- label: CodeExtent<'tcx>,
+ label: CodeExtent,
},
Return {
value: Option<ExprRef<'tcx>>,
rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>,
ty: ty::Ty<'tcx>,
span: Span,
- scope: region::CodeExtent<'tcx>)
+ scope: region::CodeExtent)
-> Result<(), ErrorReported>
{
debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
use rustc_back::slice::ref_slice;
use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
use rustc::infer::type_variable::{TypeVariableOrigin};
+use rustc::middle::region::CodeExtent;
use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue};
let tcx = infcx.tcx;
let item_id = tcx.hir.as_local_node_id(def_id);
let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id));
- let implicit_region_bound = item_id.and_then(|id| {
- if body_id.is_some() {
- Some(tcx.mk_region(ty::ReScope(tcx.call_site_extent(id))))
- } else {
- None
- }
+ let implicit_region_bound = body_id.map(|body| {
+ tcx.mk_region(ty::ReScope(CodeExtent::CallSiteScope(body)))
});
Inherited {
region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
- pub region_maps: Rc<RegionMaps<'tcx>>,
+ pub region_maps: Rc<RegionMaps>,
free_region_map: FreeRegionMap<'tcx>,
body_id: ast::NodeId,
// call_site scope of innermost fn
- call_site_scope: Option<CodeExtent<'tcx>>,
+ call_site_scope: Option<CodeExtent>,
// id of innermost fn or loop
repeating_scope: ast::NodeId,
}
}
- fn set_call_site_scope(&mut self, call_site_scope: Option<CodeExtent<'tcx>>)
- -> Option<CodeExtent<'tcx>> {
+ fn set_call_site_scope(&mut self, call_site_scope: Option<CodeExtent>)
+ -> Option<CodeExtent> {
mem::replace(&mut self.call_site_scope, call_site_scope)
}
let body_id = body.id();
- let call_site = self.tcx.call_site_extent(id);
+ let call_site = CodeExtent::CallSiteScope(body_id);
let old_call_site_scope = self.set_call_site_scope(Some(call_site));
let fn_sig = {
let old_body_id = self.set_body_id(body_id.node_id);
self.relate_free_regions(&fn_sig_tys[..], body_id.node_id, span);
- self.link_fn_args(self.tcx.node_extent(body_id.node_id), &body.arguments);
+ self.link_fn_args(CodeExtent::Misc(body_id.node_id), &body.arguments);
self.visit_body(body);
self.visit_region_obligations(body_id.node_id);
// call occurs.
//
// FIXME(#6268) to support nested method calls, should be callee_id
- let callee_scope = self.tcx.node_extent(call_expr.id);
+ let callee_scope = CodeExtent::Misc(call_expr.id);
let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope));
debug!("callee_region={:?}", callee_region);
debug!("constrain_index(index_expr=?, indexed_ty={}",
self.ty_to_string(indexed_ty));
- let r_index_expr = ty::ReScope(self.tcx.node_extent(index_expr.id));
+ let r_index_expr = ty::ReScope(CodeExtent::Misc(index_expr.id));
if let ty::TyRef(r_ptr, mt) = indexed_ty.sty {
match mt.ty.sty {
ty::TySlice(_) | ty::TyStr => {
/// Computes the guarantors for any ref bindings in a match and
/// then ensures that the lifetime of the resulting pointer is
/// linked to the lifetime of its guarantor (if any).
- fn link_fn_args(&self, body_scope: CodeExtent<'tcx>, args: &[hir::Arg]) {
+ fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
let mc = &mc::MemCategorizationContext::new(self, &self.region_maps);
for arg in args {
/// must outlive `callee_scope`.
fn link_by_ref(&self,
expr: &hir::Expr,
- callee_scope: CodeExtent<'tcx>) {
+ callee_scope: CodeExtent) {
debug!("link_by_ref(expr={:?}, callee_scope={:?})",
expr, callee_scope);
let mc = mc::MemCategorizationContext::new(self, &self.region_maps);
}
}
-impl<'tcx> Clean<Option<Lifetime>> for ty::RegionKind<'tcx> {
+impl Clean<Option<Lifetime>> for ty::RegionKind {
fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
match *self {
ty::ReStatic => Some(Lifetime::statik()),