From 18ad750786b00420eaaa33535195832be0fc3b92 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 23 Mar 2022 14:30:04 +0100 Subject: [PATCH] fix: properly import all types of macros with #[macro_use] again --- crates/hir/src/symbols.rs | 11 ++++--- crates/hir_def/src/child_by_source.rs | 8 +++-- crates/hir_def/src/item_scope.rs | 13 ++++---- crates/hir_def/src/nameres/collector.rs | 10 +++--- crates/hir_def/src/nameres/tests/macros.rs | 37 ++++++++++++++++++++++ 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs index 858293a345c..bdb8c7552d3 100644 --- a/crates/hir/src/symbols.rs +++ b/crates/hir/src/symbols.rs @@ -3,7 +3,7 @@ use base_db::FileRange; use hir_def::{ item_tree::ItemTreeNode, src::HasSource, AdtId, AssocItemId, AssocItemLoc, DefWithBodyId, - ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, + HasModule, ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, }; use hir_expand::{HirFileId, InFile}; use hir_ty::db::HirDatabase; @@ -176,9 +176,12 @@ impl<'a> SymbolCollector<'a> { } for (_, id) in scope.legacy_macros() { - let loc = id.lookup(self.db.upcast()); - if loc.container == module_id { - self.push_decl(id, FileSymbolKind::Macro); + if id.module(self.db.upcast()) == module_id { + match id { + MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro), + MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro), + MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro), + } } } } diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index 6a2212f1994..b1337ecc242 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs @@ -103,9 +103,11 @@ impl ChildBySource for ItemScope { }, ); self.legacy_macros().for_each(|(_, id)| { - let loc = id.lookup(db); - if loc.id.file_id() == file_id { - res[keys::MACRO_RULES].insert(loc.source(db).value, id); + if let MacroId::MacroRulesId(id) = id { + let loc = id.lookup(db); + if loc.id.file_id() == file_id { + res[keys::MACRO_RULES].insert(loc.source(db).value, id); + } } }); self.derive_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each( diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 0096df2288d..ddccbbfef9c 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs @@ -14,8 +14,7 @@ use syntax::ast; use crate::{ attr::AttrId, db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, - ConstId, HasModule, ImplId, LocalModuleId, MacroId, MacroRulesId, ModuleDefId, ModuleId, - TraitId, + ConstId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId, }; #[derive(Copy, Clone)] @@ -62,7 +61,7 @@ pub struct ItemScope { /// Module scoped macros will be inserted into `items` instead of here. // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will // be all resolved to the last one defined if shadowing happens. - legacy_macros: FxHashMap, + legacy_macros: FxHashMap, /// The derive macro invocations in this scope. attr_macros: FxHashMap, MacroCallId>, /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes @@ -135,7 +134,7 @@ impl ItemScope { } /// Iterate over all legacy textual scoped macros visible at the end of the module - pub fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { + pub fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { self.legacy_macros.iter().map(|(name, def)| (name, *def)) } @@ -181,7 +180,7 @@ impl ItemScope { self.declarations.push(def) } - pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option { + pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option { self.legacy_macros.get(name).copied() } @@ -193,7 +192,7 @@ impl ItemScope { self.unnamed_consts.push(konst); } - pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroRulesId) { + pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroId) { self.legacy_macros.insert(name, mac); } @@ -323,7 +322,7 @@ impl ItemScope { ) } - pub(crate) fn collect_legacy_macros(&self) -> FxHashMap { + pub(crate) fn collect_legacy_macros(&self) -> FxHashMap { self.legacy_macros.clone() } diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index ea29f804373..4660ccf5007 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -610,7 +610,7 @@ impl DefCollector<'_> { export: bool, ) { // Textual scoping - self.define_legacy_macro(module_id, name.clone(), macro_); + self.define_legacy_macro(module_id, name.clone(), macro_.into()); // Module scoping // In Rust, `#[macro_export]` macros are unconditionally visible at the @@ -634,7 +634,7 @@ impl DefCollector<'_> { /// the definition of current module. /// And also, `macro_use` on a module will import all legacy macros visible inside to /// current legacy scope, with possible shadowing. - fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroRulesId) { + fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroId) { // Always shadowing self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); } @@ -706,10 +706,8 @@ impl DefCollector<'_> { fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) { let def_map = self.db.crate_def_map(krate); for (name, def) in def_map[def_map.root].scope.macros() { - if let MacroId::MacroRulesId(def) = def { - // `macro_use` only bring things into legacy scope. - self.define_legacy_macro(current_module_id, name.clone(), def); - } + // `#[macro_use]` brings macros into legacy scope. Yes, even non-`macro_rules!` macros. + self.define_legacy_macro(current_module_id, name.clone(), def); } } diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index 222e524d6c0..411840ccbcc 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs @@ -1143,3 +1143,40 @@ struct A; "#]], ); } + +#[test] +fn macro_use_imports_all_macro_types() { + let def_map = compute_crate_def_map( + r#" +//- /main.rs crate:main deps:lib +#[macro_use] +extern crate lib; + +//- /lib.rs crate:lib deps:proc +pub use proc::*; + +#[macro_export] +macro_rules! legacy { () => () } + +pub macro macro20 {} + +//- /proc.rs crate:proc +#![crate_type="proc-macro"] + +struct TokenStream; + +#[proc_macro_attribute] +fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a } + "#, + ); + + let root = &def_map[def_map.root()].scope; + let actual = root.legacy_macros().map(|(name, _)| format!("{name}\n")).collect::(); + + expect![[r#" + macro20 + legacy + proc_attr + "#]] + .assert_eq(&actual); +}