rustc: store ty::Tables separately for each body (except closures').
This commit is contained in:
parent
85a4a192c7
commit
cde0a7e7e0
@ -113,6 +113,7 @@ pub enum DepNode<D: Clone + Debug> {
|
||||
SizedConstraint(D),
|
||||
AssociatedItemDefIds(D),
|
||||
InherentImpls(D),
|
||||
Tables(D),
|
||||
|
||||
// The set of impls for a given trait. Ultimately, it would be
|
||||
// nice to get more fine-grained here (e.g., to include a
|
||||
@ -162,6 +163,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
ItemSignature,
|
||||
AssociatedItemDefIds,
|
||||
InherentImpls,
|
||||
Tables,
|
||||
TraitImpls,
|
||||
ReprHints,
|
||||
}
|
||||
@ -230,6 +232,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
SizedConstraint(ref d) => op(d).map(SizedConstraint),
|
||||
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
|
||||
InherentImpls(ref d) => op(d).map(InherentImpls),
|
||||
Tables(ref d) => op(d).map(Tables),
|
||||
TraitImpls(ref d) => op(d).map(TraitImpls),
|
||||
TraitItems(ref d) => op(d).map(TraitItems),
|
||||
ReprHints(ref d) => op(d).map(ReprHints),
|
||||
|
@ -23,10 +23,6 @@ pub struct NodeCollector<'ast> {
|
||||
pub(super) map: Vec<MapEntry<'ast>>,
|
||||
/// The parent of this node
|
||||
pub parent_node: NodeId,
|
||||
/// If true, completely ignore nested items. We set this when loading
|
||||
/// HIR from metadata, since in that case we only want the HIR for
|
||||
/// one specific item (and not the ones nested inside of it).
|
||||
pub ignore_nested_items: bool
|
||||
}
|
||||
|
||||
impl<'ast> NodeCollector<'ast> {
|
||||
@ -35,30 +31,12 @@ impl<'ast> NodeCollector<'ast> {
|
||||
krate: krate,
|
||||
map: vec![],
|
||||
parent_node: CRATE_NODE_ID,
|
||||
ignore_nested_items: false
|
||||
};
|
||||
collector.insert_entry(CRATE_NODE_ID, RootCrate);
|
||||
|
||||
collector
|
||||
}
|
||||
|
||||
pub(super) fn extend(krate: &'ast Crate,
|
||||
parent: &'ast InlinedItem,
|
||||
parent_node: NodeId,
|
||||
map: Vec<MapEntry<'ast>>)
|
||||
-> NodeCollector<'ast> {
|
||||
let mut collector = NodeCollector {
|
||||
krate: krate,
|
||||
map: map,
|
||||
parent_node: parent_node,
|
||||
ignore_nested_items: true
|
||||
};
|
||||
|
||||
collector.insert_entry(parent_node, RootInlinedParent(parent));
|
||||
|
||||
collector
|
||||
}
|
||||
|
||||
fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
|
||||
debug!("ast_map: {:?} => {:?}", id, entry);
|
||||
let len = self.map.len();
|
||||
@ -92,27 +70,19 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
|
||||
fn visit_nested_item(&mut self, item: ItemId) {
|
||||
debug!("visit_nested_item: {:?}", item);
|
||||
if !self.ignore_nested_items {
|
||||
self.visit_item(self.krate.item(item.id))
|
||||
}
|
||||
self.visit_item(self.krate.item(item.id));
|
||||
}
|
||||
|
||||
fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
|
||||
if !self.ignore_nested_items {
|
||||
self.visit_trait_item(self.krate.trait_item(item_id))
|
||||
}
|
||||
self.visit_trait_item(self.krate.trait_item(item_id));
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
|
||||
if !self.ignore_nested_items {
|
||||
self.visit_impl_item(self.krate.impl_item(item_id))
|
||||
}
|
||||
self.visit_impl_item(self.krate.impl_item(item_id));
|
||||
}
|
||||
|
||||
fn visit_nested_body(&mut self, id: BodyId) {
|
||||
if !self.ignore_nested_items {
|
||||
self.visit_body(self.krate.body(id))
|
||||
}
|
||||
self.visit_body(self.krate.body(id));
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, i: &'ast Item) {
|
||||
|
@ -25,28 +25,18 @@ use syntax::codemap::Spanned;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use hir::*;
|
||||
use hir::intravisit::Visitor;
|
||||
use hir::print::Nested;
|
||||
use util::nodemap::DefIdMap;
|
||||
|
||||
use arena::TypedArena;
|
||||
use std::cell::RefCell;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
|
||||
pub mod blocks;
|
||||
mod collector;
|
||||
mod def_collector;
|
||||
pub mod definitions;
|
||||
|
||||
/// The data we save and restore about an inlined item or method. This is not
|
||||
/// part of the AST that we parse from a file, but it becomes part of the tree
|
||||
/// that we trans.
|
||||
#[derive(Debug)]
|
||||
struct InlinedItem {
|
||||
def_id: DefId,
|
||||
body: Body,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Node<'ast> {
|
||||
NodeItem(&'ast Item),
|
||||
@ -99,7 +89,6 @@ enum MapEntry<'ast> {
|
||||
|
||||
/// Roots for node trees.
|
||||
RootCrate,
|
||||
RootInlinedParent(&'ast InlinedItem)
|
||||
}
|
||||
|
||||
impl<'ast> Clone for MapEntry<'ast> {
|
||||
@ -152,8 +141,7 @@ impl<'ast> MapEntry<'ast> {
|
||||
EntryVisibility(id, _) => id,
|
||||
|
||||
NotPresent |
|
||||
RootCrate |
|
||||
RootInlinedParent(_) => return None,
|
||||
RootCrate => return None,
|
||||
})
|
||||
}
|
||||
|
||||
@ -225,7 +213,7 @@ impl<'ast> MapEntry<'ast> {
|
||||
pub struct Forest {
|
||||
krate: Crate,
|
||||
pub dep_graph: DepGraph,
|
||||
inlined_items: TypedArena<InlinedItem>
|
||||
inlined_bodies: TypedArena<Body>
|
||||
}
|
||||
|
||||
impl Forest {
|
||||
@ -233,7 +221,7 @@ impl Forest {
|
||||
Forest {
|
||||
krate: krate,
|
||||
dep_graph: dep_graph.clone(),
|
||||
inlined_items: TypedArena::new()
|
||||
inlined_bodies: TypedArena::new()
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,20 +251,15 @@ pub struct Map<'ast> {
|
||||
///
|
||||
/// Also, indexing is pretty quick when you've got a vector and
|
||||
/// plain old integers.
|
||||
map: RefCell<Vec<MapEntry<'ast>>>,
|
||||
map: Vec<MapEntry<'ast>>,
|
||||
|
||||
definitions: Definitions,
|
||||
|
||||
/// All NodeIds that are numerically greater or equal to this value come
|
||||
/// from inlined items.
|
||||
local_node_id_watermark: NodeId,
|
||||
/// Bodies inlined from other crates are cached here.
|
||||
inlined_bodies: RefCell<DefIdMap<&'ast Body>>,
|
||||
}
|
||||
|
||||
impl<'ast> Map<'ast> {
|
||||
pub fn is_inlined_node_id(&self, id: NodeId) -> bool {
|
||||
id >= self.local_node_id_watermark
|
||||
}
|
||||
|
||||
/// Registers a read in the dependency graph of the AST node with
|
||||
/// the given `id`. This needs to be called each time a public
|
||||
/// function returns the HIR for a node -- in other words, when it
|
||||
@ -289,111 +272,71 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
|
||||
fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
|
||||
let map = self.map.borrow();
|
||||
let mut id = id0;
|
||||
if !self.is_inlined_node_id(id) {
|
||||
let mut last_expr = None;
|
||||
loop {
|
||||
let entry = map[id.as_usize()];
|
||||
match entry {
|
||||
EntryItem(..) |
|
||||
EntryTraitItem(..) |
|
||||
EntryImplItem(..) => {
|
||||
if let Some(last_id) = last_expr {
|
||||
// The body may have a separate dep node
|
||||
if entry.is_body_owner(last_id) {
|
||||
let def_id = self.local_def_id(id);
|
||||
return DepNode::HirBody(def_id);
|
||||
}
|
||||
}
|
||||
return DepNode::Hir(self.local_def_id(id));
|
||||
}
|
||||
|
||||
EntryVariant(p, v) => {
|
||||
id = p;
|
||||
|
||||
if last_expr.is_some() {
|
||||
if v.node.disr_expr.map(|e| e.node_id) == last_expr {
|
||||
// The enum parent holds both Hir and HirBody nodes.
|
||||
let def_id = self.local_def_id(id);
|
||||
return DepNode::HirBody(def_id);
|
||||
}
|
||||
let mut last_expr = None;
|
||||
loop {
|
||||
let entry = self.map[id.as_usize()];
|
||||
match entry {
|
||||
EntryItem(..) |
|
||||
EntryTraitItem(..) |
|
||||
EntryImplItem(..) => {
|
||||
if let Some(last_id) = last_expr {
|
||||
// The body may have a separate dep node
|
||||
if entry.is_body_owner(last_id) {
|
||||
let def_id = self.local_def_id(id);
|
||||
return DepNode::HirBody(def_id);
|
||||
}
|
||||
}
|
||||
|
||||
EntryForeignItem(p, _) |
|
||||
EntryField(p, _) |
|
||||
EntryStmt(p, _) |
|
||||
EntryTy(p, _) |
|
||||
EntryTraitRef(p, _) |
|
||||
EntryLocal(p, _) |
|
||||
EntryPat(p, _) |
|
||||
EntryBlock(p, _) |
|
||||
EntryStructCtor(p, _) |
|
||||
EntryLifetime(p, _) |
|
||||
EntryTyParam(p, _) |
|
||||
EntryVisibility(p, _) =>
|
||||
id = p,
|
||||
|
||||
EntryExpr(p, _) => {
|
||||
last_expr = Some(id);
|
||||
id = p;
|
||||
}
|
||||
|
||||
RootCrate => {
|
||||
return DepNode::Hir(DefId::local(CRATE_DEF_INDEX));
|
||||
}
|
||||
|
||||
RootInlinedParent(_) =>
|
||||
bug!("node {} has inlined ancestor but is not inlined", id0),
|
||||
|
||||
NotPresent =>
|
||||
// Some nodes, notably macro definitions, are not
|
||||
// present in the map for whatever reason, but
|
||||
// they *do* have def-ids. So if we encounter an
|
||||
// empty hole, check for that case.
|
||||
return self.opt_local_def_id(id)
|
||||
.map(|def_id| DepNode::Hir(def_id))
|
||||
.unwrap_or_else(|| {
|
||||
bug!("Walking parents from `{}` \
|
||||
led to `NotPresent` at `{}`",
|
||||
id0, id)
|
||||
}),
|
||||
return DepNode::Hir(self.local_def_id(id));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// reading from an inlined def-id is really a read out of
|
||||
// the metadata from which we loaded the item.
|
||||
loop {
|
||||
match map[id.as_usize()] {
|
||||
EntryItem(p, _) |
|
||||
EntryForeignItem(p, _) |
|
||||
EntryTraitItem(p, _) |
|
||||
EntryImplItem(p, _) |
|
||||
EntryVariant(p, _) |
|
||||
EntryField(p, _) |
|
||||
EntryExpr(p, _) |
|
||||
EntryStmt(p, _) |
|
||||
EntryTy(p, _) |
|
||||
EntryTraitRef(p, _) |
|
||||
EntryLocal(p, _) |
|
||||
EntryPat(p, _) |
|
||||
EntryBlock(p, _) |
|
||||
EntryStructCtor(p, _) |
|
||||
EntryLifetime(p, _) |
|
||||
EntryTyParam(p, _) |
|
||||
EntryVisibility(p, _) =>
|
||||
id = p,
|
||||
|
||||
RootInlinedParent(parent) =>
|
||||
return DepNode::MetaData(parent.def_id),
|
||||
EntryVariant(p, v) => {
|
||||
id = p;
|
||||
|
||||
RootCrate =>
|
||||
bug!("node {} has crate ancestor but is inlined", id0),
|
||||
|
||||
NotPresent =>
|
||||
bug!("node {} is inlined but not present in map", id0),
|
||||
if last_expr.is_some() {
|
||||
if v.node.disr_expr.map(|e| e.node_id) == last_expr {
|
||||
// The enum parent holds both Hir and HirBody nodes.
|
||||
let def_id = self.local_def_id(id);
|
||||
return DepNode::HirBody(def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EntryForeignItem(p, _) |
|
||||
EntryField(p, _) |
|
||||
EntryStmt(p, _) |
|
||||
EntryTy(p, _) |
|
||||
EntryTraitRef(p, _) |
|
||||
EntryLocal(p, _) |
|
||||
EntryPat(p, _) |
|
||||
EntryBlock(p, _) |
|
||||
EntryStructCtor(p, _) |
|
||||
EntryLifetime(p, _) |
|
||||
EntryTyParam(p, _) |
|
||||
EntryVisibility(p, _) =>
|
||||
id = p,
|
||||
|
||||
EntryExpr(p, _) => {
|
||||
last_expr = Some(id);
|
||||
id = p;
|
||||
}
|
||||
|
||||
RootCrate => {
|
||||
return DepNode::Hir(DefId::local(CRATE_DEF_INDEX));
|
||||
}
|
||||
|
||||
NotPresent =>
|
||||
// Some nodes, notably macro definitions, are not
|
||||
// present in the map for whatever reason, but
|
||||
// they *do* have def-ids. So if we encounter an
|
||||
// empty hole, check for that case.
|
||||
return self.opt_local_def_id(id)
|
||||
.map(|def_id| DepNode::Hir(def_id))
|
||||
.unwrap_or_else(|| {
|
||||
bug!("Walking parents from `{}` \
|
||||
led to `NotPresent` at `{}`",
|
||||
id0, id)
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -442,11 +385,11 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
|
||||
fn entry_count(&self) -> usize {
|
||||
self.map.borrow().len()
|
||||
self.map.len()
|
||||
}
|
||||
|
||||
fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
|
||||
self.map.borrow().get(id.as_usize()).cloned()
|
||||
self.map.get(id.as_usize()).cloned()
|
||||
}
|
||||
|
||||
pub fn krate(&self) -> &'ast Crate {
|
||||
@ -483,7 +426,7 @@ impl<'ast> Map<'ast> {
|
||||
/// for embedded constant expressions (e.g. `N` in `[T; N]`).
|
||||
pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
|
||||
let parent = self.get_parent_node(node_id);
|
||||
if self.map.borrow()[parent.as_usize()].is_body_owner(node_id) {
|
||||
if self.map[parent.as_usize()].is_body_owner(node_id) {
|
||||
parent
|
||||
} else {
|
||||
node_id
|
||||
@ -644,11 +587,7 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
|
||||
pub fn get_parent_did(&self, id: NodeId) -> DefId {
|
||||
let parent = self.get_parent(id);
|
||||
match self.find_entry(parent) {
|
||||
Some(RootInlinedParent(ii)) => ii.def_id,
|
||||
_ => self.local_def_id(parent)
|
||||
}
|
||||
self.local_def_id(self.get_parent(id))
|
||||
}
|
||||
|
||||
pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
|
||||
@ -660,8 +599,6 @@ impl<'ast> Map<'ast> {
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
/// Wrong but OK, because the only inlined foreign items are intrinsics.
|
||||
Some(RootInlinedParent(_)) => Some(Abi::RustIntrinsic),
|
||||
_ => None
|
||||
};
|
||||
match abi {
|
||||
@ -737,11 +674,17 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_inlined_body(&self, id: NodeId) -> &'ast Body {
|
||||
match self.find_entry(id) {
|
||||
Some(RootInlinedParent(inlined_item)) => &inlined_item.body,
|
||||
_ => bug!("expected inlined item, found {}", self.node_to_string(id)),
|
||||
}
|
||||
pub fn get_inlined_body(&self, def_id: DefId) -> Option<&'ast Body> {
|
||||
self.inlined_bodies.borrow().get(&def_id).map(|&body| {
|
||||
self.dep_graph.read(DepNode::MetaData(def_id));
|
||||
body
|
||||
})
|
||||
}
|
||||
|
||||
pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'ast Body {
|
||||
let body = self.forest.inlined_bodies.alloc(body);
|
||||
self.inlined_bodies.borrow_mut().insert(def_id, body);
|
||||
body
|
||||
}
|
||||
|
||||
/// Returns the name associated with the given NodeId's AST.
|
||||
@ -824,7 +767,6 @@ impl<'ast> Map<'ast> {
|
||||
Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),
|
||||
|
||||
Some(RootCrate) => self.forest.krate.span,
|
||||
Some(RootInlinedParent(parent)) => parent.body.value.span,
|
||||
Some(NotPresent) | None => {
|
||||
bug!("hir::map::Map::span: id not in map: {:?}", id)
|
||||
}
|
||||
@ -973,41 +915,15 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
|
||||
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
|
||||
}
|
||||
|
||||
let local_node_id_watermark = NodeId::new(map.len());
|
||||
|
||||
Map {
|
||||
forest: forest,
|
||||
dep_graph: forest.dep_graph.clone(),
|
||||
map: RefCell::new(map),
|
||||
map: map,
|
||||
definitions: definitions,
|
||||
local_node_id_watermark: local_node_id_watermark,
|
||||
inlined_bodies: RefCell::new(DefIdMap()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for bodies loaded from external crate that are being inlined into this
|
||||
/// crate.
|
||||
pub fn map_decoded_body<'ast>(map: &Map<'ast>,
|
||||
def_id: DefId,
|
||||
body: Body,
|
||||
parent_id: NodeId)
|
||||
-> &'ast Body {
|
||||
let _ignore = map.forest.dep_graph.in_ignore();
|
||||
|
||||
let ii = map.forest.inlined_items.alloc(InlinedItem {
|
||||
def_id: def_id,
|
||||
body: body
|
||||
});
|
||||
|
||||
let mut collector = NodeCollector::extend(map.krate(),
|
||||
ii,
|
||||
parent_id,
|
||||
mem::replace(&mut *map.map.borrow_mut(), vec![]));
|
||||
collector.visit_body(&ii.body);
|
||||
*map.map.borrow_mut() = collector.map;
|
||||
|
||||
&ii.body
|
||||
}
|
||||
|
||||
/// Identical to the `PpAnn` implementation for `hir::Crate`,
|
||||
/// except it avoids creating a dependency on the whole crate.
|
||||
impl<'ast> print::PpAnn for Map<'ast> {
|
||||
|
@ -65,6 +65,7 @@ pub struct GlobalArenas<'tcx> {
|
||||
trait_def: TypedArena<ty::TraitDef>,
|
||||
adt_def: TypedArena<ty::AdtDef>,
|
||||
mir: TypedArena<RefCell<Mir<'tcx>>>,
|
||||
tables: TypedArena<ty::Tables<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> GlobalArenas<'tcx> {
|
||||
@ -75,6 +76,7 @@ impl<'tcx> GlobalArenas<'tcx> {
|
||||
trait_def: TypedArena::new(),
|
||||
adt_def: TypedArena::new(),
|
||||
mir: TypedArena::new(),
|
||||
tables: TypedArena::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -189,6 +191,7 @@ pub struct CommonTypes<'tcx> {
|
||||
pub err: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct Tables<'tcx> {
|
||||
/// Resolved definitions for `<T>::X` associated paths.
|
||||
pub type_relative_path_defs: NodeMap<Def>,
|
||||
@ -399,7 +402,7 @@ pub struct GlobalCtxt<'tcx> {
|
||||
free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
|
||||
// FIXME: jroesch make this a refcell
|
||||
|
||||
pub tables: RefCell<Tables<'tcx>>,
|
||||
pub tables: RefCell<DepTrackingMap<maps::Tables<'tcx>>>,
|
||||
|
||||
/// Maps from a trait item to the trait item "descriptor"
|
||||
pub associated_items: RefCell<DepTrackingMap<maps::AssociatedItems<'tcx>>>,
|
||||
@ -651,6 +654,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.global_arenas.mir.alloc(RefCell::new(mir))
|
||||
}
|
||||
|
||||
pub fn alloc_tables(self, tables: ty::Tables<'gcx>) -> &'gcx ty::Tables<'gcx> {
|
||||
self.global_arenas.tables.alloc(tables)
|
||||
}
|
||||
|
||||
pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
|
||||
self.global_arenas.trait_def.alloc(def)
|
||||
}
|
||||
@ -749,7 +756,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
variance_computed: Cell::new(false),
|
||||
sess: s,
|
||||
trait_map: resolutions.trait_map,
|
||||
tables: RefCell::new(Tables::empty()),
|
||||
tables: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
|
@ -48,3 +48,4 @@ dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }
|
||||
dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }
|
||||
dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind }
|
||||
dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> }
|
||||
dep_map_ty! { Tables: Tables(DefId) -> &'tcx ty::Tables<'tcx> }
|
||||
|
@ -321,7 +321,7 @@ pub struct MethodCallee<'tcx> {
|
||||
/// needed to add to the side tables. Thus to disambiguate
|
||||
/// we also keep track of whether there's an adjustment in
|
||||
/// our key.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct MethodCall {
|
||||
pub expr_id: NodeId,
|
||||
pub autoderef: u32
|
||||
@ -501,7 +501,7 @@ impl<T> Slice<T> {
|
||||
/// Upvars do not get their own node-id. Instead, we use the pair of
|
||||
/// the original var id (that is, the root variable that is referenced
|
||||
/// by the upvar) and the id of the closure expression.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct UpvarId {
|
||||
pub var_id: NodeId,
|
||||
pub closure_expr_id: NodeId,
|
||||
@ -1917,19 +1917,30 @@ impl BorrowKind {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn tables(self) -> Ref<'a, Tables<'gcx>> {
|
||||
self.tables.borrow()
|
||||
}
|
||||
|
||||
pub fn body_tables(self, body: hir::BodyId) -> &'a Tables<'gcx> {
|
||||
pub fn body_tables(self, body: hir::BodyId) -> &'gcx Tables<'gcx> {
|
||||
self.item_tables(self.map.body_owner_def_id(body))
|
||||
}
|
||||
|
||||
pub fn item_tables(self, _def_id: DefId) -> &'a Tables<'gcx> {
|
||||
// HACK(eddyb) temporarily work around RefCell until proper per-body tables
|
||||
unsafe {
|
||||
mem::transmute::<&Tables, &Tables>(&self.tables())
|
||||
}
|
||||
pub fn item_tables(self, def_id: DefId) -> &'gcx Tables<'gcx> {
|
||||
self.tables.memoize(def_id, || {
|
||||
if def_id.is_local() {
|
||||
// Closures' tables come from their outermost function,
|
||||
// as they are part of the same "inference environment".
|
||||
let outer_def_id = self.closure_base_def_id(def_id);
|
||||
if outer_def_id != def_id {
|
||||
return self.item_tables(outer_def_id);
|
||||
}
|
||||
|
||||
bug!("No def'n found for {:?} in tcx.tables", def_id);
|
||||
}
|
||||
|
||||
// Cross-crate side-tables only exist alongside serialized HIR.
|
||||
self.sess.cstore.maybe_get_item_body(self.global_tcx(), def_id).map(|_| {
|
||||
self.tables.borrow()[&def_id]
|
||||
}).unwrap_or_else(|| {
|
||||
bug!("tcx.item_tables({:?}): missing from metadata", def_id)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn expr_span(self, id: NodeId) -> Span {
|
||||
|
@ -52,21 +52,20 @@ macro_rules! math {
|
||||
|
||||
fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
variant_def: DefId)
|
||||
-> Option<(&'tcx Expr, &'a ty::Tables<'tcx>)> {
|
||||
-> Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>)> {
|
||||
if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) {
|
||||
let enum_node_id = tcx.map.get_parent(variant_node_id);
|
||||
if let Some(ast_map::NodeItem(it)) = tcx.map.find(enum_node_id) {
|
||||
match it.node {
|
||||
hir::ItemEnum(hir::EnumDef { ref variants }, _) => {
|
||||
for variant in variants {
|
||||
if variant.node.data.id() == variant_node_id {
|
||||
return variant.node.disr_expr.map(|e| {
|
||||
(&tcx.map.body(e).value, tcx.body_tables(e))
|
||||
});
|
||||
}
|
||||
if let hir::ItemEnum(ref edef, _) = it.node {
|
||||
for variant in &edef.variants {
|
||||
if variant.node.data.id() == variant_node_id {
|
||||
return variant.node.disr_expr.map(|e| {
|
||||
let def_id = tcx.map.body_owner_def_id(e);
|
||||
(&tcx.map.body(e).value,
|
||||
tcx.tables.borrow().get(&def_id).cloned())
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -81,7 +80,8 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: Option<&'tcx Substs<'tcx>>)
|
||||
-> Option<(&'tcx Expr, &'a ty::Tables<'tcx>,
|
||||
-> Option<(&'tcx Expr,
|
||||
Option<&'a ty::Tables<'tcx>>,
|
||||
Option<ty::Ty<'tcx>>)> {
|
||||
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
|
||||
match tcx.map.find(node_id) {
|
||||
@ -92,7 +92,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
Some(ast_map::NodeImplItem(&hir::ImplItem {
|
||||
node: hir::ImplItemKind::Const(ref ty, body), ..
|
||||
})) => {
|
||||
Some((&tcx.map.body(body).value, tcx.item_tables(def_id),
|
||||
Some((&tcx.map.body(body).value,
|
||||
tcx.tables.borrow().get(&def_id).cloned(),
|
||||
tcx.ast_ty_to_prim_ty(ty)))
|
||||
}
|
||||
Some(ast_map::NodeTraitItem(ti)) => match ti.node {
|
||||
@ -104,7 +105,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let trait_id = tcx.map.get_parent(node_id);
|
||||
let trait_id = tcx.map.local_def_id(trait_id);
|
||||
let default_value = default.map(|body| {
|
||||
(&tcx.map.body(body).value, tcx.item_tables(def_id),
|
||||
(&tcx.map.body(body).value,
|
||||
tcx.tables.borrow().get(&def_id).cloned(),
|
||||
tcx.ast_ty_to_prim_ty(ty))
|
||||
});
|
||||
resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs)
|
||||
@ -124,7 +126,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
} else {
|
||||
let expr_tables_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| {
|
||||
(&body.value, tcx.item_tables(def_id),
|
||||
(&body.value, Some(tcx.item_tables(def_id)),
|
||||
Some(tcx.sess.cstore.item_type(tcx, def_id)))
|
||||
});
|
||||
match tcx.sess.cstore.describe_def(def_id) {
|
||||
@ -152,12 +154,13 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
|
||||
-> Option<(&'tcx hir::Body, &'a ty::Tables<'tcx>)>
|
||||
-> Option<(&'tcx hir::Body, Option<&'a ty::Tables<'tcx>>)>
|
||||
{
|
||||
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
|
||||
FnLikeNode::from_node(tcx.map.get(node_id)).and_then(|fn_like| {
|
||||
if fn_like.constness() == hir::Constness::Const {
|
||||
Some((tcx.map.body(fn_like.body()), tcx.body_tables(fn_like.body())))
|
||||
Some((tcx.map.body(fn_like.body()),
|
||||
tcx.tables.borrow().get(&def_id).cloned()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -165,7 +168,7 @@ fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
|
||||
} else {
|
||||
if tcx.sess.cstore.is_const_fn(def_id) {
|
||||
tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| {
|
||||
(body, tcx.item_tables(def_id))
|
||||
(body, Some(tcx.item_tables(def_id)))
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@ -223,19 +226,24 @@ pub fn note_const_eval_err<'a, 'tcx>(
|
||||
|
||||
pub struct ConstContext<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tables: &'a ty::Tables<'tcx>,
|
||||
tables: Option<&'a ty::Tables<'tcx>>,
|
||||
fn_args: Option<DefIdMap<ConstVal>>
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self {
|
||||
ConstContext::with_tables(tcx, tcx.body_tables(body))
|
||||
let def_id = tcx.map.body_owner_def_id(body);
|
||||
ConstContext {
|
||||
tcx: tcx,
|
||||
tables: tcx.tables.borrow().get(&def_id).cloned(),
|
||||
fn_args: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::Tables<'tcx>) -> Self {
|
||||
ConstContext {
|
||||
tcx: tcx,
|
||||
tables: tables,
|
||||
tables: Some(tables),
|
||||
fn_args: None
|
||||
}
|
||||
}
|
||||
@ -436,7 +444,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
let ety = match ty_hint {
|
||||
ExprTypeChecked => {
|
||||
// After type-checking, expr_ty is guaranteed to succeed.
|
||||
Some(cx.tables.expr_ty(e))
|
||||
cx.tables.map(|tables| tables.expr_ty(e))
|
||||
}
|
||||
UncheckedExprHint(ty) => {
|
||||
// Use the type hint; it's not guaranteed to be right, but it's
|
||||
@ -447,7 +455,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
// This expression might not be type-checked, and we have no hint.
|
||||
// Try to query the context for a type anyway; we might get lucky
|
||||
// (for example, if the expression was imported from another crate).
|
||||
cx.tables.expr_ty_opt(e)
|
||||
cx.tables.and_then(|tables| tables.expr_ty_opt(e))
|
||||
}
|
||||
};
|
||||
let result = match e.node {
|
||||
@ -594,7 +602,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
let base_hint = if let ExprTypeChecked = ty_hint {
|
||||
ExprTypeChecked
|
||||
} else {
|
||||
match cx.tables.expr_ty_opt(&base) {
|
||||
match cx.tables.and_then(|tables| tables.expr_ty_opt(&base)) {
|
||||
Some(t) => UncheckedExprHint(t),
|
||||
None => ty_hint
|
||||
}
|
||||
@ -623,12 +631,18 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
hir::ExprPath(ref qpath) => {
|
||||
let def = cx.tables.qpath_def(qpath, e.id);
|
||||
let def = cx.tables.map(|tables| tables.qpath_def(qpath, e.id)).unwrap_or_else(|| {
|
||||
// There are no tables so we can only handle already-resolved HIR.
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.def,
|
||||
hir::QPath::TypeRelative(..) => Def::Err
|
||||
}
|
||||
});
|
||||
match def {
|
||||
Def::Const(def_id) |
|
||||
Def::AssociatedConst(def_id) => {
|
||||
let substs = if let ExprTypeChecked = ty_hint {
|
||||
Some(cx.tables.node_id_item_substs(e.id)
|
||||
Some(cx.tables.and_then(|tables| tables.node_id_item_substs(e.id))
|
||||
.unwrap_or_else(|| tcx.intern_substs(&[])))
|
||||
} else {
|
||||
None
|
||||
@ -638,7 +652,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
Some(ty) => ty_hint.checked_or(ty),
|
||||
None => ty_hint,
|
||||
};
|
||||
let cx = ConstContext::with_tables(tcx, tables);
|
||||
let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None };
|
||||
match cx.eval(expr, item_hint) {
|
||||
Ok(val) => val,
|
||||
Err(err) => {
|
||||
@ -652,7 +666,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
},
|
||||
Def::VariantCtor(variant_def, ..) => {
|
||||
if let Some((expr, tables)) = lookup_variant_by_id(tcx, variant_def) {
|
||||
let cx = ConstContext::with_tables(tcx, tables);
|
||||
let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None };
|
||||
match cx.eval(expr, ty_hint) {
|
||||
Ok(val) => val,
|
||||
Err(err) => {
|
||||
@ -903,10 +917,10 @@ fn infer<'a, 'tcx>(i: ConstInt,
|
||||
fn resolve_trait_associated_const<'a, 'tcx: 'a>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
trait_item_id: DefId,
|
||||
default_value: Option<(&'tcx Expr, &'a ty::Tables<'tcx>, Option<ty::Ty<'tcx>>)>,
|
||||
default_value: Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>, Option<ty::Ty<'tcx>>)>,
|
||||
trait_id: DefId,
|
||||
rcvr_substs: &'tcx Substs<'tcx>
|
||||
) -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>, Option<ty::Ty<'tcx>>)>
|
||||
) -> Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>, Option<ty::Ty<'tcx>>)>
|
||||
{
|
||||
let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs));
|
||||
debug!("resolve_trait_associated_const: trait_ref={:?}",
|
||||
|
@ -582,7 +582,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
|
||||
Some((const_expr, const_tables, _const_ty)) => {
|
||||
// Enter the inlined constant's tables temporarily.
|
||||
let old_tables = self.tables;
|
||||
self.tables = const_tables;
|
||||
self.tables = const_tables.expect("missing tables after typeck");
|
||||
let pat = self.lower_const_expr(const_expr, pat_id, span);
|
||||
self.tables = old_tables;
|
||||
return pat;
|
||||
|
@ -8,60 +8,31 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::hir::map as ast_map;
|
||||
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
|
||||
|
||||
use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange, NestedVisitorMap};
|
||||
|
||||
use cstore::CrateMetadata;
|
||||
use encoder::EncodeContext;
|
||||
use schema::*;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::{self, TyCtxt, Ty};
|
||||
|
||||
use syntax::ast;
|
||||
use rustc::ty;
|
||||
|
||||
use rustc_serialize::Encodable;
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct Ast<'tcx> {
|
||||
id_range: IdRange,
|
||||
body: Lazy<hir::Body>,
|
||||
side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>,
|
||||
pub body: Lazy<hir::Body>,
|
||||
pub tables: Lazy<ty::Tables<'tcx>>,
|
||||
pub nested_bodies: LazySeq<hir::Body>,
|
||||
pub rvalue_promotable_to_static: bool,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
enum TableEntry<'tcx> {
|
||||
TypeRelativeDef(Def),
|
||||
NodeType(Ty<'tcx>),
|
||||
ItemSubsts(ty::ItemSubsts<'tcx>),
|
||||
Adjustment(ty::adjustment::Adjustment<'tcx>),
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
pub fn encode_body(&mut self, body: hir::BodyId) -> Lazy<Ast<'tcx>> {
|
||||
let body = self.tcx.map.body(body);
|
||||
pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
|
||||
let body = self.tcx.map.body(body_id);
|
||||
let lazy_body = self.lazy(body);
|
||||
|
||||
let mut id_visitor = IdRangeComputingVisitor::new(&self.tcx.map);
|
||||
id_visitor.visit_body(body);
|
||||
|
||||
let body_pos = self.position();
|
||||
body.encode(self).unwrap();
|
||||
|
||||
let tables_pos = self.position();
|
||||
let tables_count = {
|
||||
let mut visitor = SideTableEncodingIdVisitor {
|
||||
tables: self.tcx.body_tables(body.id()),
|
||||
ecx: self,
|
||||
count: 0,
|
||||
};
|
||||
visitor.visit_body(body);
|
||||
visitor.count
|
||||
};
|
||||
let tables = self.tcx.body_tables(body_id);
|
||||
let lazy_tables = self.lazy(tables);
|
||||
|
||||
let nested_pos = self.position();
|
||||
let nested_count = {
|
||||
@ -77,45 +48,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
|
||||
|
||||
self.lazy(&Ast {
|
||||
id_range: id_visitor.result(),
|
||||
body: Lazy::with_position(body_pos),
|
||||
side_tables: LazySeq::with_position_and_length(tables_pos, tables_count),
|
||||
body: lazy_body,
|
||||
tables: lazy_tables,
|
||||
nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count),
|
||||
rvalue_promotable_to_static: rvalue_promotable_to_static
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct SideTableEncodingIdVisitor<'a, 'b: 'a, 'tcx: 'b> {
|
||||
ecx: &'a mut EncodeContext<'b, 'tcx>,
|
||||
tables: &'a ty::Tables<'tcx>,
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||
NestedVisitorMap::OnlyBodies(&self.ecx.tcx.map)
|
||||
}
|
||||
|
||||
fn visit_id(&mut self, id: ast::NodeId) {
|
||||
debug!("Encoding side tables for id {}", id);
|
||||
|
||||
let tables = self.tables;
|
||||
let mut encode = |entry: Option<TableEntry>| {
|
||||
if let Some(entry) = entry {
|
||||
(id, entry).encode(self.ecx).unwrap();
|
||||
self.count += 1;
|
||||
}
|
||||
};
|
||||
|
||||
encode(tables.type_relative_path_defs.get(&id).cloned()
|
||||
.map(TableEntry::TypeRelativeDef));
|
||||
encode(tables.node_types.get(&id).cloned().map(TableEntry::NodeType));
|
||||
encode(tables.item_substs.get(&id).cloned().map(TableEntry::ItemSubsts));
|
||||
encode(tables.adjustments.get(&id).cloned().map(TableEntry::Adjustment));
|
||||
}
|
||||
}
|
||||
|
||||
struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> {
|
||||
ecx: &'a mut EncodeContext<'b, 'tcx>,
|
||||
count: usize,
|
||||
@ -134,41 +74,3 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> {
|
||||
self.visit_body(body);
|
||||
}
|
||||
}
|
||||
|
||||
/// Decodes an item's body from its AST in the cdata's metadata and adds it to the
|
||||
/// ast-map.
|
||||
pub fn decode_body<'a, 'tcx>(cdata: &CrateMetadata,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
ast: Ast<'tcx>)
|
||||
-> &'tcx hir::Body {
|
||||
debug!("> Decoding inlined fn: {}", tcx.item_path_str(def_id));
|
||||
|
||||
let cnt = ast.id_range.max.as_usize() - ast.id_range.min.as_usize();
|
||||
let start = tcx.sess.reserve_node_ids(cnt);
|
||||
let id_ranges = [ast.id_range,
|
||||
IdRange {
|
||||
min: start,
|
||||
max: ast::NodeId::new(start.as_usize() + cnt),
|
||||
}];
|
||||
|
||||
for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) {
|
||||
match entry {
|
||||
TableEntry::TypeRelativeDef(def) => {
|
||||
tcx.tables.borrow_mut().type_relative_path_defs.insert(id, def);
|
||||
}
|
||||
TableEntry::NodeType(ty) => {
|
||||
tcx.tables.borrow_mut().node_types.insert(id, ty);
|
||||
}
|
||||
TableEntry::ItemSubsts(item_substs) => {
|
||||
tcx.tables.borrow_mut().item_substs.insert(id, item_substs);
|
||||
}
|
||||
TableEntry::Adjustment(adj) => {
|
||||
tcx.tables.borrow_mut().adjustments.insert(id, adj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let body = ast.body.decode((cdata, tcx, id_ranges));
|
||||
ast_map::map_decoded_body(&tcx.map, def_id, body, tcx.sess.next_node_id())
|
||||
}
|
||||
|
@ -97,7 +97,6 @@ pub struct CStore {
|
||||
used_link_args: RefCell<Vec<String>>,
|
||||
statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
|
||||
pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
|
||||
pub inlined_item_cache: RefCell<DefIdMap<Option<ast::NodeId>>>,
|
||||
pub visible_parent_map: RefCell<DefIdMap<DefId>>,
|
||||
}
|
||||
|
||||
@ -112,7 +111,6 @@ impl CStore {
|
||||
statically_included_foreign_items: RefCell::new(FxHashSet()),
|
||||
dllimport_foreign_items: RefCell::new(FxHashSet()),
|
||||
visible_parent_map: RefCell::new(FxHashMap()),
|
||||
inlined_item_cache: RefCell::new(FxHashMap()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -434,27 +434,14 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
def_id: DefId)
|
||||
-> Option<&'tcx hir::Body>
|
||||
{
|
||||
self.dep_graph.read(DepNode::MetaData(def_id));
|
||||
|
||||
if let Some(&cached) = self.inlined_item_cache.borrow().get(&def_id) {
|
||||
return cached.map(|root_id| {
|
||||
// Already inline
|
||||
debug!("maybe_get_item_body({}): already inline", tcx.item_path_str(def_id));
|
||||
tcx.map.expect_inlined_body(root_id)
|
||||
});
|
||||
if let Some(cached) = tcx.map.get_inlined_body(def_id) {
|
||||
return Some(cached);
|
||||
}
|
||||
|
||||
self.dep_graph.read(DepNode::MetaData(def_id));
|
||||
debug!("maybe_get_item_body({}): inlining item", tcx.item_path_str(def_id));
|
||||
|
||||
let inlined = self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index);
|
||||
|
||||
self.inlined_item_cache.borrow_mut().insert(def_id, inlined.map(|body| {
|
||||
let root_id = tcx.map.get_parent_node(body.value.id);
|
||||
assert_eq!(tcx.map.get_parent_node(root_id), root_id);
|
||||
root_id
|
||||
}));
|
||||
|
||||
inlined
|
||||
self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index)
|
||||
}
|
||||
|
||||
fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {
|
||||
|
@ -10,13 +10,11 @@
|
||||
|
||||
// Decoding metadata from a single crate's metadata
|
||||
|
||||
use astencode::decode_body;
|
||||
use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
|
||||
use schema::*;
|
||||
|
||||
use rustc::hir::map::{DefKey, DefPath, DefPathData};
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::IdRange;
|
||||
|
||||
use rustc::middle::cstore::LinkagePreference;
|
||||
use rustc::hir::def::{self, Def, CtorKind};
|
||||
@ -40,7 +38,7 @@ use std::u32;
|
||||
|
||||
use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
|
||||
use syntax::attr;
|
||||
use syntax::ast::{self, NodeId};
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
|
||||
use rustc_i128::{u128, i128};
|
||||
@ -50,8 +48,6 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
|
||||
cdata: Option<&'a CrateMetadata>,
|
||||
sess: Option<&'a Session>,
|
||||
tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
|
||||
from_id_range: IdRange,
|
||||
to_id_range: IdRange,
|
||||
|
||||
// Cache the last used filemap for translating spans as an optimization.
|
||||
last_filemap_index: usize,
|
||||
@ -67,18 +63,12 @@ pub trait Metadata<'a, 'tcx>: Copy {
|
||||
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { None }
|
||||
|
||||
fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
|
||||
let id_range = IdRange {
|
||||
min: NodeId::from_u32(u32::MIN),
|
||||
max: NodeId::from_u32(u32::MAX),
|
||||
};
|
||||
let tcx = self.tcx();
|
||||
DecodeContext {
|
||||
opaque: opaque::Decoder::new(self.raw_bytes(), pos),
|
||||
cdata: self.cdata(),
|
||||
sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
|
||||
tcx: tcx,
|
||||
from_id_range: id_range,
|
||||
to_id_range: id_range,
|
||||
last_filemap_index: 0,
|
||||
lazy_state: LazyState::NoNode,
|
||||
}
|
||||
@ -128,26 +118,6 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>
|
||||
}
|
||||
}
|
||||
|
||||
// HACK(eddyb) Only used by astencode to customize the from/to IdRange's.
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>, [IdRange; 2]) {
|
||||
fn raw_bytes(self) -> &'a [u8] {
|
||||
self.0.raw_bytes()
|
||||
}
|
||||
fn cdata(self) -> Option<&'a CrateMetadata> {
|
||||
Some(self.0)
|
||||
}
|
||||
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> {
|
||||
Some(self.1)
|
||||
}
|
||||
|
||||
fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
|
||||
let mut dcx = (self.0, self.1).decoder(pos);
|
||||
dcx.from_id_range = self.2[0];
|
||||
dcx.to_id_range = self.2[1];
|
||||
dcx
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx: 'a, T: Decodable> Lazy<T> {
|
||||
pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
|
||||
let mut dcx = meta.decoder(self.position);
|
||||
@ -256,28 +226,6 @@ impl<'a, 'tcx, T> SpecializedDecoder<LazySeq<T>> for DecodeContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<NodeId> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<NodeId, Self::Error> {
|
||||
let id = u32::decode(self)?;
|
||||
|
||||
// from_id_range should be non-empty
|
||||
assert!(!self.from_id_range.empty());
|
||||
// Make sure that translating the NodeId will actually yield a
|
||||
// meaningful result
|
||||
if !self.from_id_range.contains(NodeId::from_u32(id)) {
|
||||
bug!("NodeId::decode: {} out of DecodeContext range ({:?} -> {:?})",
|
||||
id,
|
||||
self.from_id_range,
|
||||
self.to_id_range);
|
||||
}
|
||||
|
||||
// Use wrapping arithmetic because otherwise it introduces control flow.
|
||||
// Maybe we should just have the control flow? -- aatch
|
||||
Ok(NodeId::from_u32(id.wrapping_sub(self.from_id_range.min.as_u32())
|
||||
.wrapping_add(self.to_id_range.min.as_u32())))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<CrateNum> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
|
||||
let cnum = CrateNum::from_u32(u32::decode(self)?);
|
||||
@ -829,7 +777,14 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
-> Option<&'tcx hir::Body> {
|
||||
if self.is_proc_macro(id) { return None; }
|
||||
self.entry(id).ast.map(|ast| {
|
||||
decode_body(self, tcx, self.local_def_id(id), ast.decode(self))
|
||||
let def_id = self.local_def_id(id);
|
||||
let ast = ast.decode(self);
|
||||
|
||||
let tables = ast.tables.decode((self, tcx));
|
||||
tcx.tables.borrow_mut().insert(def_id, tcx.alloc_tables(tables));
|
||||
|
||||
let body = ast.body.decode((self, tcx));
|
||||
tcx.map.intern_inlined_body(def_id, body)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ use rustc::mir::transform::MirSource;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::map::blocks::FnLikeNode;
|
||||
use rustc::infer::InferCtxt;
|
||||
@ -52,17 +51,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
MirSource::Promoted(..) => bug!(),
|
||||
};
|
||||
|
||||
let src_node_id = src.item_id();
|
||||
|
||||
// We are going to be accessing various tables
|
||||
// generated by TypeckItemBody; we also assume
|
||||
// that the body passes type check. These tables
|
||||
// are not individually tracked, so just register
|
||||
// a read here.
|
||||
let src_def_id = infcx.tcx.map.local_def_id(src_node_id);
|
||||
infcx.tcx.dep_graph.read(DepNode::TypeckItemBody(src_def_id));
|
||||
|
||||
let attrs = infcx.tcx.map.attrs(src_node_id);
|
||||
let attrs = infcx.tcx.map.attrs(src.item_id());
|
||||
|
||||
// Some functions always have overflow checks enabled,
|
||||
// however, they may not get codegen'd, depending on
|
||||
|
@ -95,8 +95,6 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
|
||||
let sym = ccx.symbol_map()
|
||||
.get(TransItem::Static(id))
|
||||
.expect("Local statics should always be in the SymbolMap");
|
||||
// Make sure that this is never executed for something inlined.
|
||||
assert!(!ccx.tcx().map.is_inlined_node_id(id));
|
||||
|
||||
let defined_in_current_codegen_unit = ccx.codegen_unit()
|
||||
.items()
|
||||
|
@ -1738,14 +1738,6 @@ pub fn create_global_var_metadata(cx: &CrateContext,
|
||||
|
||||
let tcx = cx.tcx();
|
||||
|
||||
// Don't create debuginfo for globals inlined from other crates. The other
|
||||
// crate should already contain debuginfo for it. More importantly, the
|
||||
// global might not even exist in un-inlined form anywhere which would lead
|
||||
// to a linker errors.
|
||||
if tcx.map.is_inlined_node_id(node_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let node_def_id = tcx.map.local_def_id(node_id);
|
||||
let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id);
|
||||
|
||||
|
@ -679,7 +679,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
|
||||
|
||||
fcx.regionck_fn(fn_id, body);
|
||||
fcx.resolve_type_vars_in_body(body, fn_id);
|
||||
fcx.resolve_type_vars_in_body(body);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1246,7 +1246,7 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
|
||||
fcx.select_all_obligations_or_error();
|
||||
|
||||
fcx.regionck_expr(body);
|
||||
fcx.resolve_type_vars_in_body(body, id);
|
||||
fcx.resolve_type_vars_in_body(body);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,12 @@ use rustc::hir;
|
||||
// Entry point
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn resolve_type_vars_in_body(&self,
|
||||
body: &'gcx hir::Body,
|
||||
item_id: ast::NodeId) {
|
||||
pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) {
|
||||
assert_eq!(self.writeback_errors.get(), false);
|
||||
|
||||
let item_id = self.tcx.map.body_owner(body.id());
|
||||
let item_def_id = self.tcx.map.local_def_id(item_id);
|
||||
|
||||
let mut wbcx = WritebackCx::new(self);
|
||||
for arg in &body.arguments {
|
||||
wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id);
|
||||
@ -49,6 +51,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
wbcx.visit_anon_types();
|
||||
wbcx.visit_deferred_obligations(item_id);
|
||||
wbcx.visit_type_nodes();
|
||||
|
||||
let tables = self.tcx.alloc_tables(wbcx.tables);
|
||||
self.tcx.tables.borrow_mut().insert(item_def_id, tables);
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,6 +68,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
||||
fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
|
||||
|
||||
tables: ty::Tables<'gcx>,
|
||||
|
||||
// Mapping from free regions of the function to the
|
||||
// early-bound versions of them, visible from the
|
||||
// outside of the function. This is needed by, and
|
||||
@ -74,6 +81,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
let mut wbcx = WritebackCx {
|
||||
fcx: fcx,
|
||||
tables: ty::Tables::empty(),
|
||||
free_to_bound_regions: DefIdMap()
|
||||
};
|
||||
|
||||
@ -113,10 +121,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
self.fcx.tcx
|
||||
}
|
||||
|
||||
fn write_ty_to_tcx(&self, node_id: ast::NodeId, ty: Ty<'gcx>) {
|
||||
debug!("write_ty_to_tcx({}, {:?})", node_id, ty);
|
||||
fn write_ty_to_tables(&mut self, node_id: ast::NodeId, ty: Ty<'gcx>) {
|
||||
debug!("write_ty_to_tables({}, {:?})", node_id, ty);
|
||||
assert!(!ty.needs_infer());
|
||||
self.tcx().tables.borrow_mut().node_types.insert(node_id, ty);
|
||||
self.tables.node_types.insert(node_id, ty);
|
||||
}
|
||||
|
||||
// Hacky hack: During type-checking, we treat *all* operators
|
||||
@ -238,13 +246,13 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
|
||||
let var_ty = self.fcx.local_ty(l.span, l.id);
|
||||
let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span));
|
||||
self.write_ty_to_tcx(l.id, var_ty);
|
||||
self.write_ty_to_tables(l.id, var_ty);
|
||||
intravisit::walk_local(self, l);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
fn visit_upvar_borrow_map(&self) {
|
||||
fn visit_upvar_borrow_map(&mut self) {
|
||||
if self.fcx.writeback_errors.get() {
|
||||
return;
|
||||
}
|
||||
@ -262,11 +270,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
debug!("Upvar capture for {:?} resolved to {:?}",
|
||||
upvar_id,
|
||||
new_upvar_capture);
|
||||
self.tcx()
|
||||
.tables
|
||||
.borrow_mut()
|
||||
.upvar_capture_map
|
||||
.insert(*upvar_id, new_upvar_capture);
|
||||
self.tables.upvar_capture_map.insert(*upvar_id, new_upvar_capture);
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,10 +340,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) {
|
||||
fn visit_node_id(&mut self, reason: ResolveReason, id: ast::NodeId) {
|
||||
// Export associated path extensions.
|
||||
if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&id) {
|
||||
self.tcx().tables.borrow_mut().type_relative_path_defs.insert(id, def);
|
||||
self.tables.type_relative_path_defs.insert(id, def);
|
||||
}
|
||||
|
||||
// Resolve any borrowings for the node with id `id`
|
||||
@ -348,7 +352,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
// Resolve the type of the node with id `id`
|
||||
let n_ty = self.fcx.node_ty(id);
|
||||
let n_ty = self.resolve(&n_ty, reason);
|
||||
self.write_ty_to_tcx(id, n_ty);
|
||||
self.write_ty_to_tables(id, n_ty);
|
||||
debug!("Node {} has type {:?}", id, n_ty);
|
||||
|
||||
// Resolve any substitutions
|
||||
@ -357,12 +361,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
if !item_substs.is_noop() {
|
||||
debug!("write_substs_to_tcx({}, {:?})", id, item_substs);
|
||||
assert!(!item_substs.substs.needs_infer());
|
||||
self.tcx().tables.borrow_mut().item_substs.insert(id, item_substs);
|
||||
self.tables.item_substs.insert(id, item_substs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
|
||||
fn visit_adjustments(&mut self, reason: ResolveReason, id: ast::NodeId) {
|
||||
let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&id);
|
||||
match adjustments {
|
||||
None => {
|
||||
@ -405,13 +409,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
target: self.resolve(&adjustment.target, reason)
|
||||
};
|
||||
debug!("Adjustments for node {}: {:?}", id, resolved_adjustment);
|
||||
self.tcx().tables.borrow_mut().adjustments.insert(
|
||||
id, resolved_adjustment);
|
||||
self.tables.adjustments.insert(id, resolved_adjustment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_method_map_entry(&self,
|
||||
fn visit_method_map_entry(&mut self,
|
||||
reason: ResolveReason,
|
||||
method_call: MethodCall) {
|
||||
// Resolve any method map entry
|
||||
@ -433,25 +436,25 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
|
||||
//NB(jroesch): We need to match twice to avoid a double borrow which would cause an ICE
|
||||
if let Some(method) = new_method {
|
||||
self.tcx().tables.borrow_mut().method_map.insert(method_call, method);
|
||||
self.tables.method_map.insert(method_call, method);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_liberated_fn_sigs(&self) {
|
||||
fn visit_liberated_fn_sigs(&mut self) {
|
||||
for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() {
|
||||
let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id));
|
||||
self.tcx().tables.borrow_mut().liberated_fn_sigs.insert(node_id, fn_sig.clone());
|
||||
self.tables.liberated_fn_sigs.insert(node_id, fn_sig.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_fru_field_types(&self) {
|
||||
fn visit_fru_field_types(&mut self) {
|
||||
for (&node_id, ftys) in self.fcx.tables.borrow().fru_field_types.iter() {
|
||||
let ftys = self.resolve(ftys, ResolvingFieldTypes(node_id));
|
||||
self.tcx().tables.borrow_mut().fru_field_types.insert(node_id, ftys);
|
||||
self.tables.fru_field_types.insert(node_id, ftys);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_deferred_obligations(&self, item_id: ast::NodeId) {
|
||||
fn visit_deferred_obligations(&mut self, item_id: ast::NodeId) {
|
||||
let deferred_obligations = self.fcx.deferred_obligations.borrow();
|
||||
let obligations: Vec<_> = deferred_obligations.iter().map(|obligation| {
|
||||
let reason = ResolvingDeferredObligation(obligation.cause.span);
|
||||
|
Loading…
Reference in New Issue
Block a user