diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5b655522f342f..2cc39412182dc 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -50,6 +50,7 @@ use session::Session; use std::collections::BTreeMap; use std::iter; use syntax::ast::*; +use syntax::errors; use syntax::ptr::P; use syntax::codemap::{respan, Spanned}; use syntax::parse::token; @@ -60,7 +61,7 @@ use syntax_pos::Span; pub struct LoweringContext<'a> { crate_root: Option<&'static str>, // 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 // 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. @@ -99,7 +100,6 @@ impl Resolver for DummyResolver { pub fn lower_crate(sess: &Session, krate: &Crate, - id_assigner: &NodeIdAssigner, resolver: &mut Resolver) -> hir::Crate { // We're constructing the HIR here; we don't care what we will @@ -115,17 +115,17 @@ pub fn lower_crate(sess: &Session, } else { Some("std") }, - id_assigner: id_assigner, + sess: Some(sess), parent_def: None, resolver: resolver, }.lower_crate(krate) } 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 { crate_root: None, - id_assigner: id_assigner, + sess: None, parent_def: None, resolver: resolver, } @@ -161,7 +161,12 @@ impl<'a> LoweringContext<'a> { } 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 { @@ -786,7 +791,7 @@ impl<'a> LoweringContext<'a> { if let Some(SelfKind::Explicit(..)) = 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(..)) => { - 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"); } _ => {} @@ -1212,7 +1217,7 @@ impl<'a> LoweringContext<'a> { make_struct(self, e, &["RangeInclusive", "NonEmpty"], &[("start", e1), ("end", e2)]), - _ => panic!(self.id_assigner.diagnostic() + _ => panic!(self.diagnostic() .span_fatal(e.span, "inclusive range with no end")), }; } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index ccb3e154d9204..2b89695ab41ca 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -25,15 +25,15 @@ pub struct DefCollector<'ast> { // If we are walking HIR (c.f., AST), we need to keep a reference to the // crate. hir_crate: Option<&'ast hir::Crate>, - pub definitions: Definitions, + definitions: &'ast mut Definitions, parent_def: Option, } impl<'ast> DefCollector<'ast> { - pub fn root() -> DefCollector<'ast> { + pub fn root(definitions: &'ast mut Definitions) -> DefCollector<'ast> { let mut collector = DefCollector { hir_crate: None, - definitions: Definitions::new(), + definitions: definitions, parent_def: None, }; 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, parent_def_path: DefPath, parent_def_id: DefId, - definitions: Definitions) + definitions: &'ast mut Definitions) -> DefCollector<'ast> { let mut collector = DefCollector { hir_crate: None, diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index d66df3e4e8fd2..3317585f820aa 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -10,8 +10,9 @@ use middle::cstore::LOCAL_CRATE; use hir::def_id::{DefId, DefIndex}; +use hir::map::def_collector::DefCollector; use rustc_data_structures::fnv::FnvHashMap; -use syntax::ast; +use syntax::{ast, visit}; use syntax::parse::token::InternedString; 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. pub fn len(&self) -> usize { self.data.len() diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f9fb8ac66b7ef..960e32ae99faf 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -24,7 +24,6 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, }; use syntax::codemap::Spanned; -use syntax::visit; use syntax_pos::Span; use hir::*; @@ -780,12 +779,6 @@ impl Folder for IdAndSpanUpdater { } } -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, definitions: Definitions) -> 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_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, parent_def_path.clone(), parent_def_id, defs); def_collector.walk_item(ii, map.krate()); - *map.definitions.borrow_mut() = def_collector.definitions; let mut collector = NodeCollector::extend(map.krate(), ii, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 77259cea24d28..fdaf182c60542 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use ty::tls; use util::nodemap::{NodeMap, FnvHashMap}; use mir::transform as mir_pass; -use syntax::ast::{NodeId, NodeIdAssigner, Name}; +use syntax::ast::{NodeId, Name}; use errors::{self, DiagnosticBuilder}; use errors::emitter::{Emitter, BasicEmitter, EmitterWriter}; use syntax::json::JsonEmitter; @@ -272,6 +272,9 @@ impl Session { id } + pub fn next_node_id(&self) -> NodeId { + self.reserve_node_ids(1) + } pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { &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 { // Conditions for enabling multi-line errors: if !msg.contains("mismatched types") && diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index eb442c0a34e74..46009e5813094 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::{map as hir_map, FreevarMap, TraitMap}; use rustc::hir::def::DefMap; @@ -27,7 +26,7 @@ use rustc::util::nodemap::NodeSet; use rustc_back::sha2::{Sha256, Digest}; use rustc_borrowck as borrowck; use rustc_incremental; -use rustc_resolve as resolve; +use rustc_resolve::{MakeGlobMap, Resolver}; use rustc_metadata::macro_import; use rustc_metadata::creader::read_local_crates; use rustc_metadata::cstore::CStore; @@ -49,13 +48,11 @@ use std::ffi::{OsString, OsStr}; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use syntax::ast::{self, NodeIdAssigner}; +use syntax::{ast, diagnostics, visit}; use syntax::attr::{self, AttrMetaMethods}; -use syntax::diagnostics; use syntax::fold::Folder; use syntax::parse::{self, PResult, token}; use syntax::util::node_count::NodeCounter; -use syntax::visit; use syntax; use syntax_ext; @@ -293,7 +290,7 @@ pub struct CompileController<'a> { pub after_analysis: PhaseController<'a>, pub after_llvm: PhaseController<'a>, - pub make_glob_map: resolve::MakeGlobMap, + pub make_glob_map: MakeGlobMap, } impl<'a> CompileController<'a> { @@ -305,7 +302,7 @@ impl<'a> CompileController<'a> { after_hir_lowering: PhaseController::basic(), after_analysis: 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, crate_name: &'a str, addl_plugins: Option>, - make_glob_map: resolve::MakeGlobMap) + make_glob_map: MakeGlobMap) -> Result, usize> { 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); + let resolver_arenas = Resolver::arenas(); + let mut resolver = Resolver::new(sess, make_glob_map, &resolver_arenas); + // Collect defintions for def ids. - let mut defs = - time(sess.time_passes(), "collecting defs", || hir_map::collect_definitions(&krate)); + time(sess.time_passes(), "collecting defs", || resolver.definitions.collect(&krate)); - time(sess.time_passes(), - "external crate/lib resolution", - || 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(), "early lint checks", @@ -745,8 +745,14 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, "AST validation", || ast_validation::check_crate(sess, &krate)); - let (analysis, resolutions, hir_forest) = - lower_and_resolve(sess, crate_name, &mut defs, &krate, &sess.dep_graph, make_glob_map); + time(sess.time_passes(), "name resolution", || { + 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. if !keep_mtwt_tables(sess) { @@ -755,9 +761,20 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, Ok(ExpansionResult { expanded_crate: krate, - defs: defs, - analysis: analysis, - resolutions: resolutions, + defs: resolver.definitions, + analysis: ty::CrateAnalysis { + 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 }) } @@ -809,38 +826,6 @@ pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate { 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 /// miscellaneous analysis passes on the crate. Return various /// structures carrying the results of the analysis. diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index dc37bdf6322af..7ef00b971c57b 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -38,7 +38,6 @@ use rustc::ty::subst; use rustc::ty::{self, Ty, TyCtxt}; use syntax::ast; -use syntax::ast::NodeIdAssigner; use syntax::ptr::P; use syntax_pos; @@ -56,7 +55,6 @@ use rustc_serialize::{Encodable, EncoderHelpers}; #[cfg(test)] use std::io::Cursor; #[cfg(test)] use syntax::parse; -#[cfg(test)] use syntax::ast::NodeId; #[cfg(test)] use rustc::hir::print as pprust; #[cfg(test)] use rustc::hir::lowering::{LoweringContext, DummyResolver}; @@ -1295,22 +1293,6 @@ impl FakeExtCtxt for parse::ParseSess { 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)] fn mk_ctxt() -> parse::ParseSess { parse::ParseSess::new() @@ -1318,9 +1300,8 @@ fn mk_ctxt() -> parse::ParseSess { #[cfg(test)] fn with_testing_context T>(f: F) -> T { - let assigner = FakeNodeIdAssigner; let mut resolver = DummyResolver; - let mut lcx = LoweringContext::testing_context(&assigner, &mut resolver); + let mut lcx = LoweringContext::testing_context(&mut resolver); f(&mut lcx) } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8ffa95ec7e96f..9c9e3ff037bc4 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -47,7 +47,7 @@ use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; use rustc::session::Session; use rustc::lint; 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::subst::{ParamSpace, FnSpace, TypeSpace}; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; @@ -925,7 +925,7 @@ impl PrimitiveTypeTable { pub struct Resolver<'a> { session: &'a Session, - definitions: &'a mut Definitions, + pub definitions: Definitions, graph_root: Module<'a>, @@ -1001,7 +1001,7 @@ pub struct Resolver<'a> { arenas: &'a ResolverArenas<'a>, } -struct ResolverArenas<'a> { +pub struct ResolverArenas<'a> { modules: arena::TypedArena>, local_modules: RefCell>>, name_bindings: arena::TypedArena>, @@ -1079,7 +1079,7 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { } 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> { - fn new(session: &'a Session, - definitions: &'a mut Definitions, - make_glob_map: MakeGlobMap, - arenas: &'a ResolverArenas<'a>) - -> Resolver<'a> { - let root_def_id = definitions.local_def_id(CRATE_NODE_ID); + pub fn new(session: &'a Session, make_glob_map: MakeGlobMap, arenas: &'a ResolverArenas<'a>) + -> Resolver<'a> { + let root_def_id = DefId::local(CRATE_DEF_INDEX); let graph_root = ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas); let graph_root = arenas.alloc_module(graph_root); @@ -1115,7 +1112,7 @@ impl<'a> Resolver<'a> { Resolver { session: session, - definitions: definitions, + definitions: Definitions::new(), // The outermost module has def ID 0; this is not reflected in the // AST. @@ -1158,7 +1155,7 @@ impl<'a> Resolver<'a> { } } - fn arenas() -> ResolverArenas<'a> { + pub fn arenas() -> ResolverArenas<'a> { ResolverArenas { modules: arena::TypedArena::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, external: bool) -> Module<'a> { self.arenas.alloc_module(ModuleS::new(parent_link, def, external, self.arenas)) @@ -1568,12 +1586,6 @@ impl<'a> Resolver<'a> { 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) { let name = item.ident.name; @@ -2287,24 +2299,25 @@ impl<'a> Resolver<'a> { PatKind::Ident(bmode, ref ident, ref opt_pat) => { // First try to resolve the identifier as some existing // entity, then fall back to a fresh binding. - let resolution = if let Ok(resolution) = self.resolve_path(pat.id, - &Path::from_ident(ident.span, ident.node), 0, ValueNS) { + let local_def = self.resolve_identifier(ident.node, ValueNS, true); + let resolution = if let Some(LocalDef { def, .. }) = local_def { let always_binding = !pat_src.is_refutable() || opt_pat.is_some() || bmode != BindingMode::ByValue(Mutability::Immutable); - match resolution.base_def { + match def { Def::Struct(..) | Def::Variant(..) | Def::Const(..) | Def::AssociatedConst(..) if !always_binding => { // A constant, unit variant, etc pattern. - resolution + PathResolution::new(def) } Def::Struct(..) | Def::Variant(..) | Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => { // A fresh binding that shadows something unacceptable. + let kind_name = PathResolution::new(def).kind_name(); resolve_error( self, ident.span, ResolutionError::BindingShadowsSomethingUnacceptable( - pat_src.descr(), resolution.kind_name(), ident.node.name) + pat_src.descr(), kind_name, ident.node.name) ); err_path_resolution() } @@ -3454,34 +3467,4 @@ pub enum MakeGlobMap { 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 } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a352715b20b12..cc033cec8b8b1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -19,7 +19,6 @@ pub use util::ThinVec; use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId}; use codemap::{respan, Spanned}; use abi::Abi; -use errors; use parse::token::{self, keywords, InternedString}; use print::pprust; use ptr::P; @@ -362,15 +361,6 @@ pub const CRATE_NODE_ID: NodeId = 0; /// small, positive ids. 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. /// typeck::collect::compute_bounds matches these against /// the "special" built-in traits (see middle::lang_items) and diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index da2967e306f65..3c88fb8f6703b 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -839,7 +839,7 @@ impl HasAttrs for StmtKind { fn attrs(&self) -> &[Attribute] { match *self { 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::Mac(ref mac) => { let (_, _, ref attrs) = **mac; @@ -851,7 +851,7 @@ impl HasAttrs for StmtKind { fn map_attrs) -> Vec>(self, f: F) -> Self { match self { 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::Semi(expr) => StmtKind::Semi(expr.map_attrs(f)), StmtKind::Mac(mac) => StmtKind::Mac(mac.map(|(mac, style, attrs)| { diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 961763c6025fd..eaf82f5f43ded 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -213,12 +213,7 @@ impl<'a> fold::Folder for StripUnconfigured<'a> { } fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector { - // avoid calling `visit_stmt_or_expr_attrs` on items - match stmt.node { - ast::StmtKind::Item(_) => {} - _ => self.visit_stmt_or_expr_attrs(stmt.attrs()), - } - + self.visit_stmt_or_expr_attrs(stmt.attrs()); self.configure(stmt).map(|stmt| fold::noop_fold_stmt(stmt, self)) .unwrap_or(SmallVector::zero()) } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 757b039fcac8a..ca38ef068d05f 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -443,6 +443,10 @@ impl MacResult for DummyResult { span: self.span, })) } + + fn make_ty(self: Box) -> Option> { + Some(DummyResult::raw_ty(self.span)) + } } /// An enum representing the different kinds of syntax extensions. diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3036a88430a2b..a0bbdd8db7a48 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -43,18 +43,19 @@ trait MacroGenerable: Sized { fn fold_with(self, folder: &mut F) -> Self; fn visit_with(&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. 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 { ($($ty:ty: $kind_name:expr, .$make:ident, $(.$fold:ident)* $(lift .$fold_elt:ident)*, - $(.$visit:ident)* $(lift .$visit_elt:ident)*, - |$span:ident| $dummy:expr;)*) => { $( + $(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => { $( impl MacroGenerable for $ty { fn kind_name() -> &'static str { $kind_name } fn make_with<'a>(result: Box) -> Option { result.$make() } @@ -66,31 +67,24 @@ macro_rules! impl_macro_generable { $( visitor.$visit(self) )* $( for item in self.as_slice() { visitor. $visit_elt (item) } )* } - fn dummy($span: Span) -> Self { $dummy } } )* } } impl_macro_generable! { - P: "pattern", .make_pat, .fold_pat, .visit_pat, |span| P(DummyResult::raw_pat(span)); - P: "type", .make_ty, .fold_ty, .visit_ty, |span| DummyResult::raw_ty(span); - P: - "expression", .make_expr, .fold_expr, .visit_expr, |span| DummyResult::raw_expr(span); - SmallVector: - "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt, |_span| SmallVector::zero(); - SmallVector>: - "item", .make_items, lift .fold_item, lift .visit_item, |_span| SmallVector::zero(); + P: "expression", .make_expr, .fold_expr, .visit_expr; + P: "pattern", .make_pat, .fold_pat, .visit_pat; + P: "type", .make_ty, .fold_ty, .visit_ty; + SmallVector: "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt; + SmallVector>: "item", .make_items, lift .fold_item, lift .visit_item; SmallVector: - "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item, - |_span| SmallVector::zero(); + "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item; SmallVector: - "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item, - |_span| SmallVector::zero(); + "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item; } impl MacroGenerable for Option> { fn kind_name() -> &'static str { "expression" } - fn dummy(_span: Span) -> Self { None } fn make_with<'a>(result: Box) -> Option { result.make_expr().map(Some) }