rustc: store ty::Tables separately for each body (except closures').
This commit is contained in:
parent
85a4a192c7
commit
cde0a7e7e0
17 changed files with 223 additions and 477 deletions
|
@ -113,6 +113,7 @@ pub enum DepNode<D: Clone + Debug> {
|
||||||
SizedConstraint(D),
|
SizedConstraint(D),
|
||||||
AssociatedItemDefIds(D),
|
AssociatedItemDefIds(D),
|
||||||
InherentImpls(D),
|
InherentImpls(D),
|
||||||
|
Tables(D),
|
||||||
|
|
||||||
// The set of impls for a given trait. Ultimately, it would be
|
// The set of impls for a given trait. Ultimately, it would be
|
||||||
// nice to get more fine-grained here (e.g., to include a
|
// nice to get more fine-grained here (e.g., to include a
|
||||||
|
@ -162,6 +163,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||||
ItemSignature,
|
ItemSignature,
|
||||||
AssociatedItemDefIds,
|
AssociatedItemDefIds,
|
||||||
InherentImpls,
|
InherentImpls,
|
||||||
|
Tables,
|
||||||
TraitImpls,
|
TraitImpls,
|
||||||
ReprHints,
|
ReprHints,
|
||||||
}
|
}
|
||||||
|
@ -230,6 +232,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||||
SizedConstraint(ref d) => op(d).map(SizedConstraint),
|
SizedConstraint(ref d) => op(d).map(SizedConstraint),
|
||||||
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
|
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
|
||||||
InherentImpls(ref d) => op(d).map(InherentImpls),
|
InherentImpls(ref d) => op(d).map(InherentImpls),
|
||||||
|
Tables(ref d) => op(d).map(Tables),
|
||||||
TraitImpls(ref d) => op(d).map(TraitImpls),
|
TraitImpls(ref d) => op(d).map(TraitImpls),
|
||||||
TraitItems(ref d) => op(d).map(TraitItems),
|
TraitItems(ref d) => op(d).map(TraitItems),
|
||||||
ReprHints(ref d) => op(d).map(ReprHints),
|
ReprHints(ref d) => op(d).map(ReprHints),
|
||||||
|
|
|
@ -23,10 +23,6 @@ pub struct NodeCollector<'ast> {
|
||||||
pub(super) map: Vec<MapEntry<'ast>>,
|
pub(super) map: Vec<MapEntry<'ast>>,
|
||||||
/// The parent of this node
|
/// The parent of this node
|
||||||
pub parent_node: NodeId,
|
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> {
|
impl<'ast> NodeCollector<'ast> {
|
||||||
|
@ -35,30 +31,12 @@ impl<'ast> NodeCollector<'ast> {
|
||||||
krate: krate,
|
krate: krate,
|
||||||
map: vec![],
|
map: vec![],
|
||||||
parent_node: CRATE_NODE_ID,
|
parent_node: CRATE_NODE_ID,
|
||||||
ignore_nested_items: false
|
|
||||||
};
|
};
|
||||||
collector.insert_entry(CRATE_NODE_ID, RootCrate);
|
collector.insert_entry(CRATE_NODE_ID, RootCrate);
|
||||||
|
|
||||||
collector
|
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>) {
|
fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
|
||||||
debug!("ast_map: {:?} => {:?}", id, entry);
|
debug!("ast_map: {:?} => {:?}", id, entry);
|
||||||
let len = self.map.len();
|
let len = self.map.len();
|
||||||
|
@ -92,27 +70,19 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||||
|
|
||||||
fn visit_nested_item(&mut self, item: ItemId) {
|
fn visit_nested_item(&mut self, item: ItemId) {
|
||||||
debug!("visit_nested_item: {:?}", item);
|
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) {
|
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) {
|
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) {
|
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) {
|
fn visit_item(&mut self, i: &'ast Item) {
|
||||||
|
|
|
@ -25,28 +25,18 @@ use syntax::codemap::Spanned;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
use hir::*;
|
use hir::*;
|
||||||
use hir::intravisit::Visitor;
|
|
||||||
use hir::print::Nested;
|
use hir::print::Nested;
|
||||||
|
use util::nodemap::DefIdMap;
|
||||||
|
|
||||||
use arena::TypedArena;
|
use arena::TypedArena;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
pub mod blocks;
|
pub mod blocks;
|
||||||
mod collector;
|
mod collector;
|
||||||
mod def_collector;
|
mod def_collector;
|
||||||
pub mod definitions;
|
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)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Node<'ast> {
|
pub enum Node<'ast> {
|
||||||
NodeItem(&'ast Item),
|
NodeItem(&'ast Item),
|
||||||
|
@ -99,7 +89,6 @@ enum MapEntry<'ast> {
|
||||||
|
|
||||||
/// Roots for node trees.
|
/// Roots for node trees.
|
||||||
RootCrate,
|
RootCrate,
|
||||||
RootInlinedParent(&'ast InlinedItem)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> Clone for MapEntry<'ast> {
|
impl<'ast> Clone for MapEntry<'ast> {
|
||||||
|
@ -152,8 +141,7 @@ impl<'ast> MapEntry<'ast> {
|
||||||
EntryVisibility(id, _) => id,
|
EntryVisibility(id, _) => id,
|
||||||
|
|
||||||
NotPresent |
|
NotPresent |
|
||||||
RootCrate |
|
RootCrate => return None,
|
||||||
RootInlinedParent(_) => return None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +213,7 @@ impl<'ast> MapEntry<'ast> {
|
||||||
pub struct Forest {
|
pub struct Forest {
|
||||||
krate: Crate,
|
krate: Crate,
|
||||||
pub dep_graph: DepGraph,
|
pub dep_graph: DepGraph,
|
||||||
inlined_items: TypedArena<InlinedItem>
|
inlined_bodies: TypedArena<Body>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Forest {
|
impl Forest {
|
||||||
|
@ -233,7 +221,7 @@ impl Forest {
|
||||||
Forest {
|
Forest {
|
||||||
krate: krate,
|
krate: krate,
|
||||||
dep_graph: dep_graph.clone(),
|
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
|
/// Also, indexing is pretty quick when you've got a vector and
|
||||||
/// plain old integers.
|
/// plain old integers.
|
||||||
map: RefCell<Vec<MapEntry<'ast>>>,
|
map: Vec<MapEntry<'ast>>,
|
||||||
|
|
||||||
definitions: Definitions,
|
definitions: Definitions,
|
||||||
|
|
||||||
/// All NodeIds that are numerically greater or equal to this value come
|
/// Bodies inlined from other crates are cached here.
|
||||||
/// from inlined items.
|
inlined_bodies: RefCell<DefIdMap<&'ast Body>>,
|
||||||
local_node_id_watermark: NodeId,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> Map<'ast> {
|
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
|
/// Registers a read in the dependency graph of the AST node with
|
||||||
/// the given `id`. This needs to be called each time a public
|
/// the given `id`. This needs to be called each time a public
|
||||||
/// function returns the HIR for a node -- in other words, when it
|
/// 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> {
|
fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
|
||||||
let map = self.map.borrow();
|
|
||||||
let mut id = id0;
|
let mut id = id0;
|
||||||
if !self.is_inlined_node_id(id) {
|
let mut last_expr = None;
|
||||||
let mut last_expr = None;
|
loop {
|
||||||
loop {
|
let entry = self.map[id.as_usize()];
|
||||||
let entry = map[id.as_usize()];
|
match entry {
|
||||||
match entry {
|
EntryItem(..) |
|
||||||
EntryItem(..) |
|
EntryTraitItem(..) |
|
||||||
EntryTraitItem(..) |
|
EntryImplItem(..) => {
|
||||||
EntryImplItem(..) => {
|
if let Some(last_id) = last_expr {
|
||||||
if let Some(last_id) = last_expr {
|
// The body may have a separate dep node
|
||||||
// The body may have a separate dep node
|
if entry.is_body_owner(last_id) {
|
||||||
if entry.is_body_owner(last_id) {
|
let def_id = self.local_def_id(id);
|
||||||
let def_id = self.local_def_id(id);
|
return DepNode::HirBody(def_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return DepNode::Hir(self.local_def_id(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)
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} 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) =>
|
EntryVariant(p, v) => {
|
||||||
return DepNode::MetaData(parent.def_id),
|
id = p;
|
||||||
|
|
||||||
RootCrate =>
|
if last_expr.is_some() {
|
||||||
bug!("node {} has crate ancestor but is inlined", id0),
|
if v.node.disr_expr.map(|e| e.node_id) == last_expr {
|
||||||
|
// The enum parent holds both Hir and HirBody nodes.
|
||||||
NotPresent =>
|
let def_id = self.local_def_id(id);
|
||||||
bug!("node {} is inlined but not present in map", id0),
|
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 {
|
fn entry_count(&self) -> usize {
|
||||||
self.map.borrow().len()
|
self.map.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
|
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 {
|
pub fn krate(&self) -> &'ast Crate {
|
||||||
|
@ -483,7 +426,7 @@ impl<'ast> Map<'ast> {
|
||||||
/// for embedded constant expressions (e.g. `N` in `[T; N]`).
|
/// for embedded constant expressions (e.g. `N` in `[T; N]`).
|
||||||
pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
|
pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
|
||||||
let parent = self.get_parent_node(node_id);
|
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
|
parent
|
||||||
} else {
|
} else {
|
||||||
node_id
|
node_id
|
||||||
|
@ -644,11 +587,7 @@ impl<'ast> Map<'ast> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_parent_did(&self, id: NodeId) -> DefId {
|
pub fn get_parent_did(&self, id: NodeId) -> DefId {
|
||||||
let parent = self.get_parent(id);
|
self.local_def_id(self.get_parent(id))
|
||||||
match self.find_entry(parent) {
|
|
||||||
Some(RootInlinedParent(ii)) => ii.def_id,
|
|
||||||
_ => self.local_def_id(parent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
|
pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
|
||||||
|
@ -660,8 +599,6 @@ impl<'ast> Map<'ast> {
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Wrong but OK, because the only inlined foreign items are intrinsics.
|
|
||||||
Some(RootInlinedParent(_)) => Some(Abi::RustIntrinsic),
|
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
match abi {
|
match abi {
|
||||||
|
@ -737,11 +674,17 @@ impl<'ast> Map<'ast> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_inlined_body(&self, id: NodeId) -> &'ast Body {
|
pub fn get_inlined_body(&self, def_id: DefId) -> Option<&'ast Body> {
|
||||||
match self.find_entry(id) {
|
self.inlined_bodies.borrow().get(&def_id).map(|&body| {
|
||||||
Some(RootInlinedParent(inlined_item)) => &inlined_item.body,
|
self.dep_graph.read(DepNode::MetaData(def_id));
|
||||||
_ => bug!("expected inlined item, found {}", self.node_to_string(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.
|
/// 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(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),
|
||||||
|
|
||||||
Some(RootCrate) => self.forest.krate.span,
|
Some(RootCrate) => self.forest.krate.span,
|
||||||
Some(RootInlinedParent(parent)) => parent.body.value.span,
|
|
||||||
Some(NotPresent) | None => {
|
Some(NotPresent) | None => {
|
||||||
bug!("hir::map::Map::span: id not in map: {:?}", id)
|
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.);
|
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
|
||||||
}
|
}
|
||||||
|
|
||||||
let local_node_id_watermark = NodeId::new(map.len());
|
|
||||||
|
|
||||||
Map {
|
Map {
|
||||||
forest: forest,
|
forest: forest,
|
||||||
dep_graph: forest.dep_graph.clone(),
|
dep_graph: forest.dep_graph.clone(),
|
||||||
map: RefCell::new(map),
|
map: map,
|
||||||
definitions: definitions,
|
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`,
|
/// Identical to the `PpAnn` implementation for `hir::Crate`,
|
||||||
/// except it avoids creating a dependency on the whole crate.
|
/// except it avoids creating a dependency on the whole crate.
|
||||||
impl<'ast> print::PpAnn for Map<'ast> {
|
impl<'ast> print::PpAnn for Map<'ast> {
|
||||||
|
|
|
@ -65,6 +65,7 @@ pub struct GlobalArenas<'tcx> {
|
||||||
trait_def: TypedArena<ty::TraitDef>,
|
trait_def: TypedArena<ty::TraitDef>,
|
||||||
adt_def: TypedArena<ty::AdtDef>,
|
adt_def: TypedArena<ty::AdtDef>,
|
||||||
mir: TypedArena<RefCell<Mir<'tcx>>>,
|
mir: TypedArena<RefCell<Mir<'tcx>>>,
|
||||||
|
tables: TypedArena<ty::Tables<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> GlobalArenas<'tcx> {
|
impl<'tcx> GlobalArenas<'tcx> {
|
||||||
|
@ -75,6 +76,7 @@ impl<'tcx> GlobalArenas<'tcx> {
|
||||||
trait_def: TypedArena::new(),
|
trait_def: TypedArena::new(),
|
||||||
adt_def: TypedArena::new(),
|
adt_def: TypedArena::new(),
|
||||||
mir: TypedArena::new(),
|
mir: TypedArena::new(),
|
||||||
|
tables: TypedArena::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,6 +191,7 @@ pub struct CommonTypes<'tcx> {
|
||||||
pub err: Ty<'tcx>,
|
pub err: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct Tables<'tcx> {
|
pub struct Tables<'tcx> {
|
||||||
/// Resolved definitions for `<T>::X` associated paths.
|
/// Resolved definitions for `<T>::X` associated paths.
|
||||||
pub type_relative_path_defs: NodeMap<Def>,
|
pub type_relative_path_defs: NodeMap<Def>,
|
||||||
|
@ -399,7 +402,7 @@ pub struct GlobalCtxt<'tcx> {
|
||||||
free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
|
free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
|
||||||
// FIXME: jroesch make this a refcell
|
// 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"
|
/// Maps from a trait item to the trait item "descriptor"
|
||||||
pub associated_items: RefCell<DepTrackingMap<maps::AssociatedItems<'tcx>>>,
|
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))
|
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 {
|
pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
|
||||||
self.global_arenas.trait_def.alloc(def)
|
self.global_arenas.trait_def.alloc(def)
|
||||||
}
|
}
|
||||||
|
@ -749,7 +756,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
variance_computed: Cell::new(false),
|
variance_computed: Cell::new(false),
|
||||||
sess: s,
|
sess: s,
|
||||||
trait_map: resolutions.trait_map,
|
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())),
|
impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||||
trait_defs: 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())),
|
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! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }
|
||||||
dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind }
|
dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind }
|
||||||
dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> }
|
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
|
/// needed to add to the side tables. Thus to disambiguate
|
||||||
/// we also keep track of whether there's an adjustment in
|
/// we also keep track of whether there's an adjustment in
|
||||||
/// our key.
|
/// our key.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub struct MethodCall {
|
pub struct MethodCall {
|
||||||
pub expr_id: NodeId,
|
pub expr_id: NodeId,
|
||||||
pub autoderef: u32
|
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
|
/// 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
|
/// the original var id (that is, the root variable that is referenced
|
||||||
/// by the upvar) and the id of the closure expression.
|
/// 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 struct UpvarId {
|
||||||
pub var_id: NodeId,
|
pub var_id: NodeId,
|
||||||
pub closure_expr_id: NodeId,
|
pub closure_expr_id: NodeId,
|
||||||
|
@ -1917,19 +1917,30 @@ impl BorrowKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn tables(self) -> Ref<'a, Tables<'gcx>> {
|
pub fn body_tables(self, body: hir::BodyId) -> &'gcx Tables<'gcx> {
|
||||||
self.tables.borrow()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn body_tables(self, body: hir::BodyId) -> &'a Tables<'gcx> {
|
|
||||||
self.item_tables(self.map.body_owner_def_id(body))
|
self.item_tables(self.map.body_owner_def_id(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn item_tables(self, _def_id: DefId) -> &'a Tables<'gcx> {
|
pub fn item_tables(self, def_id: DefId) -> &'gcx Tables<'gcx> {
|
||||||
// HACK(eddyb) temporarily work around RefCell until proper per-body tables
|
self.tables.memoize(def_id, || {
|
||||||
unsafe {
|
if def_id.is_local() {
|
||||||
mem::transmute::<&Tables, &Tables>(&self.tables())
|
// 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 {
|
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>,
|
fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
variant_def: DefId)
|
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) {
|
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);
|
let enum_node_id = tcx.map.get_parent(variant_node_id);
|
||||||
if let Some(ast_map::NodeItem(it)) = tcx.map.find(enum_node_id) {
|
if let Some(ast_map::NodeItem(it)) = tcx.map.find(enum_node_id) {
|
||||||
match it.node {
|
if let hir::ItemEnum(ref edef, _) = it.node {
|
||||||
hir::ItemEnum(hir::EnumDef { ref variants }, _) => {
|
for variant in &edef.variants {
|
||||||
for variant in variants {
|
if variant.node.data.id() == variant_node_id {
|
||||||
if variant.node.data.id() == variant_node_id {
|
return variant.node.disr_expr.map(|e| {
|
||||||
return variant.node.disr_expr.map(|e| {
|
let def_id = tcx.map.body_owner_def_id(e);
|
||||||
(&tcx.map.body(e).value, tcx.body_tables(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>,
|
pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
substs: Option<&'tcx Substs<'tcx>>)
|
substs: Option<&'tcx Substs<'tcx>>)
|
||||||
-> Option<(&'tcx Expr, &'a ty::Tables<'tcx>,
|
-> Option<(&'tcx Expr,
|
||||||
|
Option<&'a ty::Tables<'tcx>>,
|
||||||
Option<ty::Ty<'tcx>>)> {
|
Option<ty::Ty<'tcx>>)> {
|
||||||
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
|
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
|
||||||
match tcx.map.find(node_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 {
|
Some(ast_map::NodeImplItem(&hir::ImplItem {
|
||||||
node: hir::ImplItemKind::Const(ref ty, body), ..
|
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)))
|
tcx.ast_ty_to_prim_ty(ty)))
|
||||||
}
|
}
|
||||||
Some(ast_map::NodeTraitItem(ti)) => match ti.node {
|
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.get_parent(node_id);
|
||||||
let trait_id = tcx.map.local_def_id(trait_id);
|
let trait_id = tcx.map.local_def_id(trait_id);
|
||||||
let default_value = default.map(|body| {
|
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))
|
tcx.ast_ty_to_prim_ty(ty))
|
||||||
});
|
});
|
||||||
resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs)
|
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 {
|
} else {
|
||||||
let expr_tables_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| {
|
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)))
|
Some(tcx.sess.cstore.item_type(tcx, def_id)))
|
||||||
});
|
});
|
||||||
match tcx.sess.cstore.describe_def(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)
|
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) {
|
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| {
|
FnLikeNode::from_node(tcx.map.get(node_id)).and_then(|fn_like| {
|
||||||
if fn_like.constness() == hir::Constness::Const {
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -165,7 +168,7 @@ fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
|
||||||
} else {
|
} else {
|
||||||
if tcx.sess.cstore.is_const_fn(def_id) {
|
if tcx.sess.cstore.is_const_fn(def_id) {
|
||||||
tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| {
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -223,19 +226,24 @@ pub fn note_const_eval_err<'a, 'tcx>(
|
||||||
|
|
||||||
pub struct ConstContext<'a, 'tcx: 'a> {
|
pub struct ConstContext<'a, 'tcx: 'a> {
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
tables: &'a ty::Tables<'tcx>,
|
tables: Option<&'a ty::Tables<'tcx>>,
|
||||||
fn_args: Option<DefIdMap<ConstVal>>
|
fn_args: Option<DefIdMap<ConstVal>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
||||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self {
|
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 {
|
pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::Tables<'tcx>) -> Self {
|
||||||
ConstContext {
|
ConstContext {
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
tables: tables,
|
tables: Some(tables),
|
||||||
fn_args: None
|
fn_args: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,7 +444,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||||
let ety = match ty_hint {
|
let ety = match ty_hint {
|
||||||
ExprTypeChecked => {
|
ExprTypeChecked => {
|
||||||
// After type-checking, expr_ty is guaranteed to succeed.
|
// 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) => {
|
UncheckedExprHint(ty) => {
|
||||||
// Use the type hint; it's not guaranteed to be right, but it's
|
// 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.
|
// 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
|
// Try to query the context for a type anyway; we might get lucky
|
||||||
// (for example, if the expression was imported from another crate).
|
// (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 {
|
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 {
|
let base_hint = if let ExprTypeChecked = ty_hint {
|
||||||
ExprTypeChecked
|
ExprTypeChecked
|
||||||
} else {
|
} else {
|
||||||
match cx.tables.expr_ty_opt(&base) {
|
match cx.tables.and_then(|tables| tables.expr_ty_opt(&base)) {
|
||||||
Some(t) => UncheckedExprHint(t),
|
Some(t) => UncheckedExprHint(t),
|
||||||
None => ty_hint
|
None => ty_hint
|
||||||
}
|
}
|
||||||
|
@ -623,12 +631,18 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprPath(ref qpath) => {
|
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 {
|
match def {
|
||||||
Def::Const(def_id) |
|
Def::Const(def_id) |
|
||||||
Def::AssociatedConst(def_id) => {
|
Def::AssociatedConst(def_id) => {
|
||||||
let substs = if let ExprTypeChecked = ty_hint {
|
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(&[])))
|
.unwrap_or_else(|| tcx.intern_substs(&[])))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -638,7 +652,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||||
Some(ty) => ty_hint.checked_or(ty),
|
Some(ty) => ty_hint.checked_or(ty),
|
||||||
None => ty_hint,
|
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) {
|
match cx.eval(expr, item_hint) {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -652,7 +666,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||||
},
|
},
|
||||||
Def::VariantCtor(variant_def, ..) => {
|
Def::VariantCtor(variant_def, ..) => {
|
||||||
if let Some((expr, tables)) = lookup_variant_by_id(tcx, 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) {
|
match cx.eval(expr, ty_hint) {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -903,10 +917,10 @@ fn infer<'a, 'tcx>(i: ConstInt,
|
||||||
fn resolve_trait_associated_const<'a, 'tcx: 'a>(
|
fn resolve_trait_associated_const<'a, 'tcx: 'a>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
trait_item_id: DefId,
|
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,
|
trait_id: DefId,
|
||||||
rcvr_substs: &'tcx Substs<'tcx>
|
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));
|
let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs));
|
||||||
debug!("resolve_trait_associated_const: trait_ref={:?}",
|
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)) => {
|
Some((const_expr, const_tables, _const_ty)) => {
|
||||||
// Enter the inlined constant's tables temporarily.
|
// Enter the inlined constant's tables temporarily.
|
||||||
let old_tables = self.tables;
|
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);
|
let pat = self.lower_const_expr(const_expr, pat_id, span);
|
||||||
self.tables = old_tables;
|
self.tables = old_tables;
|
||||||
return pat;
|
return pat;
|
||||||
|
|
|
@ -8,60 +8,31 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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 encoder::EncodeContext;
|
||||||
use schema::*;
|
use schema::*;
|
||||||
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def::Def;
|
use rustc::ty;
|
||||||
use rustc::hir::def_id::DefId;
|
|
||||||
use rustc::ty::{self, TyCtxt, Ty};
|
|
||||||
|
|
||||||
use syntax::ast;
|
|
||||||
|
|
||||||
use rustc_serialize::Encodable;
|
use rustc_serialize::Encodable;
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct Ast<'tcx> {
|
pub struct Ast<'tcx> {
|
||||||
id_range: IdRange,
|
pub body: Lazy<hir::Body>,
|
||||||
body: Lazy<hir::Body>,
|
pub tables: Lazy<ty::Tables<'tcx>>,
|
||||||
side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>,
|
|
||||||
pub nested_bodies: LazySeq<hir::Body>,
|
pub nested_bodies: LazySeq<hir::Body>,
|
||||||
pub rvalue_promotable_to_static: bool,
|
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> {
|
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
pub fn encode_body(&mut self, body: hir::BodyId) -> Lazy<Ast<'tcx>> {
|
pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
|
||||||
let body = self.tcx.map.body(body);
|
let body = self.tcx.map.body(body_id);
|
||||||
|
let lazy_body = self.lazy(body);
|
||||||
|
|
||||||
let mut id_visitor = IdRangeComputingVisitor::new(&self.tcx.map);
|
let tables = self.tcx.body_tables(body_id);
|
||||||
id_visitor.visit_body(body);
|
let lazy_tables = self.lazy(tables);
|
||||||
|
|
||||||
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 nested_pos = self.position();
|
let nested_pos = self.position();
|
||||||
let nested_count = {
|
let nested_count = {
|
||||||
|
@ -77,45 +48,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
|
self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
|
||||||
|
|
||||||
self.lazy(&Ast {
|
self.lazy(&Ast {
|
||||||
id_range: id_visitor.result(),
|
body: lazy_body,
|
||||||
body: Lazy::with_position(body_pos),
|
tables: lazy_tables,
|
||||||
side_tables: LazySeq::with_position_and_length(tables_pos, tables_count),
|
|
||||||
nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count),
|
nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count),
|
||||||
rvalue_promotable_to_static: rvalue_promotable_to_static
|
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> {
|
struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> {
|
||||||
ecx: &'a mut EncodeContext<'b, 'tcx>,
|
ecx: &'a mut EncodeContext<'b, 'tcx>,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
@ -134,41 +74,3 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> {
|
||||||
self.visit_body(body);
|
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>>,
|
used_link_args: RefCell<Vec<String>>,
|
||||||
statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
|
statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
|
||||||
pub dllimport_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>>,
|
pub visible_parent_map: RefCell<DefIdMap<DefId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +111,6 @@ impl CStore {
|
||||||
statically_included_foreign_items: RefCell::new(FxHashSet()),
|
statically_included_foreign_items: RefCell::new(FxHashSet()),
|
||||||
dllimport_foreign_items: RefCell::new(FxHashSet()),
|
dllimport_foreign_items: RefCell::new(FxHashSet()),
|
||||||
visible_parent_map: RefCell::new(FxHashMap()),
|
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)
|
def_id: DefId)
|
||||||
-> Option<&'tcx hir::Body>
|
-> Option<&'tcx hir::Body>
|
||||||
{
|
{
|
||||||
self.dep_graph.read(DepNode::MetaData(def_id));
|
if let Some(cached) = tcx.map.get_inlined_body(def_id) {
|
||||||
|
return Some(cached);
|
||||||
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)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.dep_graph.read(DepNode::MetaData(def_id));
|
||||||
debug!("maybe_get_item_body({}): inlining item", tcx.item_path_str(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.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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {
|
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
|
// Decoding metadata from a single crate's metadata
|
||||||
|
|
||||||
use astencode::decode_body;
|
|
||||||
use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
|
use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
|
||||||
use schema::*;
|
use schema::*;
|
||||||
|
|
||||||
use rustc::hir::map::{DefKey, DefPath, DefPathData};
|
use rustc::hir::map::{DefKey, DefPath, DefPathData};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::intravisit::IdRange;
|
|
||||||
|
|
||||||
use rustc::middle::cstore::LinkagePreference;
|
use rustc::middle::cstore::LinkagePreference;
|
||||||
use rustc::hir::def::{self, Def, CtorKind};
|
use rustc::hir::def::{self, Def, CtorKind};
|
||||||
|
@ -40,7 +38,7 @@ use std::u32;
|
||||||
|
|
||||||
use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
|
use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::ast::{self, NodeId};
|
use syntax::ast;
|
||||||
use syntax::codemap;
|
use syntax::codemap;
|
||||||
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
|
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
|
||||||
use rustc_i128::{u128, i128};
|
use rustc_i128::{u128, i128};
|
||||||
|
@ -50,8 +48,6 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
|
||||||
cdata: Option<&'a CrateMetadata>,
|
cdata: Option<&'a CrateMetadata>,
|
||||||
sess: Option<&'a Session>,
|
sess: Option<&'a Session>,
|
||||||
tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
|
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.
|
// Cache the last used filemap for translating spans as an optimization.
|
||||||
last_filemap_index: usize,
|
last_filemap_index: usize,
|
||||||
|
@ -67,18 +63,12 @@ pub trait Metadata<'a, 'tcx>: Copy {
|
||||||
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { None }
|
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { None }
|
||||||
|
|
||||||
fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
|
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();
|
let tcx = self.tcx();
|
||||||
DecodeContext {
|
DecodeContext {
|
||||||
opaque: opaque::Decoder::new(self.raw_bytes(), pos),
|
opaque: opaque::Decoder::new(self.raw_bytes(), pos),
|
||||||
cdata: self.cdata(),
|
cdata: self.cdata(),
|
||||||
sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
|
sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
from_id_range: id_range,
|
|
||||||
to_id_range: id_range,
|
|
||||||
last_filemap_index: 0,
|
last_filemap_index: 0,
|
||||||
lazy_state: LazyState::NoNode,
|
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> {
|
impl<'a, 'tcx: 'a, T: Decodable> Lazy<T> {
|
||||||
pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
|
pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
|
||||||
let mut dcx = meta.decoder(self.position);
|
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> {
|
impl<'a, 'tcx> SpecializedDecoder<CrateNum> for DecodeContext<'a, 'tcx> {
|
||||||
fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
|
fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
|
||||||
let cnum = CrateNum::from_u32(u32::decode(self)?);
|
let cnum = CrateNum::from_u32(u32::decode(self)?);
|
||||||
|
@ -829,7 +777,14 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
-> Option<&'tcx hir::Body> {
|
-> Option<&'tcx hir::Body> {
|
||||||
if self.is_proc_macro(id) { return None; }
|
if self.is_proc_macro(id) { return None; }
|
||||||
self.entry(id).ast.map(|ast| {
|
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::middle::const_val::ConstVal;
|
||||||
use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err};
|
use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err};
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use rustc::dep_graph::DepNode;
|
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::map::blocks::FnLikeNode;
|
use rustc::hir::map::blocks::FnLikeNode;
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
|
@ -52,17 +51,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
MirSource::Promoted(..) => bug!(),
|
MirSource::Promoted(..) => bug!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let src_node_id = src.item_id();
|
let attrs = infcx.tcx.map.attrs(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);
|
|
||||||
|
|
||||||
// Some functions always have overflow checks enabled,
|
// Some functions always have overflow checks enabled,
|
||||||
// however, they may not get codegen'd, depending on
|
// 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()
|
let sym = ccx.symbol_map()
|
||||||
.get(TransItem::Static(id))
|
.get(TransItem::Static(id))
|
||||||
.expect("Local statics should always be in the SymbolMap");
|
.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()
|
let defined_in_current_codegen_unit = ccx.codegen_unit()
|
||||||
.items()
|
.items()
|
||||||
|
|
|
@ -1738,14 +1738,6 @@ pub fn create_global_var_metadata(cx: &CrateContext,
|
||||||
|
|
||||||
let tcx = cx.tcx();
|
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 node_def_id = tcx.map.local_def_id(node_id);
|
||||||
let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_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.select_all_obligations_or_error(); // Casts can introduce new obligations.
|
||||||
|
|
||||||
fcx.regionck_fn(fn_id, body);
|
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.select_all_obligations_or_error();
|
||||||
|
|
||||||
fcx.regionck_expr(body);
|
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
|
// Entry point
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn resolve_type_vars_in_body(&self,
|
pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) {
|
||||||
body: &'gcx hir::Body,
|
|
||||||
item_id: ast::NodeId) {
|
|
||||||
assert_eq!(self.writeback_errors.get(), false);
|
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);
|
let mut wbcx = WritebackCx::new(self);
|
||||||
for arg in &body.arguments {
|
for arg in &body.arguments {
|
||||||
wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id);
|
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_anon_types();
|
||||||
wbcx.visit_deferred_obligations(item_id);
|
wbcx.visit_deferred_obligations(item_id);
|
||||||
wbcx.visit_type_nodes();
|
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> {
|
struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
||||||
fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
|
fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
|
||||||
|
|
||||||
|
tables: ty::Tables<'gcx>,
|
||||||
|
|
||||||
// Mapping from free regions of the function to the
|
// Mapping from free regions of the function to the
|
||||||
// early-bound versions of them, visible from the
|
// early-bound versions of them, visible from the
|
||||||
// outside of the function. This is needed by, and
|
// 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> {
|
fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
let mut wbcx = WritebackCx {
|
let mut wbcx = WritebackCx {
|
||||||
fcx: fcx,
|
fcx: fcx,
|
||||||
|
tables: ty::Tables::empty(),
|
||||||
free_to_bound_regions: DefIdMap()
|
free_to_bound_regions: DefIdMap()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,10 +121,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
self.fcx.tcx
|
self.fcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_ty_to_tcx(&self, node_id: ast::NodeId, ty: Ty<'gcx>) {
|
fn write_ty_to_tables(&mut self, node_id: ast::NodeId, ty: Ty<'gcx>) {
|
||||||
debug!("write_ty_to_tcx({}, {:?})", node_id, ty);
|
debug!("write_ty_to_tables({}, {:?})", node_id, ty);
|
||||||
assert!(!ty.needs_infer());
|
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
|
// 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.fcx.local_ty(l.span, l.id);
|
||||||
let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span));
|
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);
|
intravisit::walk_local(self, l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
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() {
|
if self.fcx.writeback_errors.get() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -262,11 +270,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
debug!("Upvar capture for {:?} resolved to {:?}",
|
debug!("Upvar capture for {:?} resolved to {:?}",
|
||||||
upvar_id,
|
upvar_id,
|
||||||
new_upvar_capture);
|
new_upvar_capture);
|
||||||
self.tcx()
|
self.tables.upvar_capture_map.insert(*upvar_id, new_upvar_capture);
|
||||||
.tables
|
|
||||||
.borrow_mut()
|
|
||||||
.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.
|
// Export associated path extensions.
|
||||||
if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&id) {
|
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`
|
// 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`
|
// Resolve the type of the node with id `id`
|
||||||
let n_ty = self.fcx.node_ty(id);
|
let n_ty = self.fcx.node_ty(id);
|
||||||
let n_ty = self.resolve(&n_ty, reason);
|
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);
|
debug!("Node {} has type {:?}", id, n_ty);
|
||||||
|
|
||||||
// Resolve any substitutions
|
// Resolve any substitutions
|
||||||
|
@ -357,12 +361,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
if !item_substs.is_noop() {
|
if !item_substs.is_noop() {
|
||||||
debug!("write_substs_to_tcx({}, {:?})", id, item_substs);
|
debug!("write_substs_to_tcx({}, {:?})", id, item_substs);
|
||||||
assert!(!item_substs.substs.needs_infer());
|
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);
|
let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&id);
|
||||||
match adjustments {
|
match adjustments {
|
||||||
None => {
|
None => {
|
||||||
|
@ -405,13 +409,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
target: self.resolve(&adjustment.target, reason)
|
target: self.resolve(&adjustment.target, reason)
|
||||||
};
|
};
|
||||||
debug!("Adjustments for node {}: {:?}", id, resolved_adjustment);
|
debug!("Adjustments for node {}: {:?}", id, resolved_adjustment);
|
||||||
self.tcx().tables.borrow_mut().adjustments.insert(
|
self.tables.adjustments.insert(id, resolved_adjustment);
|
||||||
id, resolved_adjustment);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_method_map_entry(&self,
|
fn visit_method_map_entry(&mut self,
|
||||||
reason: ResolveReason,
|
reason: ResolveReason,
|
||||||
method_call: MethodCall) {
|
method_call: MethodCall) {
|
||||||
// Resolve any method map entry
|
// 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
|
//NB(jroesch): We need to match twice to avoid a double borrow which would cause an ICE
|
||||||
if let Some(method) = new_method {
|
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() {
|
for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() {
|
||||||
let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id));
|
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() {
|
for (&node_id, ftys) in self.fcx.tables.borrow().fru_field_types.iter() {
|
||||||
let ftys = self.resolve(ftys, ResolvingFieldTypes(node_id));
|
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 deferred_obligations = self.fcx.deferred_obligations.borrow();
|
||||||
let obligations: Vec<_> = deferred_obligations.iter().map(|obligation| {
|
let obligations: Vec<_> = deferred_obligations.iter().map(|obligation| {
|
||||||
let reason = ResolvingDeferredObligation(obligation.cause.span);
|
let reason = ResolvingDeferredObligation(obligation.cause.span);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue