Instrument the AST map so that it registers reads when data is
acccessed.
This commit is contained in:
parent
37fbfaf183
commit
d09fd1a529
8 changed files with 118 additions and 18 deletions
|
@ -116,6 +116,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 {
|
pub fn query(&self) -> DepGraphQuery {
|
||||||
self.data.query()
|
self.data.query()
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,7 @@ impl<'ast> NodeCollector<'ast> {
|
||||||
|
|
||||||
fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
|
fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
|
||||||
let parent_def = self.parent_def();
|
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)
|
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
|
/// deep walking so that we walk nested items in the context of
|
||||||
/// their outer items.
|
/// their outer items.
|
||||||
fn visit_nested_item(&mut self, item: ItemId) {
|
fn visit_nested_item(&mut self, item: ItemId) {
|
||||||
|
debug!("visit_nested_item: {:?}", item);
|
||||||
self.visit_item(self.krate.item(item.id))
|
self.visit_item(self.krate.item(item.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, i: &'ast Item) {
|
fn visit_item(&mut self, i: &'ast Item) {
|
||||||
|
debug!("visit_item: {:?}", i);
|
||||||
|
|
||||||
// Pick the def data. This need not be unique, but the more
|
// Pick the def data. This need not be unique, but the more
|
||||||
// information we encapsulate into
|
// information we encapsulate into
|
||||||
let def_data = match i.node {
|
let def_data = match i.node {
|
||||||
|
|
|
@ -14,6 +14,8 @@ use self::MapEntry::*;
|
||||||
use self::collector::NodeCollector;
|
use self::collector::NodeCollector;
|
||||||
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData};
|
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData};
|
||||||
|
|
||||||
|
use dep_graph::{DepGraph, DepNode};
|
||||||
|
|
||||||
use middle::cstore::InlinedItem;
|
use middle::cstore::InlinedItem;
|
||||||
use middle::cstore::InlinedItem as II;
|
use middle::cstore::InlinedItem as II;
|
||||||
use middle::def_id::DefId;
|
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.
|
/// Stores a crate and any number of inlined items from other crates.
|
||||||
pub struct Forest {
|
pub struct Forest {
|
||||||
pub krate: Crate,
|
krate: Crate,
|
||||||
|
pub dep_graph: DepGraph,
|
||||||
inlined_items: TypedArena<InlinedParent>
|
inlined_items: TypedArena<InlinedParent>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Forest {
|
impl Forest {
|
||||||
pub fn new(krate: Crate) -> Forest {
|
pub fn new(krate: Crate, dep_graph: DepGraph) -> Forest {
|
||||||
Forest {
|
Forest {
|
||||||
krate: krate,
|
krate: krate,
|
||||||
|
dep_graph: dep_graph,
|
||||||
inlined_items: TypedArena::new()
|
inlined_items: TypedArena::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn krate<'ast>(&'ast self) -> &'ast Crate {
|
pub fn krate<'ast>(&'ast self) -> &'ast Crate {
|
||||||
|
self.dep_graph.read(DepNode::Krate);
|
||||||
&self.krate
|
&self.krate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,6 +257,10 @@ pub struct Map<'ast> {
|
||||||
/// The backing storage for all the AST nodes.
|
/// The backing storage for all the AST nodes.
|
||||||
pub forest: &'ast Forest,
|
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
|
/// NodeIds are sequential integers from 0, so we can be
|
||||||
/// super-compact by storing them in a vector. Not everything with
|
/// super-compact by storing them in a vector. Not everything with
|
||||||
/// a NodeId is in the map, but empirically the occupancy is about
|
/// a NodeId is in the map, but empirically the occupancy is about
|
||||||
|
@ -267,6 +276,60 @@ pub struct Map<'ast> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> 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
|
||||||
|
// ViewPath like `use self::{mem, foo}`, we record
|
||||||
|
// 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 {
|
pub fn num_local_def_ids(&self) -> usize {
|
||||||
self.definitions.borrow().len()
|
self.definitions.borrow().len()
|
||||||
}
|
}
|
||||||
|
@ -309,26 +372,30 @@ impl<'ast> Map<'ast> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn krate(&self) -> &'ast Crate {
|
pub fn krate(&self) -> &'ast Crate {
|
||||||
&self.forest.krate
|
self.forest.krate()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the Node corresponding to `id`, panicking if it cannot
|
/// Retrieve the Node corresponding to `id`, panicking if it cannot
|
||||||
/// be found.
|
/// be found.
|
||||||
pub fn get(&self, id: NodeId) -> Node<'ast> {
|
pub fn get(&self, id: NodeId) -> Node<'ast> {
|
||||||
match self.find(id) {
|
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)
|
None => panic!("couldn't find node id {} in the AST map", id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_if_local(&self, id: DefId) -> Option<Node<'ast>> {
|
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
|
/// Retrieve the Node corresponding to `id`, returning None if
|
||||||
/// cannot be found.
|
/// cannot be found.
|
||||||
pub fn find(&self, id: NodeId) -> Option<Node<'ast>> {
|
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
|
/// Similar to get_parent, returns the parent node id or id if there is no
|
||||||
|
@ -459,22 +526,25 @@ impl<'ast> Map<'ast> {
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
match abi {
|
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 {}",
|
None => panic!("expected foreign mod or inlined parent, found {}",
|
||||||
self.node_to_string(parent))
|
self.node_to_string(parent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_foreign_vis(&self, id: NodeId) -> Visibility {
|
pub fn get_foreign_vis(&self, id: NodeId) -> Visibility {
|
||||||
let vis = self.expect_foreign_item(id).vis;
|
let vis = self.expect_foreign_item(id).vis; // read recorded by `expect_foreign_item`
|
||||||
match self.find(self.get_parent(id)) {
|
match self.find(self.get_parent(id)) { // read recorded by `find`
|
||||||
Some(NodeItem(i)) => vis.inherit_from(i.vis),
|
Some(NodeItem(i)) => vis.inherit_from(i.vis),
|
||||||
_ => vis
|
_ => vis
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_item(&self, id: NodeId) -> &'ast Item {
|
pub fn expect_item(&self, id: NodeId) -> &'ast Item {
|
||||||
match self.find(id) {
|
match self.find(id) { // read recorded by `id`
|
||||||
Some(NodeItem(item)) => item,
|
Some(NodeItem(item)) => item,
|
||||||
_ => panic!("expected item, found {}", self.node_to_string(id))
|
_ => 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 {
|
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,
|
Some(NodeExpr(expr)) => expr,
|
||||||
_ => panic!("expected expr, found {}", self.node_to_string(id))
|
_ => 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
|
fn with_path_next<T, F>(&self, id: NodeId, next: LinkedPath, f: F) -> T where
|
||||||
F: FnOnce(PathElems) -> T,
|
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 = self.get_parent(id);
|
||||||
let parent = match self.find_entry(id) {
|
let parent = match self.find_entry(id) {
|
||||||
Some(EntryForeignItem(..)) => {
|
Some(EntryForeignItem(..)) => {
|
||||||
|
@ -602,6 +677,7 @@ impl<'ast> Map<'ast> {
|
||||||
/// Given a node ID, get a list of attributes associated with the AST
|
/// Given a node ID, get a list of attributes associated with the AST
|
||||||
/// corresponding to the Node ID
|
/// corresponding to the Node ID
|
||||||
pub fn attrs(&self, id: NodeId) -> &'ast [ast::Attribute] {
|
pub fn attrs(&self, id: NodeId) -> &'ast [ast::Attribute] {
|
||||||
|
self.read(id); // reveals attributes on the node
|
||||||
let attrs = match self.find(id) {
|
let attrs = match self.find(id) {
|
||||||
Some(NodeItem(i)) => Some(&i.attrs[..]),
|
Some(NodeItem(i)) => Some(&i.attrs[..]),
|
||||||
Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
|
Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
|
||||||
|
@ -655,6 +731,7 @@ impl<'ast> Map<'ast> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span(&self, id: NodeId) -> Span {
|
pub fn span(&self, id: NodeId) -> Span {
|
||||||
|
self.read(id); // reveals span from node
|
||||||
self.opt_span(id)
|
self.opt_span(id)
|
||||||
.unwrap_or_else(|| panic!("AstMap.span: could not find span for id {:?}", 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 {
|
Map {
|
||||||
forest: forest,
|
forest: forest,
|
||||||
|
dep_graph: forest.dep_graph.clone(),
|
||||||
map: RefCell::new(map),
|
map: RefCell::new(map),
|
||||||
definitions: RefCell::new(definitions),
|
definitions: RefCell::new(definitions),
|
||||||
}
|
}
|
||||||
|
|
|
@ -509,7 +509,7 @@ impl<'tcx> ctxt<'tcx> {
|
||||||
{
|
{
|
||||||
let interner = RefCell::new(FnvHashMap());
|
let interner = RefCell::new(FnvHashMap());
|
||||||
let common_types = CommonTypes::new(&arenas.type_, &interner);
|
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());
|
let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone());
|
||||||
tls::enter(ctxt {
|
tls::enter(ctxt {
|
||||||
arenas: arenas,
|
arenas: arenas,
|
||||||
|
|
|
@ -137,8 +137,13 @@ pub struct Options {
|
||||||
pub no_trans: bool,
|
pub no_trans: bool,
|
||||||
pub error_format: ErrorOutputType,
|
pub error_format: ErrorOutputType,
|
||||||
pub treat_err_as_bug: bool,
|
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 dump_dep_graph: bool,
|
||||||
|
|
||||||
pub no_analysis: bool,
|
pub no_analysis: bool,
|
||||||
pub debugging_opts: DebuggingOptions,
|
pub debugging_opts: DebuggingOptions,
|
||||||
pub prints: Vec<PrintRequest>,
|
pub prints: Vec<PrintRequest>,
|
||||||
|
@ -246,7 +251,7 @@ pub fn basic_options() -> Options {
|
||||||
parse_only: false,
|
parse_only: false,
|
||||||
no_trans: false,
|
no_trans: false,
|
||||||
treat_err_as_bug: false,
|
treat_err_as_bug: false,
|
||||||
incremental_compilation: false,
|
build_dep_graph: false,
|
||||||
dump_dep_graph: false,
|
dump_dep_graph: false,
|
||||||
no_analysis: false,
|
no_analysis: false,
|
||||||
debugging_opts: basic_debugging_options(),
|
debugging_opts: basic_debugging_options(),
|
||||||
|
@ -1145,7 +1150,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||||
parse_only: parse_only,
|
parse_only: parse_only,
|
||||||
no_trans: no_trans,
|
no_trans: no_trans,
|
||||||
treat_err_as_bug: treat_err_as_bug,
|
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,
|
dump_dep_graph: dump_dep_graph,
|
||||||
no_analysis: no_analysis,
|
no_analysis: no_analysis,
|
||||||
debugging_opts: debugging_opts,
|
debugging_opts: debugging_opts,
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub use self::MaybeTyped::*;
|
||||||
|
|
||||||
use rustc_lint;
|
use rustc_lint;
|
||||||
use rustc_driver::{driver, target_features, abort_on_err};
|
use rustc_driver::{driver, target_features, abort_on_err};
|
||||||
|
use rustc::dep_graph::DepGraph;
|
||||||
use rustc::session::{self, config};
|
use rustc::session::{self, config};
|
||||||
use rustc::middle::def_id::DefId;
|
use rustc::middle::def_id::DefId;
|
||||||
use rustc::middle::privacy::AccessLevels;
|
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);
|
let krate = driver::assign_node_ids(&sess, krate);
|
||||||
// Lower ast -> hir.
|
// Lower ast -> hir.
|
||||||
let lcx = LoweringContext::new(&sess, Some(&krate));
|
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 arenas = ty::CtxtArenas::new();
|
||||||
let hir_map = driver::make_map(&sess, &mut hir_forest);
|
let hir_map = driver::make_map(&sess, &mut hir_forest);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use testing;
|
use testing;
|
||||||
use rustc_lint;
|
use rustc_lint;
|
||||||
|
use rustc::dep_graph::DepGraph;
|
||||||
use rustc::front::map as hir_map;
|
use rustc::front::map as hir_map;
|
||||||
use rustc::session::{self, config};
|
use rustc::session::{self, config};
|
||||||
use rustc::session::config::{get_unstable_features_setting, OutputType};
|
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 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 map = hir_map::map_crate(&mut forest);
|
||||||
|
|
||||||
let ctx = core::DocContext {
|
let ctx = core::DocContext {
|
||||||
|
|
|
@ -26,6 +26,7 @@ use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::thread::Builder;
|
use std::thread::Builder;
|
||||||
|
|
||||||
|
use rustc::dep_graph::DepGraph;
|
||||||
use rustc::front::map as ast_map;
|
use rustc::front::map as ast_map;
|
||||||
use rustc::llvm;
|
use rustc::llvm;
|
||||||
use rustc::middle::cstore::{CrateStore, LinkagePreference};
|
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 krate = driver::assign_node_ids(&sess, krate);
|
||||||
let lcx = LoweringContext::new(&sess, Some(&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 arenas = ty::CtxtArenas::new();
|
||||||
let ast_map = driver::make_map(&sess, &mut hir_forest);
|
let ast_map = driver::make_map(&sess, &mut hir_forest);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue