Rollup merge of #34459 - jseyfried:expansion_cleanup, r=nrc

Miscellaneous macro expansion cleanup and groundwork

r? @nrc
This commit is contained in:
Manish Goregaokar
2016-06-29 21:21:21 +05:30
committed by GitHub
13 changed files with 122 additions and 198 deletions

View File

@@ -50,6 +50,7 @@ use session::Session;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::iter; use std::iter;
use syntax::ast::*; use syntax::ast::*;
use syntax::errors;
use syntax::ptr::P; use syntax::ptr::P;
use syntax::codemap::{respan, Spanned}; use syntax::codemap::{respan, Spanned};
use syntax::parse::token; use syntax::parse::token;
@@ -60,7 +61,7 @@ use syntax_pos::Span;
pub struct LoweringContext<'a> { pub struct LoweringContext<'a> {
crate_root: Option<&'static str>, crate_root: Option<&'static str>,
// Use to assign ids to hir nodes that do not directly correspond to an ast node // Use to assign ids to hir nodes that do not directly correspond to an ast node
id_assigner: &'a NodeIdAssigner, sess: Option<&'a Session>,
// As we walk the AST we must keep track of the current 'parent' def id (in // As we walk the AST we must keep track of the current 'parent' def id (in
// the form of a DefIndex) so that if we create a new node which introduces // the form of a DefIndex) so that if we create a new node which introduces
// a definition, then we can properly create the def id. // a definition, then we can properly create the def id.
@@ -99,7 +100,6 @@ impl Resolver for DummyResolver {
pub fn lower_crate(sess: &Session, pub fn lower_crate(sess: &Session,
krate: &Crate, krate: &Crate,
id_assigner: &NodeIdAssigner,
resolver: &mut Resolver) resolver: &mut Resolver)
-> hir::Crate { -> hir::Crate {
// We're constructing the HIR here; we don't care what we will // We're constructing the HIR here; we don't care what we will
@@ -115,17 +115,17 @@ pub fn lower_crate(sess: &Session,
} else { } else {
Some("std") Some("std")
}, },
id_assigner: id_assigner, sess: Some(sess),
parent_def: None, parent_def: None,
resolver: resolver, resolver: resolver,
}.lower_crate(krate) }.lower_crate(krate)
} }
impl<'a> LoweringContext<'a> { impl<'a> LoweringContext<'a> {
pub fn testing_context(id_assigner: &'a NodeIdAssigner, resolver: &'a mut Resolver) -> Self { pub fn testing_context(resolver: &'a mut Resolver) -> Self {
LoweringContext { LoweringContext {
crate_root: None, crate_root: None,
id_assigner: id_assigner, sess: None,
parent_def: None, parent_def: None,
resolver: resolver, resolver: resolver,
} }
@@ -161,7 +161,12 @@ impl<'a> LoweringContext<'a> {
} }
fn next_id(&self) -> NodeId { fn next_id(&self) -> NodeId {
self.id_assigner.next_node_id() self.sess.map(Session::next_node_id).unwrap_or(0)
}
fn diagnostic(&self) -> &errors::Handler {
self.sess.map(Session::diagnostic)
.unwrap_or_else(|| panic!("this lowerer cannot emit diagnostics"))
} }
fn str_to_ident(&self, s: &'static str) -> Name { fn str_to_ident(&self, s: &'static str) -> Name {
@@ -786,7 +791,7 @@ impl<'a> LoweringContext<'a> {
if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) { if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) {
match hir_sig.decl.get_self().map(|eself| eself.node) { match hir_sig.decl.get_self().map(|eself| eself.node) {
Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => { Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => {
self.id_assigner.diagnostic().span_err(sig.decl.inputs[0].ty.span, self.diagnostic().span_err(sig.decl.inputs[0].ty.span,
"the type placeholder `_` is not allowed within types on item signatures"); "the type placeholder `_` is not allowed within types on item signatures");
} }
_ => {} _ => {}
@@ -1212,7 +1217,7 @@ impl<'a> LoweringContext<'a> {
make_struct(self, e, &["RangeInclusive", "NonEmpty"], make_struct(self, e, &["RangeInclusive", "NonEmpty"],
&[("start", e1), ("end", e2)]), &[("start", e1), ("end", e2)]),
_ => panic!(self.id_assigner.diagnostic() _ => panic!(self.diagnostic()
.span_fatal(e.span, "inclusive range with no end")), .span_fatal(e.span, "inclusive range with no end")),
}; };
} }

View File

@@ -25,15 +25,15 @@ pub struct DefCollector<'ast> {
// If we are walking HIR (c.f., AST), we need to keep a reference to the // If we are walking HIR (c.f., AST), we need to keep a reference to the
// crate. // crate.
hir_crate: Option<&'ast hir::Crate>, hir_crate: Option<&'ast hir::Crate>,
pub definitions: Definitions, definitions: &'ast mut Definitions,
parent_def: Option<DefIndex>, parent_def: Option<DefIndex>,
} }
impl<'ast> DefCollector<'ast> { impl<'ast> DefCollector<'ast> {
pub fn root() -> DefCollector<'ast> { pub fn root(definitions: &'ast mut Definitions) -> DefCollector<'ast> {
let mut collector = DefCollector { let mut collector = DefCollector {
hir_crate: None, hir_crate: None,
definitions: Definitions::new(), definitions: definitions,
parent_def: None, parent_def: None,
}; };
let root = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot); let root = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
@@ -48,7 +48,7 @@ impl<'ast> DefCollector<'ast> {
pub fn extend(parent_node: NodeId, pub fn extend(parent_node: NodeId,
parent_def_path: DefPath, parent_def_path: DefPath,
parent_def_id: DefId, parent_def_id: DefId,
definitions: Definitions) definitions: &'ast mut Definitions)
-> DefCollector<'ast> { -> DefCollector<'ast> {
let mut collector = DefCollector { let mut collector = DefCollector {
hir_crate: None, hir_crate: None,

View File

@@ -10,8 +10,9 @@
use middle::cstore::LOCAL_CRATE; use middle::cstore::LOCAL_CRATE;
use hir::def_id::{DefId, DefIndex}; use hir::def_id::{DefId, DefIndex};
use hir::map::def_collector::DefCollector;
use rustc_data_structures::fnv::FnvHashMap; use rustc_data_structures::fnv::FnvHashMap;
use syntax::ast; use syntax::{ast, visit};
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use util::nodemap::NodeMap; use util::nodemap::NodeMap;
@@ -189,6 +190,11 @@ impl Definitions {
} }
} }
pub fn collect(&mut self, krate: &ast::Crate) {
let mut def_collector = DefCollector::root(self);
visit::walk_crate(&mut def_collector, krate);
}
/// Get the number of definitions. /// Get the number of definitions.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.data.len() self.data.len()

View File

@@ -24,7 +24,6 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, }; use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, };
use syntax::codemap::Spanned; use syntax::codemap::Spanned;
use syntax::visit;
use syntax_pos::Span; use syntax_pos::Span;
use hir::*; use hir::*;
@@ -780,12 +779,6 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
} }
} }
pub fn collect_definitions<'ast>(krate: &'ast ast::Crate) -> Definitions {
let mut def_collector = DefCollector::root();
visit::walk_crate(&mut def_collector, krate);
def_collector.definitions
}
pub fn map_crate<'ast>(forest: &'ast mut Forest, pub fn map_crate<'ast>(forest: &'ast mut Forest,
definitions: Definitions) definitions: Definitions)
-> Map<'ast> { -> Map<'ast> {
@@ -842,13 +835,12 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
let ii = map.forest.inlined_items.alloc(ii); let ii = map.forest.inlined_items.alloc(ii);
let ii_parent_id = fld.new_id(DUMMY_NODE_ID); let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()); let defs = &mut *map.definitions.borrow_mut();
let mut def_collector = DefCollector::extend(ii_parent_id, let mut def_collector = DefCollector::extend(ii_parent_id,
parent_def_path.clone(), parent_def_path.clone(),
parent_def_id, parent_def_id,
defs); defs);
def_collector.walk_item(ii, map.krate()); def_collector.walk_item(ii, map.krate());
*map.definitions.borrow_mut() = def_collector.definitions;
let mut collector = NodeCollector::extend(map.krate(), let mut collector = NodeCollector::extend(map.krate(),
ii, ii,

View File

@@ -20,7 +20,7 @@ use ty::tls;
use util::nodemap::{NodeMap, FnvHashMap}; use util::nodemap::{NodeMap, FnvHashMap};
use mir::transform as mir_pass; use mir::transform as mir_pass;
use syntax::ast::{NodeId, NodeIdAssigner, Name}; use syntax::ast::{NodeId, Name};
use errors::{self, DiagnosticBuilder}; use errors::{self, DiagnosticBuilder};
use errors::emitter::{Emitter, BasicEmitter, EmitterWriter}; use errors::emitter::{Emitter, BasicEmitter, EmitterWriter};
use syntax::json::JsonEmitter; use syntax::json::JsonEmitter;
@@ -272,6 +272,9 @@ impl Session {
id id
} }
pub fn next_node_id(&self) -> NodeId {
self.reserve_node_ids(1)
}
pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler {
&self.parse_sess.span_diagnostic &self.parse_sess.span_diagnostic
} }
@@ -345,20 +348,6 @@ impl Session {
} }
} }
impl NodeIdAssigner for Session {
fn next_node_id(&self) -> NodeId {
self.reserve_node_ids(1)
}
fn peek_node_id(&self) -> NodeId {
self.next_node_id.get().checked_add(1).unwrap()
}
fn diagnostic(&self) -> &errors::Handler {
self.diagnostic()
}
}
fn split_msg_into_multilines(msg: &str) -> Option<String> { fn split_msg_into_multilines(msg: &str) -> Option<String> {
// Conditions for enabling multi-line errors: // Conditions for enabling multi-line errors:
if !msg.contains("mismatched types") && if !msg.contains("mismatched types") &&

View File

@@ -8,7 +8,6 @@
// 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::dep_graph::DepGraph;
use rustc::hir; use rustc::hir;
use rustc::hir::{map as hir_map, FreevarMap, TraitMap}; use rustc::hir::{map as hir_map, FreevarMap, TraitMap};
use rustc::hir::def::DefMap; use rustc::hir::def::DefMap;
@@ -27,7 +26,7 @@ use rustc::util::nodemap::NodeSet;
use rustc_back::sha2::{Sha256, Digest}; use rustc_back::sha2::{Sha256, Digest};
use rustc_borrowck as borrowck; use rustc_borrowck as borrowck;
use rustc_incremental; use rustc_incremental;
use rustc_resolve as resolve; use rustc_resolve::{MakeGlobMap, Resolver};
use rustc_metadata::macro_import; use rustc_metadata::macro_import;
use rustc_metadata::creader::read_local_crates; use rustc_metadata::creader::read_local_crates;
use rustc_metadata::cstore::CStore; use rustc_metadata::cstore::CStore;
@@ -49,13 +48,11 @@ use std::ffi::{OsString, OsStr};
use std::fs; use std::fs;
use std::io::{self, Write}; use std::io::{self, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use syntax::ast::{self, NodeIdAssigner}; use syntax::{ast, diagnostics, visit};
use syntax::attr::{self, AttrMetaMethods}; use syntax::attr::{self, AttrMetaMethods};
use syntax::diagnostics;
use syntax::fold::Folder; use syntax::fold::Folder;
use syntax::parse::{self, PResult, token}; use syntax::parse::{self, PResult, token};
use syntax::util::node_count::NodeCounter; use syntax::util::node_count::NodeCounter;
use syntax::visit;
use syntax; use syntax;
use syntax_ext; use syntax_ext;
@@ -293,7 +290,7 @@ pub struct CompileController<'a> {
pub after_analysis: PhaseController<'a>, pub after_analysis: PhaseController<'a>,
pub after_llvm: PhaseController<'a>, pub after_llvm: PhaseController<'a>,
pub make_glob_map: resolve::MakeGlobMap, pub make_glob_map: MakeGlobMap,
} }
impl<'a> CompileController<'a> { impl<'a> CompileController<'a> {
@@ -305,7 +302,7 @@ impl<'a> CompileController<'a> {
after_hir_lowering: PhaseController::basic(), after_hir_lowering: PhaseController::basic(),
after_analysis: PhaseController::basic(), after_analysis: PhaseController::basic(),
after_llvm: PhaseController::basic(), after_llvm: PhaseController::basic(),
make_glob_map: resolve::MakeGlobMap::No, make_glob_map: MakeGlobMap::No,
} }
} }
} }
@@ -564,7 +561,7 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session,
mut krate: ast::Crate, mut krate: ast::Crate,
crate_name: &'a str, crate_name: &'a str,
addl_plugins: Option<Vec<String>>, addl_plugins: Option<Vec<String>>,
make_glob_map: resolve::MakeGlobMap) make_glob_map: MakeGlobMap)
-> Result<ExpansionResult<'a>, usize> { -> Result<ExpansionResult<'a>, usize> {
let time_passes = sess.time_passes(); let time_passes = sess.time_passes();
@@ -729,13 +726,16 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session,
krate = assign_node_ids(sess, krate); krate = assign_node_ids(sess, krate);
// Collect defintions for def ids. let resolver_arenas = Resolver::arenas();
let mut defs = let mut resolver = Resolver::new(sess, make_glob_map, &resolver_arenas);
time(sess.time_passes(), "collecting defs", || hir_map::collect_definitions(&krate));
time(sess.time_passes(), // Collect defintions for def ids.
"external crate/lib resolution", time(sess.time_passes(), "collecting defs", || resolver.definitions.collect(&krate));
|| read_local_crates(sess, &cstore, &defs, &krate, crate_name, &sess.dep_graph));
time(sess.time_passes(), "external crate/lib resolution", || {
let defs = &resolver.definitions;
read_local_crates(sess, &cstore, defs, &krate, crate_name, &sess.dep_graph)
});
time(sess.time_passes(), time(sess.time_passes(),
"early lint checks", "early lint checks",
@@ -745,8 +745,14 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session,
"AST validation", "AST validation",
|| ast_validation::check_crate(sess, &krate)); || ast_validation::check_crate(sess, &krate));
let (analysis, resolutions, hir_forest) = time(sess.time_passes(), "name resolution", || {
lower_and_resolve(sess, crate_name, &mut defs, &krate, &sess.dep_graph, make_glob_map); resolver.resolve_crate(&krate);
});
// Lower ast -> hir.
let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || {
hir_map::Forest::new(lower_crate(sess, &krate, &mut resolver), &sess.dep_graph)
});
// Discard MTWT tables that aren't required past lowering to HIR. // Discard MTWT tables that aren't required past lowering to HIR.
if !keep_mtwt_tables(sess) { if !keep_mtwt_tables(sess) {
@@ -755,9 +761,20 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session,
Ok(ExpansionResult { Ok(ExpansionResult {
expanded_crate: krate, expanded_crate: krate,
defs: defs, defs: resolver.definitions,
analysis: analysis, analysis: ty::CrateAnalysis {
resolutions: resolutions, export_map: resolver.export_map,
access_levels: AccessLevels::default(),
reachable: NodeSet(),
name: crate_name,
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
},
resolutions: Resolutions {
def_map: resolver.def_map,
freevars: resolver.freevars,
trait_map: resolver.trait_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
},
hir_forest: hir_forest hir_forest: hir_forest
}) })
} }
@@ -809,38 +826,6 @@ pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
krate krate
} }
pub fn lower_and_resolve<'a>(sess: &Session,
id: &'a str,
defs: &mut hir_map::Definitions,
krate: &ast::Crate,
dep_graph: &DepGraph,
make_glob_map: resolve::MakeGlobMap)
-> (ty::CrateAnalysis<'a>, Resolutions, hir_map::Forest) {
resolve::with_resolver(sess, defs, make_glob_map, |mut resolver| {
time(sess.time_passes(), "name resolution", || {
resolve::resolve_crate(&mut resolver, krate);
});
// Lower ast -> hir.
let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || {
hir_map::Forest::new(lower_crate(sess, krate, sess, &mut resolver), dep_graph)
});
(ty::CrateAnalysis {
export_map: resolver.export_map,
access_levels: AccessLevels::default(),
reachable: NodeSet(),
name: &id,
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
}, Resolutions {
def_map: resolver.def_map,
freevars: resolver.freevars,
trait_map: resolver.trait_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
}, hir_forest)
})
}
/// Run the resolution, typechecking, region checking and other /// Run the resolution, typechecking, region checking and other
/// miscellaneous analysis passes on the crate. Return various /// miscellaneous analysis passes on the crate. Return various
/// structures carrying the results of the analysis. /// structures carrying the results of the analysis.

View File

@@ -38,7 +38,6 @@ use rustc::ty::subst;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use syntax::ast; use syntax::ast;
use syntax::ast::NodeIdAssigner;
use syntax::ptr::P; use syntax::ptr::P;
use syntax_pos; use syntax_pos;
@@ -56,7 +55,6 @@ use rustc_serialize::{Encodable, EncoderHelpers};
#[cfg(test)] use std::io::Cursor; #[cfg(test)] use std::io::Cursor;
#[cfg(test)] use syntax::parse; #[cfg(test)] use syntax::parse;
#[cfg(test)] use syntax::ast::NodeId;
#[cfg(test)] use rustc::hir::print as pprust; #[cfg(test)] use rustc::hir::print as pprust;
#[cfg(test)] use rustc::hir::lowering::{LoweringContext, DummyResolver}; #[cfg(test)] use rustc::hir::lowering::{LoweringContext, DummyResolver};
@@ -1295,22 +1293,6 @@ impl FakeExtCtxt for parse::ParseSess {
fn parse_sess(&self) -> &parse::ParseSess { self } fn parse_sess(&self) -> &parse::ParseSess { self }
} }
#[cfg(test)]
struct FakeNodeIdAssigner;
#[cfg(test)]
// It should go without saying that this may give unexpected results. Avoid
// lowering anything which needs new nodes.
impl NodeIdAssigner for FakeNodeIdAssigner {
fn next_node_id(&self) -> NodeId {
0
}
fn peek_node_id(&self) -> NodeId {
0
}
}
#[cfg(test)] #[cfg(test)]
fn mk_ctxt() -> parse::ParseSess { fn mk_ctxt() -> parse::ParseSess {
parse::ParseSess::new() parse::ParseSess::new()
@@ -1318,9 +1300,8 @@ fn mk_ctxt() -> parse::ParseSess {
#[cfg(test)] #[cfg(test)]
fn with_testing_context<T, F: FnOnce(&mut LoweringContext) -> T>(f: F) -> T { fn with_testing_context<T, F: FnOnce(&mut LoweringContext) -> T>(f: F) -> T {
let assigner = FakeNodeIdAssigner;
let mut resolver = DummyResolver; let mut resolver = DummyResolver;
let mut lcx = LoweringContext::testing_context(&assigner, &mut resolver); let mut lcx = LoweringContext::testing_context(&mut resolver);
f(&mut lcx) f(&mut lcx)
} }

View File

@@ -47,7 +47,7 @@ use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
use rustc::session::Session; use rustc::session::Session;
use rustc::lint; use rustc::lint;
use rustc::hir::def::*; use rustc::hir::def::*;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::ty; use rustc::ty;
use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace}; use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
@@ -925,7 +925,7 @@ impl PrimitiveTypeTable {
pub struct Resolver<'a> { pub struct Resolver<'a> {
session: &'a Session, session: &'a Session,
definitions: &'a mut Definitions, pub definitions: Definitions,
graph_root: Module<'a>, graph_root: Module<'a>,
@@ -1001,7 +1001,7 @@ pub struct Resolver<'a> {
arenas: &'a ResolverArenas<'a>, arenas: &'a ResolverArenas<'a>,
} }
struct ResolverArenas<'a> { pub struct ResolverArenas<'a> {
modules: arena::TypedArena<ModuleS<'a>>, modules: arena::TypedArena<ModuleS<'a>>,
local_modules: RefCell<Vec<Module<'a>>>, local_modules: RefCell<Vec<Module<'a>>>,
name_bindings: arena::TypedArena<NameBinding<'a>>, name_bindings: arena::TypedArena<NameBinding<'a>>,
@@ -1079,7 +1079,7 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
} }
fn definitions(&mut self) -> Option<&mut Definitions> { fn definitions(&mut self) -> Option<&mut Definitions> {
Some(self.definitions) Some(&mut self.definitions)
} }
} }
@@ -1100,12 +1100,9 @@ impl Named for hir::PathSegment {
} }
impl<'a> Resolver<'a> { impl<'a> Resolver<'a> {
fn new(session: &'a Session, pub fn new(session: &'a Session, make_glob_map: MakeGlobMap, arenas: &'a ResolverArenas<'a>)
definitions: &'a mut Definitions, -> Resolver<'a> {
make_glob_map: MakeGlobMap, let root_def_id = DefId::local(CRATE_DEF_INDEX);
arenas: &'a ResolverArenas<'a>)
-> Resolver<'a> {
let root_def_id = definitions.local_def_id(CRATE_NODE_ID);
let graph_root = let graph_root =
ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas); ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas);
let graph_root = arenas.alloc_module(graph_root); let graph_root = arenas.alloc_module(graph_root);
@@ -1115,7 +1112,7 @@ impl<'a> Resolver<'a> {
Resolver { Resolver {
session: session, session: session,
definitions: definitions, definitions: Definitions::new(),
// The outermost module has def ID 0; this is not reflected in the // The outermost module has def ID 0; this is not reflected in the
// AST. // AST.
@@ -1158,7 +1155,7 @@ impl<'a> Resolver<'a> {
} }
} }
fn arenas() -> ResolverArenas<'a> { pub fn arenas() -> ResolverArenas<'a> {
ResolverArenas { ResolverArenas {
modules: arena::TypedArena::new(), modules: arena::TypedArena::new(),
local_modules: RefCell::new(Vec::new()), local_modules: RefCell::new(Vec::new()),
@@ -1168,6 +1165,27 @@ impl<'a> Resolver<'a> {
} }
} }
/// Entry point to crate resolution.
pub fn resolve_crate(&mut self, krate: &Crate) {
// 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 _ignore = self.session.dep_graph.in_ignore();
self.build_reduced_graph(krate);
resolve_imports::resolve_imports(self);
self.current_module = self.graph_root;
visit::walk_crate(self, krate);
check_unused::check_crate(self, krate);
self.report_privacy_errors();
}
fn new_module(&self, parent_link: ParentLink<'a>, def: Option<Def>, external: bool) fn new_module(&self, parent_link: ParentLink<'a>, def: Option<Def>, external: bool)
-> Module<'a> { -> Module<'a> {
self.arenas.alloc_module(ModuleS::new(parent_link, def, external, self.arenas)) self.arenas.alloc_module(ModuleS::new(parent_link, def, external, self.arenas))
@@ -1568,12 +1586,6 @@ impl<'a> Resolver<'a> {
None None
} }
fn resolve_crate(&mut self, krate: &Crate) {
debug!("(resolving crate) starting");
self.current_module = self.graph_root;
visit::walk_crate(self, krate);
}
fn resolve_item(&mut self, item: &Item) { fn resolve_item(&mut self, item: &Item) {
let name = item.ident.name; let name = item.ident.name;
@@ -2287,24 +2299,25 @@ impl<'a> Resolver<'a> {
PatKind::Ident(bmode, ref ident, ref opt_pat) => { PatKind::Ident(bmode, ref ident, ref opt_pat) => {
// First try to resolve the identifier as some existing // First try to resolve the identifier as some existing
// entity, then fall back to a fresh binding. // entity, then fall back to a fresh binding.
let resolution = if let Ok(resolution) = self.resolve_path(pat.id, let local_def = self.resolve_identifier(ident.node, ValueNS, true);
&Path::from_ident(ident.span, ident.node), 0, ValueNS) { let resolution = if let Some(LocalDef { def, .. }) = local_def {
let always_binding = !pat_src.is_refutable() || opt_pat.is_some() || let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
bmode != BindingMode::ByValue(Mutability::Immutable); bmode != BindingMode::ByValue(Mutability::Immutable);
match resolution.base_def { match def {
Def::Struct(..) | Def::Variant(..) | Def::Struct(..) | Def::Variant(..) |
Def::Const(..) | Def::AssociatedConst(..) if !always_binding => { Def::Const(..) | Def::AssociatedConst(..) if !always_binding => {
// A constant, unit variant, etc pattern. // A constant, unit variant, etc pattern.
resolution PathResolution::new(def)
} }
Def::Struct(..) | Def::Variant(..) | Def::Struct(..) | Def::Variant(..) |
Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => { Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => {
// A fresh binding that shadows something unacceptable. // A fresh binding that shadows something unacceptable.
let kind_name = PathResolution::new(def).kind_name();
resolve_error( resolve_error(
self, self,
ident.span, ident.span,
ResolutionError::BindingShadowsSomethingUnacceptable( ResolutionError::BindingShadowsSomethingUnacceptable(
pat_src.descr(), resolution.kind_name(), ident.node.name) pat_src.descr(), kind_name, ident.node.name)
); );
err_path_resolution() err_path_resolution()
} }
@@ -3454,34 +3467,4 @@ pub enum MakeGlobMap {
No, No,
} }
/// Entry point to crate resolution.
pub fn resolve_crate<'a, 'b>(resolver: &'b mut Resolver<'a>, krate: &'b Crate) {
// 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 _ignore = resolver.session.dep_graph.in_ignore();
resolver.build_reduced_graph(krate);
resolve_imports::resolve_imports(resolver);
resolver.resolve_crate(krate);
check_unused::check_crate(resolver, krate);
resolver.report_privacy_errors();
}
pub fn with_resolver<'a, T, F>(session: &'a Session,
definitions: &'a mut Definitions,
make_glob_map: MakeGlobMap,
f: F) -> T
where F: for<'b> FnOnce(Resolver<'b>) -> T,
{
let arenas = Resolver::arenas();
let resolver = Resolver::new(session, definitions, make_glob_map, &arenas);
f(resolver)
}
__build_diagnostic_array! { librustc_resolve, DIAGNOSTICS } __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }

View File

@@ -19,7 +19,6 @@ pub use util::ThinVec;
use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId}; use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId};
use codemap::{respan, Spanned}; use codemap::{respan, Spanned};
use abi::Abi; use abi::Abi;
use errors;
use parse::token::{self, keywords, InternedString}; use parse::token::{self, keywords, InternedString};
use print::pprust; use print::pprust;
use ptr::P; use ptr::P;
@@ -362,15 +361,6 @@ pub const CRATE_NODE_ID: NodeId = 0;
/// small, positive ids. /// small, positive ids.
pub const DUMMY_NODE_ID: NodeId = !0; pub const DUMMY_NODE_ID: NodeId = !0;
pub trait NodeIdAssigner {
fn next_node_id(&self) -> NodeId;
fn peek_node_id(&self) -> NodeId;
fn diagnostic(&self) -> &errors::Handler {
panic!("this ID assigner cannot emit diagnostics")
}
}
/// The AST represents all type param bounds as types. /// The AST represents all type param bounds as types.
/// typeck::collect::compute_bounds matches these against /// typeck::collect::compute_bounds matches these against
/// the "special" built-in traits (see middle::lang_items) and /// the "special" built-in traits (see middle::lang_items) and

View File

@@ -839,7 +839,7 @@ impl HasAttrs for StmtKind {
fn attrs(&self) -> &[Attribute] { fn attrs(&self) -> &[Attribute] {
match *self { match *self {
StmtKind::Local(ref local) => local.attrs(), StmtKind::Local(ref local) => local.attrs(),
StmtKind::Item(ref item) => item.attrs(), StmtKind::Item(..) => &[],
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(), StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(),
StmtKind::Mac(ref mac) => { StmtKind::Mac(ref mac) => {
let (_, _, ref attrs) = **mac; let (_, _, ref attrs) = **mac;
@@ -851,7 +851,7 @@ impl HasAttrs for StmtKind {
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self { fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
match self { match self {
StmtKind::Local(local) => StmtKind::Local(local.map_attrs(f)), StmtKind::Local(local) => StmtKind::Local(local.map_attrs(f)),
StmtKind::Item(item) => StmtKind::Item(item.map_attrs(f)), StmtKind::Item(..) => self,
StmtKind::Expr(expr) => StmtKind::Expr(expr.map_attrs(f)), StmtKind::Expr(expr) => StmtKind::Expr(expr.map_attrs(f)),
StmtKind::Semi(expr) => StmtKind::Semi(expr.map_attrs(f)), StmtKind::Semi(expr) => StmtKind::Semi(expr.map_attrs(f)),
StmtKind::Mac(mac) => StmtKind::Mac(mac.map(|(mac, style, attrs)| { StmtKind::Mac(mac) => StmtKind::Mac(mac.map(|(mac, style, attrs)| {

View File

@@ -213,12 +213,7 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
} }
fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> { fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
// avoid calling `visit_stmt_or_expr_attrs` on items self.visit_stmt_or_expr_attrs(stmt.attrs());
match stmt.node {
ast::StmtKind::Item(_) => {}
_ => self.visit_stmt_or_expr_attrs(stmt.attrs()),
}
self.configure(stmt).map(|stmt| fold::noop_fold_stmt(stmt, self)) self.configure(stmt).map(|stmt| fold::noop_fold_stmt(stmt, self))
.unwrap_or(SmallVector::zero()) .unwrap_or(SmallVector::zero())
} }

View File

@@ -443,6 +443,10 @@ impl MacResult for DummyResult {
span: self.span, span: self.span,
})) }))
} }
fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
Some(DummyResult::raw_ty(self.span))
}
} }
/// An enum representing the different kinds of syntax extensions. /// An enum representing the different kinds of syntax extensions.

View File

@@ -43,18 +43,19 @@ trait MacroGenerable: Sized {
fn fold_with<F: Folder>(self, folder: &mut F) -> Self; fn fold_with<F: Folder>(self, folder: &mut F) -> Self;
fn visit_with<V: Visitor>(&self, visitor: &mut V); fn visit_with<V: Visitor>(&self, visitor: &mut V);
// Return a placeholder expansion to allow compilation to continue after an erroring expansion.
fn dummy(span: Span) -> Self;
// The user-friendly name of the node type (e.g. "expression", "item", etc.) for diagnostics. // The user-friendly name of the node type (e.g. "expression", "item", etc.) for diagnostics.
fn kind_name() -> &'static str; fn kind_name() -> &'static str;
// Return a placeholder expansion to allow compilation to continue after an erroring expansion.
fn dummy(span: Span) -> Self {
Self::make_with(DummyResult::any(span)).unwrap()
}
} }
macro_rules! impl_macro_generable { macro_rules! impl_macro_generable {
($($ty:ty: $kind_name:expr, .$make:ident, ($($ty:ty: $kind_name:expr, .$make:ident,
$(.$fold:ident)* $(lift .$fold_elt:ident)*, $(.$fold:ident)* $(lift .$fold_elt:ident)*,
$(.$visit:ident)* $(lift .$visit_elt:ident)*, $(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => { $(
|$span:ident| $dummy:expr;)*) => { $(
impl MacroGenerable for $ty { impl MacroGenerable for $ty {
fn kind_name() -> &'static str { $kind_name } fn kind_name() -> &'static str { $kind_name }
fn make_with<'a>(result: Box<MacResult + 'a>) -> Option<Self> { result.$make() } fn make_with<'a>(result: Box<MacResult + 'a>) -> Option<Self> { result.$make() }
@@ -66,31 +67,24 @@ macro_rules! impl_macro_generable {
$( visitor.$visit(self) )* $( visitor.$visit(self) )*
$( for item in self.as_slice() { visitor. $visit_elt (item) } )* $( for item in self.as_slice() { visitor. $visit_elt (item) } )*
} }
fn dummy($span: Span) -> Self { $dummy }
} }
)* } )* }
} }
impl_macro_generable! { impl_macro_generable! {
P<ast::Pat>: "pattern", .make_pat, .fold_pat, .visit_pat, |span| P(DummyResult::raw_pat(span)); P<ast::Expr>: "expression", .make_expr, .fold_expr, .visit_expr;
P<ast::Ty>: "type", .make_ty, .fold_ty, .visit_ty, |span| DummyResult::raw_ty(span); P<ast::Pat>: "pattern", .make_pat, .fold_pat, .visit_pat;
P<ast::Expr>: P<ast::Ty>: "type", .make_ty, .fold_ty, .visit_ty;
"expression", .make_expr, .fold_expr, .visit_expr, |span| DummyResult::raw_expr(span); SmallVector<ast::Stmt>: "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt;
SmallVector<ast::Stmt>: SmallVector<P<ast::Item>>: "item", .make_items, lift .fold_item, lift .visit_item;
"statement", .make_stmts, lift .fold_stmt, lift .visit_stmt, |_span| SmallVector::zero();
SmallVector<P<ast::Item>>:
"item", .make_items, lift .fold_item, lift .visit_item, |_span| SmallVector::zero();
SmallVector<ast::TraitItem>: SmallVector<ast::TraitItem>:
"trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item, "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item;
|_span| SmallVector::zero();
SmallVector<ast::ImplItem>: SmallVector<ast::ImplItem>:
"impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item, "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item;
|_span| SmallVector::zero();
} }
impl MacroGenerable for Option<P<ast::Expr>> { impl MacroGenerable for Option<P<ast::Expr>> {
fn kind_name() -> &'static str { "expression" } fn kind_name() -> &'static str { "expression" }
fn dummy(_span: Span) -> Self { None }
fn make_with<'a>(result: Box<MacResult + 'a>) -> Option<Self> { fn make_with<'a>(result: Box<MacResult + 'a>) -> Option<Self> {
result.make_expr().map(Some) result.make_expr().map(Some)
} }