//! Most of the documentation on regions can be found in
//! `middle/typeck/infer/region_inference.rs`
-use metadata::inline::InlinedItem;
use front::map as ast_map;
use session::Session;
use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
+use middle::cstore::InlinedItem;
use middle::ty::{self, Ty};
use std::cell::RefCell;
use std::collections::hash_map::Entry;
+use std::fmt;
use std::mem;
use syntax::codemap::{self, Span};
use syntax::ast::{self, NodeId};
use rustc_front::hir;
-use rustc_front::visit::{self, Visitor, FnKind};
+use rustc_front::intravisit::{self, Visitor, FnKind};
use rustc_front::hir::{Block, Item, FnDecl, Arm, Pat, Stmt, Expr, Local};
use rustc_front::util::stmt_id;
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
- RustcDecodable, Debug, Copy)]
+ RustcDecodable, Copy)]
pub struct CodeExtent(u32);
+impl fmt::Debug for CodeExtent {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, "CodeExtent({:?}", self.0));
+
+ try!(ty::tls::with_opt(|opt_tcx| {
+ if let Some(tcx) = opt_tcx {
+ let data = tcx.region_maps.code_extents.borrow()[self.0 as usize];
+ try!(write!(f, "/{:?}", data));
+ }
+ Ok(())
+ }));
+
+ write!(f, ")")
+ }
+}
+
/// The root of everything. I should be using NonZero or profiling
/// instead of this (probably).
pub const ROOT_CODE_EXTENT : CodeExtent = CodeExtent(0);
pub enum CodeExtentData {
Misc(ast::NodeId),
+ // extent of the call-site for a function or closure (outlives
+ // the parameters as well as the body).
+ CallSiteScope { fn_id: ast::NodeId, body_id: ast::NodeId },
+
// extent of parameters passed to a function or closure (they
// outlive its body)
ParameterScope { fn_id: ast::NodeId, body_id: ast::NodeId },
Remainder(BlockRemainder)
}
-/// extent of destructors for temporaries of node-id
+/// extent of call-site for a function/method.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
RustcDecodable, Debug, Copy)]
-pub struct DestructionScopeData {
- pub node_id: ast::NodeId
+pub struct CallSiteScopeData {
+ pub fn_id: ast::NodeId, pub body_id: ast::NodeId,
}
-impl DestructionScopeData {
- pub fn new(node_id: ast::NodeId) -> DestructionScopeData {
- DestructionScopeData { node_id: node_id }
- }
+impl CallSiteScopeData {
pub fn to_code_extent(&self, region_maps: &RegionMaps) -> CodeExtent {
region_maps.lookup_code_extent(
- CodeExtentData::DestructionScope(self.node_id))
+ match *self {
+ CallSiteScopeData { fn_id, body_id } =>
+ CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id },
+ })
}
}
// precise extent denoted by `self`.
CodeExtentData::Remainder(br) => br.block,
CodeExtentData::DestructionScope(node_id) => node_id,
+ CodeExtentData::CallSiteScope { fn_id: _, body_id } |
CodeExtentData::ParameterScope { fn_id: _, body_id } => body_id,
}
}
match ast_map.find(self.node_id(region_maps)) {
Some(ast_map::NodeBlock(ref blk)) => {
match region_maps.code_extent_data(*self) {
+ CodeExtentData::CallSiteScope { .. } |
CodeExtentData::ParameterScope { .. } |
CodeExtentData::Misc(_) |
CodeExtentData::DestructionScope(_) => Some(blk.span),
pub fn item_extent(&self, n: ast::NodeId) -> CodeExtent {
self.lookup_code_extent(CodeExtentData::DestructionScope(n))
}
+ pub fn call_site_extent(&self, fn_id: ast::NodeId, body_id: ast::NodeId) -> CodeExtent {
+ assert!(fn_id != body_id);
+ self.lookup_code_extent(CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id })
+ }
pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent> {
self.code_extent_interner.borrow().get(&CodeExtentData::DestructionScope(n)).cloned()
}
}
*vec = Vec::with_capacity(64);
- vec.push_all(buf);
+ vec.extend_from_slice(buf);
loop {
vec.push(scope);
match scope_map[scope.0 as usize].into_option() {
{
// This block should be kept approximately in sync with
- // `visit::walk_block`. (We manually walk the block, rather
+ // `intravisit::walk_block`. (We manually walk the block, rather
// than call `walk_block`, in order to maintain precise
// index information.)
parent: stmt_extent,
};
}
- visitor.visit_stmt(&**statement)
+ visitor.visit_stmt(statement)
}
walk_list!(visitor, visit_expr, &blk.expr);
}
visitor.terminating_scopes.insert(expr.id);
}
- visit::walk_arm(visitor, arm);
+ intravisit::walk_arm(visitor, arm);
}
fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &hir::Pat) {
_ => { }
}
- visit::walk_pat(visitor, pat);
+ intravisit::walk_pat(visitor, pat);
}
fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &hir::Stmt) {
let prev_parent = visitor.cx.parent;
visitor.cx.parent = stmt_extent;
- visit::walk_stmt(visitor, stmt);
+ intravisit::walk_stmt(visitor, stmt);
visitor.cx.parent = prev_parent;
}
}
}
- visit::walk_expr(visitor, expr);
+ intravisit::walk_expr(visitor, expr);
visitor.cx = prev_cx;
}
None => { }
}
- visit::walk_local(visitor, local);
+ intravisit::walk_local(visitor, local);
/// True if `pat` match the `P&` nonterminal:
///
var_parent: ROOT_CODE_EXTENT,
parent: ROOT_CODE_EXTENT
};
- visit::walk_item(visitor, item);
+ intravisit::walk_item(visitor, item);
visitor.create_item_scope_if_needed(item.id);
visitor.cx = prev_cx;
visitor.terminating_scopes = prev_ts;
body.id,
visitor.cx.parent);
+ visitor.cx.parent = visitor.new_code_extent(
+ CodeExtentData::CallSiteScope { fn_id: id, body_id: body.id });
+
let fn_decl_scope = visitor.new_code_extent(
CodeExtentData::ParameterScope { fn_id: id, body_id: body.id });
var_parent: fn_decl_scope,
};
- visit::walk_fn_decl(visitor, decl);
- visit::walk_fn_kind(visitor, kind);
+ intravisit::walk_fn_decl(visitor, decl);
+ intravisit::walk_fn_kind(visitor, kind);
// The body of the every fn is a root scope.
visitor.cx = Context {
}
fn visit_impl_item(&mut self, ii: &hir::ImplItem) {
- visit::walk_impl_item(self, ii);
+ intravisit::walk_impl_item(self, ii);
self.create_item_scope_if_needed(ii.id);
}
fn visit_trait_item(&mut self, ti: &hir::TraitItem) {
- visit::walk_trait_item(self, ti);
+ intravisit::walk_trait_item(self, ti);
self.create_item_scope_if_needed(ti.id);
}
},
terminating_scopes: NodeSet()
};
- visit::walk_crate(&mut visitor, krate);
+ krate.visit_all_items(&mut visitor);
}
return maps;
}