mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 05:26:47 +00:00
Auto merge of #31304 - nikomatsakis:incr-comp-read-from-hir-map, r=michaelwoerister
This change also modifies the dep graph infrastructure to keep track of the number of active tasks, so that even if we are not building the full dep-graph, we still get assertions when there is no active task and one does something that would add a read/write edge. This is particularly helpful since, if the assertions are *not* active, you wind up with the error happening in the message processing thread, which is too late to know the correct backtrace. ~~Before landing, I need to do some performance measurements. Those are underway.~~ See measurements below. No real effect on time. r? @michaelwoerister
This commit is contained in:
commit
34af2de409
@ -40,8 +40,21 @@ pub enum DepNode {
|
||||
Hir(DefId),
|
||||
|
||||
// Represents different phases in the compiler.
|
||||
CrateReader,
|
||||
CollectLanguageItems,
|
||||
CheckStaticRecursion,
|
||||
ResolveLifetimes,
|
||||
RegionResolveCrate,
|
||||
CheckLoops,
|
||||
PluginRegistrar,
|
||||
StabilityIndex,
|
||||
CollectItem(DefId),
|
||||
Coherence,
|
||||
EffectCheck,
|
||||
Liveness,
|
||||
Resolve,
|
||||
EntryPoint,
|
||||
CheckEntryFn,
|
||||
CoherenceCheckImpl(DefId),
|
||||
CoherenceOverlapCheck(DefId),
|
||||
CoherenceOverlapCheckSpecial(DefId),
|
||||
@ -116,6 +129,13 @@ impl DepGraph {
|
||||
}
|
||||
}
|
||||
|
||||
/// True if we are actually building a dep-graph. If this returns false,
|
||||
/// then the other methods on this `DepGraph` will have no net effect.
|
||||
#[inline]
|
||||
pub fn enabled(&self) -> bool {
|
||||
self.data.enabled()
|
||||
}
|
||||
|
||||
pub fn query(&self) -> DepGraphQuery {
|
||||
self.data.query()
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
//! allocated (and both have a fairly large capacity).
|
||||
|
||||
use rustc_data_structures::veccell::VecCell;
|
||||
use std::cell::Cell;
|
||||
use std::sync::mpsc::{self, Sender, Receiver};
|
||||
use std::thread;
|
||||
|
||||
@ -39,6 +40,13 @@ pub enum DepMessage {
|
||||
pub struct DepGraphThreadData {
|
||||
enabled: bool,
|
||||
|
||||
// Local counter that just tracks how many tasks are pushed onto the
|
||||
// stack, so that we still get an error in the case where one is
|
||||
// missing. If dep-graph construction is enabled, we'd get the same
|
||||
// error when processing tasks later on, but that's annoying because
|
||||
// it lacks precision about the source of the error.
|
||||
tasks_pushed: Cell<usize>,
|
||||
|
||||
// current buffer, where we accumulate messages
|
||||
messages: VecCell<DepMessage>,
|
||||
|
||||
@ -59,11 +67,14 @@ impl DepGraphThreadData {
|
||||
let (tx1, rx1) = mpsc::channel();
|
||||
let (tx2, rx2) = mpsc::channel();
|
||||
let (txq, rxq) = mpsc::channel();
|
||||
|
||||
if enabled {
|
||||
thread::spawn(move || main(rx1, tx2, txq));
|
||||
}
|
||||
|
||||
DepGraphThreadData {
|
||||
enabled: enabled,
|
||||
tasks_pushed: Cell::new(0),
|
||||
messages: VecCell::with_capacity(INITIAL_CAPACITY),
|
||||
swap_in: rx2,
|
||||
swap_out: tx1,
|
||||
@ -71,6 +82,11 @@ impl DepGraphThreadData {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
|
||||
/// Sends the current batch of messages to the thread. Installs a
|
||||
/// new vector of messages.
|
||||
fn swap(&self) {
|
||||
@ -100,12 +116,39 @@ impl DepGraphThreadData {
|
||||
/// the buffer is full, this may swap.)
|
||||
#[inline]
|
||||
pub fn enqueue(&self, message: DepMessage) {
|
||||
if self.enabled {
|
||||
let len = self.messages.push(message);
|
||||
if len == INITIAL_CAPACITY {
|
||||
self.swap();
|
||||
}
|
||||
// Regardless of whether dep graph construction is enabled, we
|
||||
// still want to check that we always have a valid task on the
|
||||
// stack when a read/write/etc event occurs.
|
||||
match message {
|
||||
DepMessage::Read(_) | DepMessage::Write(_) =>
|
||||
if self.tasks_pushed.get() == 0 {
|
||||
self.invalid_message("read/write but no current task")
|
||||
},
|
||||
DepMessage::PushTask(_) | DepMessage::PushIgnore =>
|
||||
self.tasks_pushed.set(self.tasks_pushed.get() + 1),
|
||||
DepMessage::PopTask(_) | DepMessage::PopIgnore =>
|
||||
self.tasks_pushed.set(self.tasks_pushed.get() - 1),
|
||||
DepMessage::Query =>
|
||||
(),
|
||||
}
|
||||
|
||||
if self.enabled {
|
||||
self.enqueue_enabled(message);
|
||||
}
|
||||
}
|
||||
|
||||
// Outline this fn since I expect it may want to be inlined
|
||||
// separately.
|
||||
fn enqueue_enabled(&self, message: DepMessage) {
|
||||
let len = self.messages.push(message);
|
||||
if len == INITIAL_CAPACITY {
|
||||
self.swap();
|
||||
}
|
||||
}
|
||||
|
||||
// Outline this too.
|
||||
fn invalid_message(&self, string: &str) {
|
||||
panic!("{}; see src/librustc/dep_graph/README.md for more information", string)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,7 @@ impl<'ast> NodeCollector<'ast> {
|
||||
|
||||
fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
|
||||
let parent_def = self.parent_def();
|
||||
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
|
||||
self.definitions.create_def_with_parent(parent_def, node_id, data)
|
||||
}
|
||||
|
||||
@ -115,10 +116,13 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
/// deep walking so that we walk nested items in the context of
|
||||
/// their outer items.
|
||||
fn visit_nested_item(&mut self, item: ItemId) {
|
||||
debug!("visit_nested_item: {:?}", item);
|
||||
self.visit_item(self.krate.item(item.id))
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, i: &'ast Item) {
|
||||
debug!("visit_item: {:?}", i);
|
||||
|
||||
// Pick the def data. This need not be unique, but the more
|
||||
// information we encapsulate into
|
||||
let def_data = match i.node {
|
||||
|
@ -14,6 +14,8 @@ use self::MapEntry::*;
|
||||
use self::collector::NodeCollector;
|
||||
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData};
|
||||
|
||||
use dep_graph::{DepGraph, DepNode};
|
||||
|
||||
use middle::cstore::InlinedItem;
|
||||
use middle::cstore::InlinedItem as II;
|
||||
use middle::def_id::DefId;
|
||||
@ -228,19 +230,22 @@ impl<'ast> MapEntry<'ast> {
|
||||
|
||||
/// Stores a crate and any number of inlined items from other crates.
|
||||
pub struct Forest {
|
||||
pub krate: Crate,
|
||||
krate: Crate,
|
||||
pub dep_graph: DepGraph,
|
||||
inlined_items: TypedArena<InlinedParent>
|
||||
}
|
||||
|
||||
impl Forest {
|
||||
pub fn new(krate: Crate) -> Forest {
|
||||
pub fn new(krate: Crate, dep_graph: DepGraph) -> Forest {
|
||||
Forest {
|
||||
krate: krate,
|
||||
dep_graph: dep_graph,
|
||||
inlined_items: TypedArena::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn krate<'ast>(&'ast self) -> &'ast Crate {
|
||||
self.dep_graph.read(DepNode::Krate);
|
||||
&self.krate
|
||||
}
|
||||
}
|
||||
@ -252,6 +257,10 @@ pub struct Map<'ast> {
|
||||
/// The backing storage for all the AST nodes.
|
||||
pub forest: &'ast Forest,
|
||||
|
||||
/// Same as the dep_graph in forest, just available with one fewer
|
||||
/// deref. This is a gratuitious micro-optimization.
|
||||
pub dep_graph: DepGraph,
|
||||
|
||||
/// NodeIds are sequential integers from 0, so we can be
|
||||
/// super-compact by storing them in a vector. Not everything with
|
||||
/// a NodeId is in the map, but empirically the occupancy is about
|
||||
@ -267,6 +276,60 @@ pub struct Map<'ast> {
|
||||
}
|
||||
|
||||
impl<'ast> Map<'ast> {
|
||||
/// 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
|
||||
/// "reveals" the content of a node to the caller (who might not
|
||||
/// otherwise have had access to those contents, and hence needs a
|
||||
/// read recorded). If the function just returns a DefId or
|
||||
/// NodeId, no actual content was returned, so no read is needed.
|
||||
fn read(&self, id: NodeId) {
|
||||
self.dep_graph.read(self.dep_node(id));
|
||||
}
|
||||
|
||||
fn dep_node(&self, id0: NodeId) -> DepNode {
|
||||
let map = self.map.borrow();
|
||||
let mut id = id0;
|
||||
loop {
|
||||
match map[id as usize] {
|
||||
EntryItem(_, item) => {
|
||||
let def_id = self.local_def_id(item.id);
|
||||
// NB ^~~~~~~
|
||||
//
|
||||
// You would expect that `item.id == id`, but this
|
||||
// is not always the case. In particular, for a
|
||||
// ViewPath item like `use self::{mem, foo}`, we
|
||||
// map the ids for `mem` and `foo` to the
|
||||
// enclosing view path item. This seems mega super
|
||||
// ultra wrong, but then who am I to judge?
|
||||
// -nmatsakis
|
||||
return DepNode::Hir(def_id);
|
||||
}
|
||||
|
||||
EntryForeignItem(p, _) |
|
||||
EntryTraitItem(p, _) |
|
||||
EntryImplItem(p, _) |
|
||||
EntryVariant(p, _) |
|
||||
EntryExpr(p, _) |
|
||||
EntryStmt(p, _) |
|
||||
EntryLocal(p, _) |
|
||||
EntryPat(p, _) |
|
||||
EntryBlock(p, _) |
|
||||
EntryStructCtor(p, _) |
|
||||
EntryLifetime(p, _) |
|
||||
EntryTyParam(p, _) =>
|
||||
id = p,
|
||||
|
||||
RootCrate |
|
||||
RootInlinedParent(_) => // FIXME(#2369) clarify story about cross-crate dep tracking
|
||||
return DepNode::Krate,
|
||||
|
||||
NotPresent =>
|
||||
panic!("Walking parents from `{}` led to `NotPresent` at `{}`", id0, id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_local_def_ids(&self) -> usize {
|
||||
self.definitions.borrow().len()
|
||||
}
|
||||
@ -309,26 +372,30 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
|
||||
pub fn krate(&self) -> &'ast Crate {
|
||||
&self.forest.krate
|
||||
self.forest.krate()
|
||||
}
|
||||
|
||||
/// Retrieve the Node corresponding to `id`, panicking if it cannot
|
||||
/// be found.
|
||||
pub fn get(&self, id: NodeId) -> Node<'ast> {
|
||||
match self.find(id) {
|
||||
Some(node) => node,
|
||||
Some(node) => node, // read recorded by `find`
|
||||
None => panic!("couldn't find node id {} in the AST map", id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_if_local(&self, id: DefId) -> Option<Node<'ast>> {
|
||||
self.as_local_node_id(id).map(|id| self.get(id))
|
||||
self.as_local_node_id(id).map(|id| self.get(id)) // read recorded by `get`
|
||||
}
|
||||
|
||||
/// Retrieve the Node corresponding to `id`, returning None if
|
||||
/// cannot be found.
|
||||
pub fn find(&self, id: NodeId) -> Option<Node<'ast>> {
|
||||
self.find_entry(id).and_then(|x| x.to_node())
|
||||
let result = self.find_entry(id).and_then(|x| x.to_node());
|
||||
if result.is_some() {
|
||||
self.read(id);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Similar to get_parent, returns the parent node id or id if there is no
|
||||
@ -459,22 +526,25 @@ impl<'ast> Map<'ast> {
|
||||
_ => None
|
||||
};
|
||||
match abi {
|
||||
Some(abi) => abi,
|
||||
Some(abi) => {
|
||||
self.read(id); // reveals some of the content of a node
|
||||
abi
|
||||
}
|
||||
None => panic!("expected foreign mod or inlined parent, found {}",
|
||||
self.node_to_string(parent))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_foreign_vis(&self, id: NodeId) -> Visibility {
|
||||
let vis = self.expect_foreign_item(id).vis;
|
||||
match self.find(self.get_parent(id)) {
|
||||
let vis = self.expect_foreign_item(id).vis; // read recorded by `expect_foreign_item`
|
||||
match self.find(self.get_parent(id)) { // read recorded by `find`
|
||||
Some(NodeItem(i)) => vis.inherit_from(i.vis),
|
||||
_ => vis
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_item(&self, id: NodeId) -> &'ast Item {
|
||||
match self.find(id) {
|
||||
match self.find(id) { // read recorded by `find`
|
||||
Some(NodeItem(item)) => item,
|
||||
_ => panic!("expected item, found {}", self.node_to_string(id))
|
||||
}
|
||||
@ -521,7 +591,7 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
|
||||
pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
|
||||
match self.find(id) {
|
||||
match self.find(id) { // read recorded by find
|
||||
Some(NodeExpr(expr)) => expr,
|
||||
_ => panic!("expected expr, found {}", self.node_to_string(id))
|
||||
}
|
||||
@ -571,6 +641,11 @@ impl<'ast> Map<'ast> {
|
||||
fn with_path_next<T, F>(&self, id: NodeId, next: LinkedPath, f: F) -> T where
|
||||
F: FnOnce(PathElems) -> T,
|
||||
{
|
||||
// This function reveals the name of the item and hence is a
|
||||
// kind of read. This is inefficient, since it walks ancestors
|
||||
// and we are walking them anyhow, but whatever.
|
||||
self.read(id);
|
||||
|
||||
let parent = self.get_parent(id);
|
||||
let parent = match self.find_entry(id) {
|
||||
Some(EntryForeignItem(..)) => {
|
||||
@ -602,6 +677,7 @@ impl<'ast> Map<'ast> {
|
||||
/// Given a node ID, get a list of attributes associated with the AST
|
||||
/// corresponding to the Node ID
|
||||
pub fn attrs(&self, id: NodeId) -> &'ast [ast::Attribute] {
|
||||
self.read(id); // reveals attributes on the node
|
||||
let attrs = match self.find(id) {
|
||||
Some(NodeItem(i)) => Some(&i.attrs[..]),
|
||||
Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
|
||||
@ -655,6 +731,7 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
|
||||
pub fn span(&self, id: NodeId) -> Span {
|
||||
self.read(id); // reveals span from node
|
||||
self.opt_span(id)
|
||||
.unwrap_or_else(|| panic!("AstMap.span: could not find span for id {:?}", id))
|
||||
}
|
||||
@ -833,6 +910,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
|
||||
|
||||
Map {
|
||||
forest: forest,
|
||||
dep_graph: forest.dep_graph.clone(),
|
||||
map: RefCell::new(map),
|
||||
definitions: RefCell::new(definitions),
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
//! `unsafe`.
|
||||
use self::RootUnsafeContext::*;
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use middle::def::Def;
|
||||
use middle::ty::{self, Ty};
|
||||
use middle::ty::MethodCall;
|
||||
@ -182,6 +183,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: &ty::ctxt) {
|
||||
let _task = tcx.dep_graph.in_task(DepNode::EffectCheck);
|
||||
|
||||
let mut visitor = EffectCheckVisitor {
|
||||
tcx: tcx,
|
||||
unsafe_context: UnsafeContext::new(SafeContext),
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use front::map as ast_map;
|
||||
use middle::def_id::{CRATE_DEF_INDEX};
|
||||
use session::{config, Session};
|
||||
@ -48,6 +49,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EntryContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
|
||||
let _task = ast_map.dep_graph.in_task(DepNode::EntryPoint);
|
||||
|
||||
let any_exe = session.crate_types.borrow().iter().any(|ty| {
|
||||
*ty == config::CrateTypeExecutable
|
||||
});
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
pub use self::LangItem::*;
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use front::map as hir_map;
|
||||
use session::Session;
|
||||
use middle::cstore::CrateStore;
|
||||
@ -234,6 +235,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
|
||||
pub fn collect_language_items(session: &Session,
|
||||
map: &hir_map::Map)
|
||||
-> LanguageItems {
|
||||
let _task = map.dep_graph.in_task(DepNode::CollectLanguageItems);
|
||||
let krate: &hir::Crate = map.krate();
|
||||
let mut collector = LanguageItemCollector::new(session, map);
|
||||
collector.collect(krate);
|
||||
|
@ -109,6 +109,7 @@ use self::LoopKind::*;
|
||||
use self::LiveNodeKind::*;
|
||||
use self::VarKind::*;
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use middle::def::*;
|
||||
use middle::pat_util;
|
||||
use middle::ty;
|
||||
@ -192,6 +193,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IrMaps<'a, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: &ty::ctxt) {
|
||||
let _task = tcx.dep_graph.in_task(DepNode::Liveness);
|
||||
tcx.map.krate().visit_all_items(&mut IrMaps::new(tcx));
|
||||
tcx.sess.abort_if_errors();
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
//! Most of the documentation on regions can be found in
|
||||
//! `middle/infer/region_inference/README.md`
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use front::map as ast_map;
|
||||
use session::Session;
|
||||
use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||
@ -1224,7 +1225,10 @@ impl<'a, 'v> Visitor<'v> for RegionResolutionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_crate(sess: &Session, krate: &hir::Crate) -> RegionMaps {
|
||||
pub fn resolve_crate(sess: &Session, map: &ast_map::Map) -> RegionMaps {
|
||||
let _task = map.dep_graph.in_task(DepNode::RegionResolveCrate);
|
||||
let krate = map.krate();
|
||||
|
||||
let maps = RegionMaps {
|
||||
code_extents: RefCell::new(vec![]),
|
||||
code_extent_interner: RefCell::new(FnvHashMap()),
|
||||
|
@ -18,6 +18,8 @@
|
||||
pub use self::DefRegion::*;
|
||||
use self::ScopeChain::*;
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use front::map::Map;
|
||||
use session::Session;
|
||||
use middle::def::{Def, DefMap};
|
||||
use middle::region;
|
||||
@ -94,9 +96,11 @@ type Scope<'a> = &'a ScopeChain<'a>;
|
||||
static ROOT_SCOPE: ScopeChain<'static> = RootScope;
|
||||
|
||||
pub fn krate(sess: &Session,
|
||||
krate: &hir::Crate,
|
||||
hir_map: &Map,
|
||||
def_map: &DefMap)
|
||||
-> Result<NamedRegionMap, usize> {
|
||||
let _task = hir_map.dep_graph.in_task(DepNode::ResolveLifetimes);
|
||||
let krate = hir_map.krate();
|
||||
let mut named_region_map = NodeMap();
|
||||
try!(sess.track_errors(|| {
|
||||
krate.visit_all_items(&mut LifetimeContext {
|
||||
|
@ -14,6 +14,7 @@
|
||||
pub use self::StabilityLevel::*;
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use front::map as hir_map;
|
||||
use session::Session;
|
||||
use lint;
|
||||
use middle::cstore::{CrateStore, LOCAL_CRATE};
|
||||
@ -30,7 +31,7 @@ use syntax::attr::{self, Stability, Deprecation, AttrMetaMethods};
|
||||
use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
|
||||
|
||||
use rustc_front::hir;
|
||||
use rustc_front::hir::{Crate, Item, Generics, StructField, Variant};
|
||||
use rustc_front::hir::{Item, Generics, StructField, Variant};
|
||||
use rustc_front::intravisit::{self, Visitor};
|
||||
|
||||
use std::mem::replace;
|
||||
@ -278,7 +279,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
|
||||
|
||||
impl<'tcx> Index<'tcx> {
|
||||
/// Construct the stability index for a crate being compiled.
|
||||
pub fn build(&mut self, tcx: &ty::ctxt<'tcx>, krate: &Crate, access_levels: &AccessLevels) {
|
||||
pub fn build(&mut self, tcx: &ty::ctxt<'tcx>, access_levels: &AccessLevels) {
|
||||
let _task = tcx.dep_graph.in_task(DepNode::StabilityIndex);
|
||||
let krate = tcx.map.krate();
|
||||
let mut annotator = Annotator {
|
||||
tcx: tcx,
|
||||
index: self,
|
||||
@ -291,7 +294,10 @@ impl<'tcx> Index<'tcx> {
|
||||
|v| intravisit::walk_crate(v, krate));
|
||||
}
|
||||
|
||||
pub fn new(krate: &Crate) -> Index<'tcx> {
|
||||
pub fn new(hir_map: &hir_map::Map) -> Index<'tcx> {
|
||||
let _task = hir_map.dep_graph.in_task(DepNode::StabilityIndex);
|
||||
let krate = hir_map.krate();
|
||||
|
||||
let mut is_staged_api = false;
|
||||
for attr in &krate.attrs {
|
||||
if attr.name() == "stable" || attr.name() == "unstable" {
|
||||
|
@ -509,7 +509,7 @@ impl<'tcx> ctxt<'tcx> {
|
||||
{
|
||||
let interner = RefCell::new(FnvHashMap());
|
||||
let common_types = CommonTypes::new(&arenas.type_, &interner);
|
||||
let dep_graph = DepGraph::new(s.opts.incremental_compilation);
|
||||
let dep_graph = map.dep_graph.clone();
|
||||
let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone());
|
||||
tls::enter(ctxt {
|
||||
arenas: arenas,
|
||||
|
@ -137,8 +137,13 @@ pub struct Options {
|
||||
pub no_trans: bool,
|
||||
pub error_format: ErrorOutputType,
|
||||
pub treat_err_as_bug: bool,
|
||||
pub incremental_compilation: bool,
|
||||
|
||||
/// if true, build up the dep-graph
|
||||
pub build_dep_graph: bool,
|
||||
|
||||
/// if true, -Z dump-dep-graph was passed to dump out the dep-graph
|
||||
pub dump_dep_graph: bool,
|
||||
|
||||
pub no_analysis: bool,
|
||||
pub debugging_opts: DebuggingOptions,
|
||||
pub prints: Vec<PrintRequest>,
|
||||
@ -246,7 +251,7 @@ pub fn basic_options() -> Options {
|
||||
parse_only: false,
|
||||
no_trans: false,
|
||||
treat_err_as_bug: false,
|
||||
incremental_compilation: false,
|
||||
build_dep_graph: false,
|
||||
dump_dep_graph: false,
|
||||
no_analysis: false,
|
||||
debugging_opts: basic_debugging_options(),
|
||||
@ -1145,7 +1150,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||
parse_only: parse_only,
|
||||
no_trans: no_trans,
|
||||
treat_err_as_bug: treat_err_as_bug,
|
||||
incremental_compilation: incremental_compilation || dump_dep_graph,
|
||||
build_dep_graph: incremental_compilation || dump_dep_graph,
|
||||
dump_dep_graph: dump_dep_graph,
|
||||
no_analysis: no_analysis,
|
||||
debugging_opts: debugging_opts,
|
||||
|
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::front;
|
||||
use rustc::front::map as hir_map;
|
||||
use rustc_mir as mir;
|
||||
@ -115,9 +116,11 @@ pub fn compile_input(sess: &Session,
|
||||
let expanded_crate = assign_node_ids(sess, expanded_crate);
|
||||
// Lower ast -> hir.
|
||||
let lcx = LoweringContext::new(sess, Some(&expanded_crate));
|
||||
let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
|
||||
let mut hir_forest = time(sess.time_passes(),
|
||||
"lowering ast -> hir",
|
||||
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate)));
|
||||
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate),
|
||||
dep_graph));
|
||||
|
||||
// Discard MTWT tables that aren't required past lowering to HIR.
|
||||
if !sess.opts.debugging_opts.keep_mtwt_tables &&
|
||||
@ -130,17 +133,20 @@ pub fn compile_input(sess: &Session,
|
||||
|
||||
write_out_deps(sess, &outputs, &id);
|
||||
|
||||
controller_entry_point!(after_write_deps,
|
||||
sess,
|
||||
CompileState::state_after_write_deps(input,
|
||||
sess,
|
||||
outdir,
|
||||
&hir_map,
|
||||
&expanded_crate,
|
||||
&hir_map.krate(),
|
||||
&id[..],
|
||||
&lcx),
|
||||
Ok(()));
|
||||
{
|
||||
let _ignore = hir_map.dep_graph.in_ignore();
|
||||
controller_entry_point!(after_write_deps,
|
||||
sess,
|
||||
CompileState::state_after_write_deps(input,
|
||||
sess,
|
||||
outdir,
|
||||
&hir_map,
|
||||
&expanded_crate,
|
||||
&hir_map.krate(),
|
||||
&id[..],
|
||||
&lcx),
|
||||
Ok(()));
|
||||
}
|
||||
|
||||
time(sess.time_passes(), "attribute checking", || {
|
||||
front::check_attr::check_crate(sess, &expanded_crate);
|
||||
@ -166,6 +172,9 @@ pub fn compile_input(sess: &Session,
|
||||
control.make_glob_map,
|
||||
|tcx, mir_map, analysis, result| {
|
||||
{
|
||||
// Eventually, we will want to track plugins.
|
||||
let _ignore = tcx.dep_graph.in_ignore();
|
||||
|
||||
let state = CompileState::state_after_analysis(input,
|
||||
&tcx.sess,
|
||||
outdir,
|
||||
@ -735,11 +744,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
}
|
||||
|
||||
let time_passes = sess.time_passes();
|
||||
let krate = hir_map.krate();
|
||||
|
||||
time(time_passes,
|
||||
"external crate/lib resolution",
|
||||
|| LocalCrateReader::new(sess, cstore, &hir_map).read_crates(krate));
|
||||
|| LocalCrateReader::new(sess, cstore, &hir_map).read_crates());
|
||||
|
||||
let lang_items = try!(time(time_passes, "language item collection", || {
|
||||
sess.track_errors(|| {
|
||||
@ -769,7 +777,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
let named_region_map = try!(time(time_passes,
|
||||
"lifetime resolution",
|
||||
|| middle::resolve_lifetime::krate(sess,
|
||||
krate,
|
||||
&hir_map,
|
||||
&def_map.borrow())));
|
||||
|
||||
time(time_passes,
|
||||
@ -777,20 +785,22 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|| middle::entry::find_entry_point(sess, &hir_map));
|
||||
|
||||
sess.plugin_registrar_fn.set(time(time_passes, "looking for plugin registrar", || {
|
||||
plugin::build::find_plugin_registrar(sess.diagnostic(), krate)
|
||||
plugin::build::find_plugin_registrar(sess.diagnostic(), &hir_map)
|
||||
}));
|
||||
|
||||
let region_map = time(time_passes,
|
||||
"region resolution",
|
||||
|| middle::region::resolve_crate(sess, krate));
|
||||
|| middle::region::resolve_crate(sess, &hir_map));
|
||||
|
||||
time(time_passes,
|
||||
"loop checking",
|
||||
|| loops::check_crate(sess, krate));
|
||||
|| loops::check_crate(sess, &hir_map));
|
||||
|
||||
try!(time(time_passes,
|
||||
"static item recursion checking",
|
||||
|| static_recursion::check_crate(sess, krate, &def_map.borrow(), &hir_map)));
|
||||
|| static_recursion::check_crate(sess, &def_map.borrow(), &hir_map)));
|
||||
|
||||
let index = stability::Index::new(&hir_map);
|
||||
|
||||
ty::ctxt::create_and_enter(sess,
|
||||
arenas,
|
||||
@ -800,7 +810,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
freevars,
|
||||
region_map,
|
||||
lang_items,
|
||||
stability::Index::new(krate),
|
||||
index,
|
||||
|tcx| {
|
||||
// passes are timed inside typeck
|
||||
try_with_f!(typeck::check_crate(tcx, trait_map), (tcx, None, analysis));
|
||||
@ -818,7 +828,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|
||||
// Do not move this check past lint
|
||||
time(time_passes, "stability index", || {
|
||||
tcx.stability.borrow_mut().build(tcx, krate, &analysis.access_levels)
|
||||
tcx.stability.borrow_mut().build(tcx, &analysis.access_levels)
|
||||
});
|
||||
|
||||
time(time_passes,
|
||||
|
@ -19,6 +19,7 @@ use rustc_trans::back::link;
|
||||
|
||||
use {driver, abort_on_err};
|
||||
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::middle::ty;
|
||||
use rustc::middle::cfg;
|
||||
use rustc::middle::cfg::graphviz::LabelledCFG;
|
||||
@ -183,7 +184,7 @@ impl PpSourceMode {
|
||||
sess: sess,
|
||||
ast_map: Some(ast_map.clone()),
|
||||
};
|
||||
f(&annotation, payload, &ast_map.forest.krate)
|
||||
f(&annotation, payload, ast_map.forest.krate())
|
||||
}
|
||||
|
||||
PpmIdentified => {
|
||||
@ -191,7 +192,7 @@ impl PpSourceMode {
|
||||
sess: sess,
|
||||
ast_map: Some(ast_map.clone()),
|
||||
};
|
||||
f(&annotation, payload, &ast_map.forest.krate)
|
||||
f(&annotation, payload, ast_map.forest.krate())
|
||||
}
|
||||
PpmTyped => {
|
||||
abort_on_err(driver::phase_3_run_analysis_passes(sess,
|
||||
@ -207,7 +208,7 @@ impl PpSourceMode {
|
||||
let _ignore = tcx.dep_graph.in_ignore();
|
||||
f(&annotation,
|
||||
payload,
|
||||
&ast_map.forest.krate)
|
||||
ast_map.forest.krate())
|
||||
}), sess)
|
||||
}
|
||||
_ => panic!("Should use call_with_pp_support"),
|
||||
@ -706,8 +707,10 @@ pub fn pretty_print_input(sess: Session,
|
||||
let mut hir_forest;
|
||||
let lcx = LoweringContext::new(&sess, Some(&krate));
|
||||
let arenas = ty::CtxtArenas::new();
|
||||
let dep_graph = DepGraph::new(false);
|
||||
let _ignore = dep_graph.in_ignore();
|
||||
let ast_map = if compute_ast_map {
|
||||
hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
|
||||
hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
|
||||
let map = driver::make_map(&sess, &mut hir_forest);
|
||||
Some(map)
|
||||
} else {
|
||||
|
@ -11,6 +11,7 @@
|
||||
//! # Standalone Tests for the Inference Module
|
||||
|
||||
use driver;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc_lint;
|
||||
use rustc_resolve as resolve;
|
||||
use rustc_typeck::middle::lang_items;
|
||||
@ -118,17 +119,19 @@ fn test_env<F>(source_string: &str,
|
||||
|
||||
let krate = driver::assign_node_ids(&sess, krate);
|
||||
let lcx = LoweringContext::new(&sess, Some(&krate));
|
||||
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
|
||||
let dep_graph = DepGraph::new(false);
|
||||
let _ignore = dep_graph.in_ignore();
|
||||
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
|
||||
let arenas = ty::CtxtArenas::new();
|
||||
let ast_map = driver::make_map(&sess, &mut hir_forest);
|
||||
let krate = ast_map.krate();
|
||||
|
||||
// run just enough stuff to build a tcx:
|
||||
let lang_items = lang_items::collect_language_items(&sess, &ast_map);
|
||||
let resolve::CrateMap { def_map, freevars, .. } =
|
||||
resolve::resolve_crate(&sess, &ast_map, resolve::MakeGlobMap::No);
|
||||
let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map.borrow());
|
||||
let region_map = region::resolve_crate(&sess, krate);
|
||||
let named_region_map = resolve_lifetime::krate(&sess, &ast_map, &def_map.borrow());
|
||||
let region_map = region::resolve_crate(&sess, &ast_map);
|
||||
let index = stability::Index::new(&ast_map);
|
||||
ty::ctxt::create_and_enter(&sess,
|
||||
&arenas,
|
||||
def_map,
|
||||
@ -137,7 +140,7 @@ fn test_env<F>(source_string: &str,
|
||||
freevars,
|
||||
region_map,
|
||||
lang_items,
|
||||
stability::Index::new(krate),
|
||||
index,
|
||||
|tcx| {
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
body(Env { infcx: &infcx });
|
||||
|
@ -18,6 +18,7 @@ use decoder;
|
||||
use loader::{self, CratePaths};
|
||||
|
||||
use rustc::back::svh::Svh;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::session::{config, Session};
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::middle::cstore::{CrateStore, validate_crate_name};
|
||||
@ -723,7 +724,10 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
|
||||
// Traverses an AST, reading all the information about use'd crates and
|
||||
// extern libraries necessary for later resolving, typechecking, linking,
|
||||
// etc.
|
||||
pub fn read_crates(&mut self, krate: &hir::Crate) {
|
||||
pub fn read_crates(&mut self) {
|
||||
let _task = self.ast_map.dep_graph.in_task(DepNode::CrateReader);
|
||||
let krate = self.ast_map.krate();
|
||||
|
||||
self.process_crate(krate);
|
||||
krate.visit_all_items(self);
|
||||
self.creader.inject_allocator_crate();
|
||||
|
@ -11,9 +11,11 @@ use self::Context::*;
|
||||
|
||||
use rustc::session::Session;
|
||||
|
||||
use syntax::codemap::Span;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::front::map::Map;
|
||||
use rustc_front::intravisit::{self, Visitor};
|
||||
use rustc_front::hir;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum Context {
|
||||
@ -26,7 +28,9 @@ struct CheckLoopVisitor<'a> {
|
||||
cx: Context
|
||||
}
|
||||
|
||||
pub fn check_crate(sess: &Session, krate: &hir::Crate) {
|
||||
pub fn check_crate(sess: &Session, map: &Map) {
|
||||
let _task = map.dep_graph.in_task(DepNode::CheckLoops);
|
||||
let krate = map.krate();
|
||||
krate.visit_all_items(&mut CheckLoopVisitor { sess: sess, cx: Normal });
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
// This compiler pass detects constants that refer to themselves
|
||||
// recursively.
|
||||
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::front::map as ast_map;
|
||||
use rustc::session::{Session, CompileResult};
|
||||
use rustc::middle::def::{Def, DefMap};
|
||||
@ -90,9 +91,11 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
|
||||
}
|
||||
|
||||
pub fn check_crate<'ast>(sess: &Session,
|
||||
krate: &'ast hir::Crate,
|
||||
def_map: &DefMap,
|
||||
ast_map: &ast_map::Map<'ast>) -> CompileResult {
|
||||
ast_map: &ast_map::Map<'ast>)
|
||||
-> CompileResult {
|
||||
let _task = ast_map.dep_graph.in_task(DepNode::CheckStaticRecursion);
|
||||
|
||||
let mut visitor = CheckCrateVisitor {
|
||||
sess: sess,
|
||||
def_map: def_map,
|
||||
@ -100,7 +103,7 @@ pub fn check_crate<'ast>(sess: &Session,
|
||||
discriminant_map: RefCell::new(NodeMap()),
|
||||
};
|
||||
sess.track_errors(|| {
|
||||
krate.visit_all_items(&mut visitor);
|
||||
ast_map.krate().visit_all_items(&mut visitor);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@ use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::errors;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::front::map::Map;
|
||||
use rustc_front::intravisit::Visitor;
|
||||
use rustc_front::hir;
|
||||
|
||||
@ -34,8 +36,11 @@ impl<'v> Visitor<'v> for RegistrarFinder {
|
||||
|
||||
/// Find the function marked with `#[plugin_registrar]`, if any.
|
||||
pub fn find_plugin_registrar(diagnostic: &errors::Handler,
|
||||
krate: &hir::Crate)
|
||||
hir_map: &Map)
|
||||
-> Option<ast::NodeId> {
|
||||
let _task = hir_map.dep_graph.in_task(DepNode::PluginRegistrar);
|
||||
let krate = hir_map.krate();
|
||||
|
||||
let mut finder = RegistrarFinder { registrars: Vec::new() };
|
||||
krate.visit_all_items(&mut finder);
|
||||
|
||||
|
@ -47,6 +47,7 @@ use self::BareIdentifierPatternResolution::*;
|
||||
use self::ParentLink::*;
|
||||
use self::FallbackChecks::*;
|
||||
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::front::map as hir_map;
|
||||
use rustc::session::Session;
|
||||
use rustc::lint;
|
||||
@ -3596,6 +3597,15 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
|
||||
ast_map: &'a hir_map::Map<'tcx>,
|
||||
make_glob_map: MakeGlobMap)
|
||||
-> CrateMap {
|
||||
// Currently, we ignore the name resolution data structures for
|
||||
// the purposes of dependency tracking. Instead we will run name
|
||||
// resolution and include its output in the hash of each item,
|
||||
// much like we do for macro expansion. In other words, the hash
|
||||
// reflects not just its contents but the results of name
|
||||
// resolution on those contents. Hopefully we'll push this back at
|
||||
// some point.
|
||||
let _task = ast_map.dep_graph.in_task(DepNode::Resolve);
|
||||
|
||||
let krate = ast_map.krate();
|
||||
let arenas = Resolver::arenas();
|
||||
let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas, None);
|
||||
|
@ -99,9 +99,8 @@ use rustc_front::print::pprust;
|
||||
|
||||
pub fn collect_item_types(tcx: &ty::ctxt) {
|
||||
let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
|
||||
|
||||
let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
|
||||
ccx.tcx.map.krate().visit_all_items(&mut visitor);
|
||||
ccx.tcx.visit_all_items_in_krate(DepNode::CollectItem, &mut visitor);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -146,9 +145,6 @@ struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
|
||||
|
||||
impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
let tcx = self.ccx.tcx;
|
||||
let item_def_id = tcx.map.local_def_id(item.id);
|
||||
let _task = tcx.dep_graph.in_task(DepNode::CollectItem(item_def_id));
|
||||
convert_item(self.ccx, item);
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +100,7 @@ pub use rustc::middle;
|
||||
pub use rustc::session;
|
||||
pub use rustc::util;
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use front::map as hir_map;
|
||||
use middle::def::Def;
|
||||
use middle::infer::{self, TypeOrigin};
|
||||
@ -312,6 +313,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
|
||||
|
||||
fn check_for_entry_fn(ccx: &CrateCtxt) {
|
||||
let tcx = ccx.tcx;
|
||||
let _task = tcx.dep_graph.in_task(DepNode::CheckEntryFn);
|
||||
match *tcx.sess.entry_fn.borrow() {
|
||||
Some((id, sp)) => match tcx.sess.entry_type.get() {
|
||||
Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
|
||||
|
@ -11,6 +11,7 @@ pub use self::MaybeTyped::*;
|
||||
|
||||
use rustc_lint;
|
||||
use rustc_driver::{driver, target_features, abort_on_err};
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::session::{self, config};
|
||||
use rustc::middle::def_id::DefId;
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
@ -143,7 +144,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
|
||||
let krate = driver::assign_node_ids(&sess, krate);
|
||||
// Lower ast -> hir.
|
||||
let lcx = LoweringContext::new(&sess, Some(&krate));
|
||||
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
|
||||
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), DepGraph::new(false));
|
||||
let arenas = ty::CtxtArenas::new();
|
||||
let hir_map = driver::make_map(&sess, &mut hir_forest);
|
||||
|
||||
|
@ -25,6 +25,7 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
use testing;
|
||||
use rustc_lint;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::front::map as hir_map;
|
||||
use rustc::session::{self, config};
|
||||
use rustc::session::config::{get_unstable_features_setting, OutputType};
|
||||
@ -99,7 +100,9 @@ pub fn run(input: &str,
|
||||
|
||||
let opts = scrape_test_config(&krate);
|
||||
|
||||
let mut forest = hir_map::Forest::new(krate);
|
||||
let dep_graph = DepGraph::new(false);
|
||||
let _ignore = dep_graph.in_ignore();
|
||||
let mut forest = hir_map::Forest::new(krate, dep_graph.clone());
|
||||
let map = hir_map::map_crate(&mut forest);
|
||||
|
||||
let ctx = core::DocContext {
|
||||
|
@ -26,6 +26,7 @@ use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::thread::Builder;
|
||||
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::front::map as ast_map;
|
||||
use rustc::llvm;
|
||||
use rustc::middle::cstore::{CrateStore, LinkagePreference};
|
||||
@ -236,7 +237,8 @@ fn compile_program(input: &str, sysroot: PathBuf)
|
||||
|
||||
let krate = driver::assign_node_ids(&sess, krate);
|
||||
let lcx = LoweringContext::new(&sess, Some(&krate));
|
||||
let mut hir_forest = ast_map::Forest::new(lower_crate(&lcx, &krate));
|
||||
let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
|
||||
let mut hir_forest = ast_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
|
||||
let arenas = ty::CtxtArenas::new();
|
||||
let ast_map = driver::make_map(&sess, &mut hir_forest);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user