diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2017-03-22 08:39:51 +0000 |
|---|---|---|
| committer | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2017-05-25 05:51:50 +0000 |
| commit | 1f175fa35d4263f1d2c4c3433a495a78996305f4 (patch) | |
| tree | 5c82cc94964d2e84147ed74a74f53d25c00fc29c /src/librustc_resolve | |
| parent | 1cded8472ed034739ff31e314f5cf76ebe5d07c1 (diff) | |
| download | rust-1f175fa35d4263f1d2c4c3433a495a78996305f4.tar.gz rust-1f175fa35d4263f1d2c4c3433a495a78996305f4.zip | |
Hygienize `librustc_resolve`.
Diffstat (limited to 'src/librustc_resolve')
| -rw-r--r-- | src/librustc_resolve/build_reduced_graph.rs | 69 | ||||
| -rw-r--r-- | src/librustc_resolve/lib.rs | 216 | ||||
| -rw-r--r-- | src/librustc_resolve/macros.rs | 51 | ||||
| -rw-r--r-- | src/librustc_resolve/resolve_imports.rs | 68 |
4 files changed, 265 insertions, 139 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 18798962df1..72f555b47cc 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -23,7 +23,7 @@ use {resolve_error, resolve_struct_error, ResolutionError}; use rustc::middle::cstore::LoadedMacro; use rustc::hir::def::*; -use rustc::hir::def_id::{CrateNum, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use std::cell::Cell; @@ -150,7 +150,7 @@ impl<'a> Resolver<'a> { view_path.span, ResolutionError::SelfImportsOnlyAllowedWithin); } else if source_name == "$crate" && full_path.segments.len() == 1 { - let crate_root = self.resolve_crate_var(source.ctxt, item.span); + let crate_root = self.resolve_crate_root(source.ctxt); let crate_name = match crate_root.kind { ModuleKind::Def(_, name) => name, ModuleKind::Block(..) => unreachable!(), @@ -247,7 +247,8 @@ impl<'a> Resolver<'a> { // n.b. we don't need to look at the path option here, because cstore already did let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap(); - let module = self.get_extern_crate_root(crate_id, item.span); + let module = + self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); self.populate_module_if_necessary(module); let used = self.process_legacy_macro_imports(item, module, expansion); let binding = @@ -279,7 +280,7 @@ impl<'a> Resolver<'a> { no_implicit_prelude: parent.no_implicit_prelude || { attr::contains_name(&item.attrs, "no_implicit_prelude") }, - ..ModuleData::new(Some(parent), module_kind, def_id, item.span) + ..ModuleData::new(Some(parent), module_kind, def_id, expansion, item.span) }); self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); self.module_map.insert(def_id, module); @@ -317,6 +318,7 @@ impl<'a> Resolver<'a> { let module = self.new_module(parent, module_kind, parent.normal_ancestor_id, + expansion, item.span); self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); @@ -376,6 +378,7 @@ impl<'a> Resolver<'a> { let module = self.new_module(parent, module_kind, parent.normal_ancestor_id, + expansion, item.span); self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); self.current_module = module; @@ -421,12 +424,13 @@ impl<'a> Resolver<'a> { self.define(parent, item.ident, ValueNS, (def, vis, item.span, expansion)); } - fn build_reduced_graph_for_block(&mut self, block: &Block) { + fn build_reduced_graph_for_block(&mut self, block: &Block, expansion: Mark) { let parent = self.current_module; if self.block_needs_anonymous_module(block) { let module = self.new_module(parent, ModuleKind::Block(block.id), parent.normal_ancestor_id, + expansion, block.span); self.block_map.insert(block.id, module); self.current_module = module; // Descend into the block. @@ -440,23 +444,24 @@ impl<'a> Resolver<'a> { let def_id = def.def_id(); let vis = self.session.cstore.visibility(def_id); let span = child.span; - + let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene match def { Def::Mod(..) | Def::Enum(..) => { let module = self.new_module(parent, ModuleKind::Def(def, ident.name), def_id, + expansion, span); - self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); } Def::Variant(..) | Def::TyAlias(..) => { - self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); } Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => { - self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); } Def::StructCtor(..) => { - self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); if let Some(struct_def_id) = self.session.cstore.def_key(def_id).parent @@ -469,14 +474,15 @@ impl<'a> Resolver<'a> { let module = self.new_module(parent, module_kind, parent.normal_ancestor_id, + expansion, span); - self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); for child in self.session.cstore.item_children(def_id) { let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS }; let ident = Ident::with_empty_ctxt(child.name); self.define(module, ident, ns, (child.def, ty::Visibility::Public, - DUMMY_SP, Mark::root())); + DUMMY_SP, expansion)); if self.session.cstore.associated_item_cloned(child.def.def_id()) .method_has_self_argument { @@ -486,31 +492,42 @@ impl<'a> Resolver<'a> { module.populated.set(true); } Def::Struct(..) | Def::Union(..) => { - self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); // Record field names for error reporting. let field_names = self.session.cstore.struct_field_names(def_id); self.insert_field_names(def_id, field_names); } Def::Macro(..) => { - self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, expansion)); } _ => bug!("unexpected definition: {:?}", def) } } - fn get_extern_crate_root(&mut self, cnum: CrateNum, span: Span) -> Module<'a> { - let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; - let name = self.session.cstore.crate_name(cnum); - let macros_only = self.session.cstore.dep_kind(cnum).macros_only(); - let module_kind = ModuleKind::Def(Def::Mod(def_id), name); - let arenas = self.arenas; - *self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| { - arenas.alloc_module(ModuleData::new(None, module_kind, def_id, span)) - }) + pub fn get_module(&mut self, def_id: DefId) -> Module<'a> { + if def_id.krate == LOCAL_CRATE { + return self.module_map[&def_id] + } + + let macros_only = self.session.cstore.dep_kind(def_id.krate).macros_only(); + if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) { + return module; + } + + let (name, parent) = if def_id.index == CRATE_DEF_INDEX { + (self.session.cstore.crate_name(def_id.krate), None) + } else { + let def_key = self.session.cstore.def_key(def_id); + (def_key.disambiguated_data.data.get_opt_name().unwrap(), + Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }))) + }; + + let kind = ModuleKind::Def(Def::Mod(def_id), name); + self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP)) } - pub fn macro_def_scope(&mut self, expansion: Mark, span: Span) -> Module<'a> { + pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> { let def_id = self.macro_defs[&expansion]; if let Some(id) = self.definitions.as_local_node_id(def_id) { self.local_macro_def_scopes[&id] @@ -519,7 +536,7 @@ impl<'a> Resolver<'a> { self.graph_root } else { let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap(); - self.get_extern_crate_root(module_def_id.krate, span) + self.get_module(module_def_id) } } @@ -766,7 +783,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { fn visit_block(&mut self, block: &'a Block) { let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); - self.resolver.build_reduced_graph_for_block(block); + self.resolver.build_reduced_graph_for_block(block, self.expansion); visit::walk_block(self, block); self.resolver.current_module = parent; self.legacy_scope = legacy_scope; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6d8ca09935c..180a608e631 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -43,7 +43,7 @@ use rustc::middle::cstore::CrateLoader; use rustc::session::Session; use rustc::lint; use rustc::hir::def::*; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; @@ -51,7 +51,7 @@ use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; -use syntax::ext::base::Determinacy::{Determined, Undetermined}; +use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::base::MacroKind; use syntax::symbol::{Symbol, keywords}; use syntax::util::lev_distance::find_best_match_for_name; @@ -861,6 +861,8 @@ pub struct ModuleData<'a> { /// Span of the module itself. Used for error reporting. span: Span, + + expansion: Mark, } pub type Module<'a> = &'a ModuleData<'a>; @@ -869,6 +871,7 @@ impl<'a> ModuleData<'a> { fn new(parent: Option<Module<'a>>, kind: ModuleKind, normal_ancestor_id: DefId, + expansion: Mark, span: Span) -> Self { ModuleData { parent: parent, @@ -884,6 +887,7 @@ impl<'a> ModuleData<'a> { traits: RefCell::new(None), populated: Cell::new(normal_ancestor_id.is_local()), span: span, + expansion: expansion, } } @@ -1165,7 +1169,7 @@ pub struct Resolver<'a> { // entry block for `f`. block_map: NodeMap<Module<'a>>, module_map: FxHashMap<DefId, Module<'a>>, - extern_crate_roots: FxHashMap<(CrateNum, bool /* MacrosOnly? */), Module<'a>>, + extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>, pub make_glob_map: bool, // Maps imports to the names of items actually imported (this actually maps @@ -1185,9 +1189,9 @@ pub struct Resolver<'a> { use_extern_macros: bool, // true if `#![feature(use_extern_macros)]` crate_loader: &'a mut CrateLoader, - macro_names: FxHashSet<Name>, + macro_names: FxHashSet<Ident>, global_macros: FxHashMap<Name, &'a NameBinding<'a>>, - lexical_macro_resolutions: Vec<(Name, &'a Cell<LegacyScope<'a>>)>, + lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>, macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>, macro_defs: FxHashMap<Mark, DefId>, local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>, @@ -1310,7 +1314,7 @@ impl<'a> Resolver<'a> { let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name()); let graph_root = arenas.alloc_module(ModuleData { no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"), - ..ModuleData::new(None, root_module_kind, root_def_id, krate.span) + ..ModuleData::new(None, root_module_kind, root_def_id, Mark::root(), krate.span) }); let mut module_map = FxHashMap(); module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root); @@ -1364,7 +1368,7 @@ impl<'a> Resolver<'a> { trait_map: NodeMap(), module_map: module_map, block_map: NodeMap(), - extern_crate_roots: FxHashMap(), + extern_module_map: FxHashMap(), make_glob_map: make_glob_map == MakeGlobMap::Yes, glob_map: NodeMap(), @@ -1449,9 +1453,11 @@ impl<'a> Resolver<'a> { parent: Module<'a>, kind: ModuleKind, normal_ancestor_id: DefId, + expansion: Mark, span: Span, ) -> Module<'a> { - self.arenas.alloc_module(ModuleData::new(Some(parent), kind, normal_ancestor_id, span)) + let module = ModuleData::new(Some(parent), kind, normal_ancestor_id, expansion, span); + self.arenas.alloc_module(module) } fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) @@ -1513,10 +1519,11 @@ impl<'a> Resolver<'a> { path_span: Span) -> Option<LexicalScopeBinding<'a>> { if ns == TypeNS { - ident = ident.unhygienize(); + ident.ctxt = ident.ctxt.modern(); } // Walk backwards up the ribs in scope. + let mut module = self.graph_root; for i in (0 .. self.ribs[ns].len()).rev() { if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() { // The ident resolves to a type parameter or local variable. @@ -1525,45 +1532,120 @@ impl<'a> Resolver<'a> { )); } - if let ModuleRibKind(module) = self.ribs[ns][i].kind { - let item = self.resolve_ident_in_module(module, ident, ns, false, - record_used, path_span); - if let Ok(binding) = item { - // The ident resolves to an item. - return Some(LexicalScopeBinding::Item(binding)); + module = match self.ribs[ns][i].kind { + ModuleRibKind(module) => module, + MacroDefinition(def) if def == self.macro_defs[&ident.ctxt.outer()] => { + // If an invocation of this macro created `ident`, give up on `ident` + // and switch to `ident`'s source from the macro definition. + ident.ctxt.remove_mark(); + continue } + _ => continue, + }; - if let ModuleKind::Block(..) = module.kind { // We can see through blocks - } else if !module.no_implicit_prelude { - return self.prelude.and_then(|prelude| { - self.resolve_ident_in_module(prelude, ident, ns, false, - false, path_span).ok() - }).map(LexicalScopeBinding::Item) - } else { - return None; - } + let item = self.resolve_ident_in_module_unadjusted( + module, ident, ns, false, record_used, path_span, + ); + if let Ok(binding) = item { + // The ident resolves to an item. + return Some(LexicalScopeBinding::Item(binding)); } - if let MacroDefinition(def) = self.ribs[ns][i].kind { - // If an invocation of this macro created `ident`, give up on `ident` - // and switch to `ident`'s source from the macro definition. - let ctxt_data = ident.ctxt.data(); - if def == self.macro_defs[&ctxt_data.outer_mark] { - ident.ctxt = ctxt_data.prev_ctxt; - } + match module.kind { + ModuleKind::Block(..) => {}, // We can see through blocks + _ => break, + } + } + + ident.ctxt = ident.ctxt.modern(); + loop { + module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.ctxt), break); + let orig_current_module = self.current_module; + self.current_module = module; // Lexical resolutions can never be a privacy error. + let result = self.resolve_ident_in_module_unadjusted( + module, ident, ns, false, record_used, path_span, + ); + self.current_module = orig_current_module; + + match result { + Ok(binding) => return Some(LexicalScopeBinding::Item(binding)), + Err(Undetermined) => return None, + Err(Determined) => {} + } + } + + match self.prelude { + Some(prelude) if !module.no_implicit_prelude => { + self.resolve_ident_in_module_unadjusted(prelude, ident, ns, false, false, path_span) + .ok().map(LexicalScopeBinding::Item) + } + _ => None, + } + } + + fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, ctxt: &mut SyntaxContext) + -> Option<Module<'a>> { + if !module.expansion.is_descendant_of(ctxt.outer()) { + return Some(self.macro_def_scope(ctxt.remove_mark())); + } + + if let ModuleKind::Block(..) = module.kind { + return Some(module.parent.unwrap()); + } + + let mut module_expansion = module.expansion.modern(); // for backward compatability + while let Some(parent) = module.parent { + let parent_expansion = parent.expansion.modern(); + if module_expansion.is_descendant_of(parent_expansion) && + parent_expansion != module_expansion { + return if parent_expansion.is_descendant_of(ctxt.outer()) { + Some(parent) + } else { + None + }; } + module = parent; + module_expansion = parent_expansion; } None } - fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext, span: Span) -> Module<'a> { - let mut ctxt_data = crate_var_ctxt.data(); - while ctxt_data.prev_ctxt != SyntaxContext::empty() { - ctxt_data = ctxt_data.prev_ctxt.data(); + fn resolve_ident_in_module(&mut self, + module: Module<'a>, + mut ident: Ident, + ns: Namespace, + ignore_unresolved_invocations: bool, + record_used: bool, + span: Span) + -> Result<&'a NameBinding<'a>, Determinacy> { + ident.ctxt = ident.ctxt.modern(); + let orig_current_module = self.current_module; + if let Some(def) = ident.ctxt.adjust(module.expansion) { + self.current_module = self.macro_def_scope(def); + } + let result = self.resolve_ident_in_module_unadjusted( + module, ident, ns, ignore_unresolved_invocations, record_used, span, + ); + self.current_module = orig_current_module; + result + } + + fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext) -> Module<'a> { + let module = match ctxt.adjust(Mark::root()) { + Some(def) => self.macro_def_scope(def), + None => return self.graph_root, + }; + self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.normal_ancestor_id }) + } + + fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> { + let mut module = self.get_module(module.normal_ancestor_id); + while module.span.ctxt.modern() != *ctxt { + let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark())); + module = self.get_module(parent.normal_ancestor_id); } - let module = self.macro_def_scope(ctxt_data.outer_mark, span); - if module.is_local() { self.graph_root } else { module } + module } // AST resolution @@ -1611,15 +1693,12 @@ impl<'a> Resolver<'a> { fn search_label(&self, mut ident: Ident) -> Option<Def> { for rib in self.label_ribs.iter().rev() { match rib.kind { - NormalRibKind => { - // Continue - } + NormalRibKind => {} + // If an invocation of this macro created `ident`, give up on `ident` + // and switch to `ident`'s source from the macro definition. MacroDefinition(def) => { - // If an invocation of this macro created `ident`, give up on `ident` - // and switch to `ident`'s source from the macro definition. - let ctxt_data = ident.ctxt.data(); - if def == self.macro_defs[&ctxt_data.outer_mark] { - ident.ctxt = ctxt_data.prev_ctxt; + if def == self.macro_defs[&ident.ctxt.outer()] { + ident.ctxt.remove_mark(); } } _ => { @@ -1751,7 +1830,7 @@ impl<'a> Resolver<'a> { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = FxHashMap(); for type_parameter in &generics.ty_params { - let ident = type_parameter.ident.unhygienize(); + let ident = type_parameter.ident.modern(); debug!("with_type_parameter_rib: {}", type_parameter.id); if seen_bindings.contains_key(&ident) { @@ -2504,7 +2583,7 @@ impl<'a> Resolver<'a> { } let is_global = self.global_macros.get(&path[0].name).cloned() .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false); - if primary_ns != MacroNS && (is_global || self.macro_names.contains(&path[0].name)) { + if primary_ns != MacroNS && (is_global || self.macro_names.contains(&path[0].modern())) { // Return some dummy definition, it's enough for error reporting. return Some( PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang)) @@ -2613,13 +2692,17 @@ impl<'a> Resolver<'a> { let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; if i == 0 && ns == TypeNS && ident.name == keywords::SelfValue.name() { - module = Some(self.module_map[&self.current_module.normal_ancestor_id]); + let mut ctxt = ident.ctxt.modern(); + module = Some(self.resolve_self(&mut ctxt, self.current_module)); continue } else if allow_super && ns == TypeNS && ident.name == keywords::Super.name() { - let current_module = if i == 0 { self.current_module } else { module.unwrap() }; - let self_module = self.module_map[¤t_module.normal_ancestor_id]; + let mut ctxt = ident.ctxt.modern(); + let self_module = match i { + 0 => self.resolve_self(&mut ctxt, self.current_module), + _ => module.unwrap(), + }; if let Some(parent) = self_module.parent { - module = Some(self.module_map[&parent.normal_ancestor_id]); + module = Some(self.resolve_self(&mut ctxt, parent)); continue } else { let msg = "There are too many initial `super`s.".to_string(); @@ -2629,10 +2712,10 @@ impl<'a> Resolver<'a> { allow_super = false; if i == 0 && ns == TypeNS && ident.name == keywords::CrateRoot.name() { - module = Some(self.graph_root); + module = Some(self.resolve_crate_root(ident.ctxt.modern())); continue } else if i == 0 && ns == TypeNS && ident.name == "$crate" { - module = Some(self.resolve_crate_var(ident.ctxt, path_span)); + module = Some(self.resolve_crate_root(ident.ctxt)); continue } @@ -3108,7 +3191,8 @@ impl<'a> Resolver<'a> { } } - fn get_traits_containing_item(&mut self, ident: Ident, ns: Namespace) -> Vec<TraitCandidate> { + fn get_traits_containing_item(&mut self, mut ident: Ident, ns: Namespace) + -> Vec<TraitCandidate> { debug!("(getting traits containing item) looking for '{}'", ident.name); let mut found_traits = Vec::new(); @@ -3120,13 +3204,12 @@ impl<'a> Resolver<'a> { } } + ident.ctxt = ident.ctxt.modern(); let mut search_module = self.current_module; loop { self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits); - match search_module.kind { - ModuleKind::Block(..) => search_module = search_module.parent.unwrap(), - _ => break, - } + search_module = + unwrap_or!(self.hygienic_lexical_parent(search_module, &mut ident.ctxt), break); } if let Some(prelude) = self.prelude { @@ -3157,7 +3240,12 @@ impl<'a> Resolver<'a> { for &(trait_name, binding) in traits.as_ref().unwrap().iter() { let module = binding.module().unwrap(); - if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() { + let mut ident = ident; + if ident.ctxt.glob_adjust(module.expansion, binding.span.ctxt.modern()).is_none() { + continue + } + if self.resolve_ident_in_module_unadjusted(module, ident, ns, false, false, module.span) + .is_ok() { let import_id = match binding.kind { NameBindingKind::Import { directive, .. } => { self.maybe_unused_trait_imports.insert(directive.id); @@ -3348,15 +3436,15 @@ impl<'a> Resolver<'a> { } fn report_shadowing_errors(&mut self) { - for (name, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) { - self.resolve_legacy_scope(scope, name, true); + for (ident, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) { + self.resolve_legacy_scope(scope, ident, true); } let mut reported_errors = FxHashSet(); for binding in replace(&mut self.disallowed_shadowing, Vec::new()) { - if self.resolve_legacy_scope(&binding.parent, binding.name, false).is_some() && - reported_errors.insert((binding.name, binding.span)) { - let msg = format!("`{}` is already in scope", binding.name); + if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() && + reported_errors.insert((binding.ident, binding.span)) { + let msg = format!("`{}` is already in scope", binding.ident); self.session.struct_span_err(binding.span, &msg) .note("macro-expanded `macro_rules!`s may not shadow \ existing macros (see RFC 1560)") diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index bf21344330b..9aba892e0ff 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -76,7 +76,7 @@ pub enum LegacyScope<'a> { pub struct LegacyBinding<'a> { pub parent: Cell<LegacyScope<'a>>, - pub name: ast::Name, + pub ident: Ident, def_id: DefId, pub span: Span, } @@ -110,7 +110,7 @@ impl<'a> base::Resolver for Resolver<'a> { } fn get_module_scope(&mut self, id: ast::NodeId) -> Mark { - let mark = Mark::fresh(); + let mark = Mark::fresh(Mark::root()); let module = self.module_map[&self.definitions.local_def_id(id)]; self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData { module: Cell::new(module), @@ -130,7 +130,7 @@ impl<'a> base::Resolver for Resolver<'a> { let ident = path.segments[0].identifier; if ident.name == "$crate" { path.segments[0].identifier.name = keywords::CrateRoot.name(); - let module = self.0.resolve_crate_var(ident.ctxt, self.1); + let module = self.0.resolve_crate_root(ident.ctxt); if !module.is_local() { let span = path.segments[0].span; path.segments.insert(1, match module.kind { @@ -292,7 +292,11 @@ impl<'a> base::Resolver for Resolver<'a> { }; self.macro_defs.insert(invoc.expansion_data.mark, def.def_id()); self.unused_macros.remove(&def.def_id()); - Ok(Some(self.get_macro(def))) + let ext = self.get_macro(def); + if ext.is_modern() { + invoc.expansion_data.mark.set_modern(); + } + Ok(Some(ext)) } fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) @@ -416,8 +420,7 @@ impl<'a> Resolver<'a> { return def; } - let name = path[0].name; - let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, name, false); + let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false); let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution { Ok(Def::Macro(binding.def_id, MacroKind::Bang)) } else { @@ -439,26 +442,31 @@ impl<'a> Resolver<'a> { // Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`) pub fn resolve_lexical_macro_path_segment(&mut self, - ident: Ident, + mut ident: Ident, ns: Namespace, record_used: bool, path_span: Span) -> Result<MacroBinding<'a>, Determinacy> { + ident = ident.modern(); let mut module = Some(self.current_module); let mut potential_illegal_shadower = Err(Determinacy::Determined); let determinacy = if record_used { Determinacy::Determined } else { Determinacy::Undetermined }; loop { + let orig_current_module = self.current_module; let result = if let Some(module) = module { + self.current_module = module; // Lexical resolutions can never be a privacy error. // Since expanded macros may not shadow the lexical scope and // globs may not shadow global macros (both enforced below), // we resolve with restricted shadowing (indicated by the penultimate argument). - self.resolve_ident_in_module(module, ident, ns, true, record_used, path_span) - .map(MacroBinding::Modern) + self.resolve_ident_in_module_unadjusted( + module, ident, ns, true, record_used, path_span, + ).map(MacroBinding::Modern) } else { self.global_macros.get(&ident.name).cloned().ok_or(determinacy) .map(MacroBinding::Global) }; + self.current_module = orig_current_module; match result.map(MacroBinding::binding) { Ok(binding) => { @@ -491,10 +499,7 @@ impl<'a> Resolver<'a> { } module = match module { - Some(module) => match module.kind { - ModuleKind::Block(..) => module.parent, - ModuleKind::Def(..) => None, - }, + Some(module) => self.hygienic_lexical_parent(module, &mut ident.ctxt), None => return potential_illegal_shadower, } } @@ -502,9 +507,10 @@ impl<'a> Resolver<'a> { pub fn resolve_legacy_scope(&mut self, mut scope: &'a Cell<LegacyScope<'a>>, - name: Name, + ident: Ident, record_used: bool) -> Option<MacroBinding<'a>> { + let ident = ident.modern(); let mut possible_time_travel = None; let mut relative_depth: u32 = 0; let mut binding = None; @@ -531,7 +537,7 @@ impl<'a> Resolver<'a> { scope = &invocation.legacy_scope; } LegacyScope::Binding(potential_binding) => { - if potential_binding.name == name { + if potential_binding.ident == ident { if (!self.use_extern_macros || record_used) && relative_depth > 0 { self.disallowed_shadowing.push(potential_binding); } @@ -545,9 +551,9 @@ impl<'a> Resolver<'a> { let binding = if let Some(binding) = binding { MacroBinding::Legacy(binding) - } else if let Some(binding) = self.global_macros.get(&name).cloned() { + } else if let Some(binding) = self.global_macros.get(&ident.name).cloned() { if !self.use_extern_macros { - self.record_use(Ident::with_empty_ctxt(name), MacroNS, binding, DUMMY_SP); + self.record_use(ident, MacroNS, binding, DUMMY_SP); } MacroBinding::Global(binding) } else { @@ -557,7 +563,7 @@ impl<'a> Resolver<'a> { if !self.use_extern_macros { if let Some(scope) = possible_time_travel { // Check for disallowed shadowing later - self.lexical_macro_resolutions.push((name, scope)); + self.lexical_macro_resolutions.push((ident, scope)); } } @@ -578,7 +584,7 @@ impl<'a> Resolver<'a> { for &(mark, ident, span, kind) in module.legacy_macro_resolutions.borrow().iter() { let legacy_scope = &self.invocations[&mark].legacy_scope; - let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true); + let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident, true); let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, span); match (legacy_resolution, resolution) { (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => { @@ -615,7 +621,7 @@ impl<'a> Resolver<'a> { err: &mut DiagnosticBuilder<'a>, span: Span) { // First check if this is a locally-defined bang macro. let suggestion = if let MacroKind::Bang = kind { - find_best_match_for_name(self.macro_names.iter(), name, None) + find_best_match_for_name(self.macro_names.iter().map(|ident| &ident.name), name, None) } else { None // Then check global macros. @@ -705,9 +711,10 @@ impl<'a> Resolver<'a> { let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() }; if def.legacy { - self.macro_names.insert(ident.name); + let ident = ident.modern(); + self.macro_names.insert(ident); *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding { - parent: Cell::new(*legacy_scope), name: ident.name, def_id: def_id, span: item.span, + parent: Cell::new(*legacy_scope), ident: ident, def_id: def_id, span: item.span, })); if attr::contains_name(&item.attrs, "macro_export") { let def = Def::Macro(def_id, MacroKind::Bang); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index fdca931ad47..f304aad4638 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -134,21 +134,20 @@ impl<'a> NameResolution<'a> { impl<'a> Resolver<'a> { fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace) -> &'a RefCell<NameResolution<'a>> { - let ident = ident.unhygienize(); - *module.resolutions.borrow_mut().entry((ident, ns)) + *module.resolutions.borrow_mut().entry((ident.modern(), ns)) .or_insert_with(|| self.arenas.alloc_name_resolution()) } /// Attempts to resolve `ident` in namespaces `ns` of `module`. /// Invariant: if `record_used` is `Some`, import resolution must be complete. - pub fn resolve_ident_in_module(&mut self, - module: Module<'a>, - ident: Ident, - ns: Namespace, - restricted_shadowing: bool, - record_used: bool, - path_span: Span) - -> Result<&'a NameBinding<'a>, Determinacy> { + pub fn resolve_ident_in_module_unadjusted(&mut self, + module: Module<'a>, + ident: Ident, + ns: Namespace, + restricted_shadowing: bool, + record_used: bool, + path_span: Span) + -> Result<&'a NameBinding<'a>, Determinacy> { self.populate_module_if_necessary(module); let resolution = self.resolution(module, ident, ns) @@ -233,20 +232,22 @@ impl<'a> Resolver<'a> { return Err(Determined); } for directive in module.globs.borrow().iter() { - if self.is_accessible(directive.vis.get()) { - if let Some(module) = directive.imported_module.get() { - let result = self.resolve_ident_in_module(module, - ident, - ns, - false, - false, - path_span); - if let Err(Undetermined) = result { - return Err(Undetermined); - } - } else { - return Err(Undetermined); - } + if !self.is_accessible(directive.vis.get()) { + continue + } + let module = unwrap_or!(directive.imported_module.get(), return Err(Undetermined)); + let (orig_current_module, mut ident) = (self.current_module, ident.modern()); + match ident.ctxt.glob_adjust(module.expansion, directive.span.ctxt.modern()) { + Some(Some(def)) => self.current_module = self.macro_def_scope(def), + Some(None) => {} + None => continue, + }; + let result = self.resolve_ident_in_module_unadjusted( + module, ident, ns, false, false, path_span, + ); + self.current_module = orig_current_module; + if let Err(Undetermined) = result { + return Err(Undetermined); } } @@ -394,7 +395,14 @@ impl<'a> Resolver<'a> { // Define `binding` in `module`s glob importers. for directive in module.glob_importers.borrow_mut().iter() { - if self.is_accessible_from(binding.vis, directive.parent) { + let mut ident = ident.modern(); + let scope = match ident.ctxt.reverse_glob_adjust(module.expansion, + directive.span.ctxt.modern()) { + Some(Some(def)) => self.macro_def_scope(def), + Some(None) => directive.parent, + None => continue, + }; + if self.is_accessible_from(binding.vis, scope) { let imported_binding = self.import(binding, directive); let _ = self.try_define(directive.parent, ident, ns, imported_binding); } @@ -767,8 +775,14 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| { resolution.borrow().binding().map(|binding| (ident, binding)) }).collect::<Vec<_>>(); - for ((ident, ns), binding) in bindings { - if binding.pseudo_vis() == ty::Visibility::Public || self.is_accessible(binding.vis) { + for ((mut ident, ns), binding) in bindings { + let scope = match ident.ctxt.reverse_glob_adjust(module.expansion, + directive.span.ctxt.modern()) { + Some(Some(def)) => self.macro_def_scope(def), + Some(None) => self.current_module, + None => continue, + }; + if self.is_accessible_from(binding.pseudo_vis(), scope) { let imported_binding = self.import(binding, directive); let _ = self.try_define(directive.parent, ident, ns, imported_binding); } |
