about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRyo Yoshida <low.ryoshida@gmail.com>2023-05-11 15:52:13 +0900
committerRyo Yoshida <low.ryoshida@gmail.com>2023-05-11 21:13:12 +0900
commitf2a35deb50fb5c6e28c5eddbd6a4cffd47ddb444 (patch)
treeb851a751b76e722a4a91afec64cb85f9c0ee80d9
parent3203ea896d1ed9f6b8a8af25a8028df51a6bd5b3 (diff)
downloadrust-f2a35deb50fb5c6e28c5eddbd6a4cffd47ddb444.tar.gz
rust-f2a35deb50fb5c6e28c5eddbd6a4cffd47ddb444.zip
Consider macro sub-namespace during name resolution
-rw-r--r--crates/hir-def/src/body/lower.rs11
-rw-r--r--crates/hir-def/src/data.rs3
-rw-r--r--crates/hir-def/src/find_path.rs1
-rw-r--r--crates/hir-def/src/generics.rs3
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mod.rs13
-rw-r--r--crates/hir-def/src/nameres.rs62
-rw-r--r--crates/hir-def/src/nameres/attr_resolution.rs5
-rw-r--r--crates/hir-def/src/nameres/collector.rs21
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs45
-rw-r--r--crates/hir-def/src/nameres/tests/macros.rs54
-rw-r--r--crates/hir-def/src/resolver.rs20
-rw-r--r--crates/hir-ty/src/lower.rs13
-rw-r--r--crates/hir/src/attrs.rs1
-rw-r--r--crates/hir/src/semantics.rs3
-rw-r--r--crates/hir/src/source_analyzer.rs17
15 files changed, 236 insertions, 36 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index 80aa1af057c..d92698a938a 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -37,7 +37,7 @@ use crate::{
     item_scope::BuiltinShadowMode,
     lang_item::LangItem,
     lower::LowerCtx,
-    nameres::DefMap,
+    nameres::{DefMap, MacroSubNs},
     path::{GenericArgs, Path},
     type_ref::{Mutability, Rawness, TypeRef},
     AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
@@ -800,7 +800,13 @@ impl ExprCollector<'_> {
         let module = self.expander.module.local_id;
         let res = self.expander.enter_expand(self.db, mcall, |path| {
             self.def_map
-                .resolve_path(self.db, module, &path, crate::item_scope::BuiltinShadowMode::Other)
+                .resolve_path(
+                    self.db,
+                    module,
+                    &path,
+                    crate::item_scope::BuiltinShadowMode::Other,
+                    Some(MacroSubNs::Bang),
+                )
                 .0
                 .take_macros()
         });
@@ -1056,6 +1062,7 @@ impl ExprCollector<'_> {
                         self.expander.module.local_id,
                         &name.clone().into(),
                         BuiltinShadowMode::Other,
+                        None,
                     );
                     match resolved.take_values() {
                         Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index de67f0b23cf..40e6a430878 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -22,7 +22,7 @@ use crate::{
         attr_resolution::ResolvedAttr,
         diagnostics::DefDiagnostic,
         proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
-        DefMap,
+        DefMap, MacroSubNs,
     },
     type_ref::{TraitRef, TypeBound, TypeRef},
     visibility::RawVisibility,
@@ -673,6 +673,7 @@ impl<'a> AssocItemCollector<'a> {
                             module,
                             &path,
                             crate::item_scope::BuiltinShadowMode::Other,
+                            Some(MacroSubNs::Bang),
                         )
                         .0
                         .take_macros()
diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs
index 30d6d019309..b401762255e 100644
--- a/crates/hir-def/src/find_path.rs
+++ b/crates/hir-def/src/find_path.rs
@@ -543,6 +543,7 @@ mod tests {
                 module.local_id,
                 &mod_path,
                 crate::item_scope::BuiltinShadowMode::Module,
+                None,
             )
             .0
             .take_types()
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index c79c1709630..f19c3f028f4 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -22,7 +22,7 @@ use crate::{
     dyn_map::{keys, DynMap},
     expander::Expander,
     lower::LowerCtx,
-    nameres::DefMap,
+    nameres::{DefMap, MacroSubNs},
     src::{HasChildSource, HasSource},
     type_ref::{LifetimeRef, TypeBound, TypeRef},
     AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId,
@@ -361,6 +361,7 @@ impl GenericParams {
                             module,
                             &path,
                             crate::item_scope::BuiltinShadowMode::Other,
+                            Some(MacroSubNs::Bang),
                         )
                         .0
                         .take_macros()
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index a59a3dc81ef..40849d4a66d 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -33,8 +33,13 @@ use syntax::{
 use tt::token_id::{Subtree, TokenId};
 
 use crate::{
-    db::DefDatabase, macro_id_to_def_id, nameres::ModuleSource, resolver::HasResolver,
-    src::HasSource, test_db::TestDB, AdtId, AsMacroCall, Lookup, ModuleDefId,
+    db::DefDatabase,
+    macro_id_to_def_id,
+    nameres::{MacroSubNs, ModuleSource},
+    resolver::HasResolver,
+    src::HasSource,
+    test_db::TestDB,
+    AdtId, AsMacroCall, Lookup, ModuleDefId,
 };
 
 #[track_caller]
@@ -127,7 +132,9 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
         let macro_call = InFile::new(source.file_id, &macro_call);
         let res = macro_call
             .as_call_id_with_errors(&db, krate, |path| {
-                resolver.resolve_path_as_macro(&db, &path).map(|it| macro_id_to_def_id(&db, it))
+                resolver
+                    .resolve_path_as_macro(&db, &path, Some(MacroSubNs::Bang))
+                    .map(|it| macro_id_to_def_id(&db, it))
             })
             .unwrap();
         let macro_call_id = res.value.unwrap();
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 2e5f090ce76..39a56814ed8 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -59,7 +59,7 @@ mod tests;
 
 use std::{cmp::Ord, ops::Deref};
 
-use base_db::{CrateId, Edition, FileId};
+use base_db::{CrateId, Edition, FileId, ProcMacroKind};
 use hir_expand::{name::Name, InFile, MacroCallId, MacroDefId};
 use itertools::Itertools;
 use la_arena::Arena;
@@ -77,7 +77,8 @@ use crate::{
     path::ModPath,
     per_ns::PerNs,
     visibility::Visibility,
-    AstId, BlockId, BlockLoc, FunctionId, LocalModuleId, MacroId, ModuleId, ProcMacroId,
+    AstId, BlockId, BlockLoc, FunctionId, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId,
+    ProcMacroId,
 };
 
 /// Contains the results of (early) name resolution.
@@ -380,9 +381,16 @@ impl DefMap {
         original_module: LocalModuleId,
         path: &ModPath,
         shadow: BuiltinShadowMode,
+        expected_macro_subns: Option<MacroSubNs>,
     ) -> (PerNs, Option<usize>) {
-        let res =
-            self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
+        let res = self.resolve_path_fp_with_macro(
+            db,
+            ResolveMode::Other,
+            original_module,
+            path,
+            shadow,
+            expected_macro_subns,
+        );
         (res.resolved_def, res.segment_index)
     }
 
@@ -399,6 +407,7 @@ impl DefMap {
             original_module,
             path,
             shadow,
+            None, // Currently this function isn't used for macro resolution.
         );
         (res.resolved_def, res.segment_index)
     }
@@ -568,3 +577,48 @@ pub enum ModuleSource {
     Module(ast::Module),
     BlockExpr(ast::BlockExpr),
 }
+
+/// See `sub_namespace_match()`.
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum MacroSubNs {
+    /// Function-like macros, suffixed with `!`.
+    Bang,
+    /// Macros inside attributes, i.e. attribute macros and derive macros.
+    Attr,
+}
+
+impl MacroSubNs {
+    fn from_id(db: &dyn DefDatabase, macro_id: MacroId) -> Self {
+        let expander = match macro_id {
+            MacroId::Macro2Id(it) => it.lookup(db).expander,
+            MacroId::MacroRulesId(it) => it.lookup(db).expander,
+            MacroId::ProcMacroId(it) => {
+                return match it.lookup(db).kind {
+                    ProcMacroKind::CustomDerive | ProcMacroKind::Attr => Self::Attr,
+                    ProcMacroKind::FuncLike => Self::Bang,
+                };
+            }
+        };
+
+        // Eager macros aren't *guaranteed* to be bang macros, but they *are* all bang macros currently.
+        match expander {
+            MacroExpander::Declarative
+            | MacroExpander::BuiltIn(_)
+            | MacroExpander::BuiltInEager(_) => Self::Bang,
+            MacroExpander::BuiltInAttr(_) | MacroExpander::BuiltInDerive(_) => Self::Attr,
+        }
+    }
+}
+
+/// Quoted from [rustc]:
+/// Macro namespace is separated into two sub-namespaces, one for bang macros and
+/// one for attribute-like macros (attributes, derives).
+/// We ignore resolutions from one sub-namespace when searching names in scope for another.
+///
+/// [rustc]: https://github.com/rust-lang/rust/blob/1.69.0/compiler/rustc_resolve/src/macros.rs#L75
+fn sub_namespace_match(candidate: Option<MacroSubNs>, expected: Option<MacroSubNs>) -> bool {
+    match (candidate, expected) {
+        (Some(candidate), Some(expected)) => candidate == expected,
+        _ => true,
+    }
+}
diff --git a/crates/hir-def/src/nameres/attr_resolution.rs b/crates/hir-def/src/nameres/attr_resolution.rs
index 84271ef51d8..6567bda709d 100644
--- a/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/crates/hir-def/src/nameres/attr_resolution.rs
@@ -14,7 +14,7 @@ use crate::{
     AstIdWithPath, LocalModuleId, UnresolvedMacro,
 };
 
-use super::DefMap;
+use super::{DefMap, MacroSubNs};
 
 pub enum ResolvedAttr {
     /// Attribute resolved to an attribute macro.
@@ -43,9 +43,12 @@ impl DefMap {
             original_module,
             &ast_id.path,
             BuiltinShadowMode::Module,
+            Some(MacroSubNs::Attr),
         );
         let def = match resolved_res.resolved_def.take_macros() {
             Some(def) => {
+                // `MacroSubNs` is just a hint, so the path may still resolve to a custom derive
+                // macro, or even function-like macro when the path is qualified.
                 if def.is_attribute(db) {
                     def
                 } else {
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 84e9b9f5719..177edcbb7f2 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -44,7 +44,7 @@ use crate::{
         mod_resolution::ModDir,
         path_resolution::ReachedFixedPoint,
         proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
-        BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
+        BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
     },
     path::{ImportAlias, ModPath, PathKind},
     per_ns::PerNs,
@@ -549,8 +549,13 @@ impl DefCollector<'_> {
         };
         let path = ModPath::from_segments(path_kind, [krate, name![prelude], edition]);
 
-        let (per_ns, _) =
-            self.def_map.resolve_path(self.db, self.def_map.root, &path, BuiltinShadowMode::Other);
+        let (per_ns, _) = self.def_map.resolve_path(
+            self.db,
+            self.def_map.root,
+            &path,
+            BuiltinShadowMode::Other,
+            None,
+        );
 
         match per_ns.types {
             Some((ModuleDefId::ModuleId(m), _)) => {
@@ -796,6 +801,7 @@ impl DefCollector<'_> {
                 module_id,
                 &import.path,
                 BuiltinShadowMode::Module,
+                None, // An import may resolve to any kind of macro.
             );
 
             let def = res.resolved_def;
@@ -1093,7 +1099,14 @@ impl DefCollector<'_> {
             resolved.push((directive.module_id, directive.depth, directive.container, call_id));
         };
         let mut res = ReachedFixedPoint::Yes;
+        // Retain unresolved macros after this round of resolution.
         macros.retain(|directive| {
+            let subns = match &directive.kind {
+                MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang,
+                MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => {
+                    MacroSubNs::Attr
+                }
+            };
             let resolver = |path| {
                 let resolved_res = self.def_map.resolve_path_fp_with_macro(
                     self.db,
@@ -1101,6 +1114,7 @@ impl DefCollector<'_> {
                     directive.module_id,
                     &path,
                     BuiltinShadowMode::Module,
+                    Some(subns),
                 );
                 resolved_res
                     .resolved_def
@@ -1419,6 +1433,7 @@ impl DefCollector<'_> {
                                 directive.module_id,
                                 &path,
                                 BuiltinShadowMode::Module,
+                                Some(MacroSubNs::Bang),
                             );
                             resolved_res
                                 .resolved_def
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index 5b454620e7b..4740fd7f449 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -16,7 +16,7 @@ use hir_expand::name::Name;
 use crate::{
     db::DefDatabase,
     item_scope::BUILTIN_SCOPE,
-    nameres::{BuiltinShadowMode, DefMap},
+    nameres::{sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs},
     path::{ModPath, PathKind},
     per_ns::PerNs,
     visibility::{RawVisibility, Visibility},
@@ -58,6 +58,17 @@ impl ResolvePathResult {
     }
 }
 
+impl PerNs {
+    fn filter_macro(mut self, db: &dyn DefDatabase, expected: Option<MacroSubNs>) -> Self {
+        self.macros = self.macros.filter(|&(id, _)| {
+            let this = MacroSubNs::from_id(db, id);
+            sub_namespace_match(Some(this), expected)
+        });
+
+        self
+    }
+}
+
 impl DefMap {
     pub(super) fn resolve_name_in_extern_prelude(
         &self,
@@ -83,7 +94,7 @@ impl DefMap {
         let mut vis = match visibility {
             RawVisibility::Module(path) => {
                 let (result, remaining) =
-                    self.resolve_path(db, original_module, path, BuiltinShadowMode::Module);
+                    self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None);
                 if remaining.is_some() {
                     return None;
                 }
@@ -124,6 +135,9 @@ impl DefMap {
         mut original_module: LocalModuleId,
         path: &ModPath,
         shadow: BuiltinShadowMode,
+        // Pass `MacroSubNs` if we know we're resolving macro names and which kind of macro we're
+        // resolving them to. Pass `None` otherwise, e.g. when we're resolving import paths.
+        expected_macro_subns: Option<MacroSubNs>,
     ) -> ResolvePathResult {
         let mut result = ResolvePathResult::empty(ReachedFixedPoint::No);
 
@@ -136,6 +150,7 @@ impl DefMap {
                 original_module,
                 path,
                 shadow,
+                expected_macro_subns,
             );
 
             // Merge `new` into `result`.
@@ -169,6 +184,7 @@ impl DefMap {
         original_module: LocalModuleId,
         path: &ModPath,
         shadow: BuiltinShadowMode,
+        expected_macro_subns: Option<MacroSubNs>,
     ) -> ResolvePathResult {
         let graph = db.crate_graph();
         let _cx = stdx::panic_context::enter(format!(
@@ -220,7 +236,13 @@ impl DefMap {
                     if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module };
 
                 tracing::debug!("resolving {:?} in module", segment);
-                self.resolve_name_in_module(db, original_module, segment, prefer_module)
+                self.resolve_name_in_module(
+                    db,
+                    original_module,
+                    segment,
+                    prefer_module,
+                    expected_macro_subns,
+                )
             }
             PathKind::Super(lvl) => {
                 let mut module = original_module;
@@ -245,6 +267,7 @@ impl DefMap {
                                     block.parent.local_id,
                                     &new_path,
                                     shadow,
+                                    expected_macro_subns,
                                 );
                             }
                             None => {
@@ -303,7 +326,12 @@ impl DefMap {
                         );
                         tracing::debug!("resolving {:?} in other crate", path);
                         let defp_map = module.def_map(db);
-                        let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
+                        // Macro sub-namespaces only matter when resolving single-segment paths
+                        // because `macro_use` and other preludes should be taken into account. At
+                        // this point, we know we're resolving a multi-segment path so macro kind
+                        // expectation is discarded.
+                        let (def, s) =
+                            defp_map.resolve_path(db, module.local_id, &path, shadow, None);
                         return ResolvePathResult::with(
                             def,
                             ReachedFixedPoint::Yes,
@@ -381,6 +409,7 @@ impl DefMap {
         module: LocalModuleId,
         name: &Name,
         shadow: BuiltinShadowMode,
+        expected_macro_subns: Option<MacroSubNs>,
     ) -> PerNs {
         // Resolve in:
         //  - legacy scope of macro
@@ -392,8 +421,12 @@ impl DefMap {
             .get_legacy_macro(name)
             // FIXME: shadowing
             .and_then(|it| it.last())
-            .map_or_else(PerNs::none, |&m| PerNs::macros(m, Visibility::Public));
-        let from_scope = self[module].scope.get(name);
+            .copied()
+            .filter(|&id| {
+                sub_namespace_match(Some(MacroSubNs::from_id(db, id)), expected_macro_subns)
+            })
+            .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public));
+        let from_scope = self[module].scope.get(name).filter_macro(db, expected_macro_subns);
         let from_builtin = match self.block {
             Some(_) => {
                 // Only resolve to builtins in the root `DefMap`.
diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs
index ea3209b9c20..e795b7b9b7e 100644
--- a/crates/hir-def/src/nameres/tests/macros.rs
+++ b/crates/hir-def/src/nameres/tests/macros.rs
@@ -1271,3 +1271,57 @@ pub mod prelude {
         "#]],
     );
 }
+
+#[test]
+fn macro_sub_namespace() {
+    let map = compute_crate_def_map(
+        r#"
+//- minicore: derive, clone
+macro_rules! Clone { () => {} }
+macro_rules! derive { () => {} }
+
+#[derive(Clone)]
+struct S;
+    "#,
+    );
+    assert_eq!(map.modules[map.root].scope.impls().len(), 1);
+}
+
+#[test]
+fn macro_sub_namespace2() {
+    check(
+        r#"
+//- /main.rs edition:2021 crate:main deps:proc,core
+use proc::{foo, bar};
+
+foo!();
+bar!();
+
+//- /proc.rs crate:proc
+#![crate_type="proc-macro"]
+#[proc_macro_derive(foo)]
+pub fn foo() {}
+#[proc_macro_attribute]
+pub fn bar() {}
+
+//- /core.rs crate:core
+pub mod prelude {
+    pub mod rust_2021 {
+        pub macro foo() {
+            struct Ok;
+        }
+        pub macro bar() {
+            fn ok() {}
+        }
+    }
+}
+    "#,
+        expect![[r#"
+            crate
+            Ok: t v
+            bar: m
+            foo: m
+            ok: v
+        "#]],
+    );
+}
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 45ec454b9eb..4bec2b4dea4 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -17,7 +17,7 @@ use crate::{
     hir::{BindingId, ExprId, LabelId},
     item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
     lang_item::LangItemTarget,
-    nameres::DefMap,
+    nameres::{DefMap, MacroSubNs},
     path::{ModPath, Path, PathKind},
     per_ns::PerNs,
     visibility::{RawVisibility, Visibility},
@@ -155,7 +155,8 @@ impl Resolver {
         path: &ModPath,
     ) -> Option<PerNs> {
         let (item_map, module) = self.item_scope();
-        let (module_res, idx) = item_map.resolve_path(db, module, path, BuiltinShadowMode::Module);
+        let (module_res, idx) =
+            item_map.resolve_path(db, module, path, BuiltinShadowMode::Module, None);
         match module_res.take_types()? {
             ModuleDefId::TraitId(it) => {
                 let idx = idx?;
@@ -385,9 +386,17 @@ impl Resolver {
         }
     }
 
-    pub fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroId> {
+    pub fn resolve_path_as_macro(
+        &self,
+        db: &dyn DefDatabase,
+        path: &ModPath,
+        expected_macro_kind: Option<MacroSubNs>,
+    ) -> Option<MacroId> {
         let (item_map, module) = self.item_scope();
-        item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros()
+        item_map
+            .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind)
+            .0
+            .take_macros()
     }
 
     /// Returns a set of names available in the current scope.
@@ -626,7 +635,8 @@ impl Resolver {
         shadow: BuiltinShadowMode,
     ) -> PerNs {
         let (item_map, module) = self.item_scope();
-        let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow);
+        // This method resolves `path` just like import paths, so no expected macro subns is given.
+        let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow, None);
         if segment_index.is_some() {
             return PerNs::none();
         }
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 4000ba5c14c..098b677b150 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -24,6 +24,7 @@ use hir_def::{
         TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
     },
     lang_item::{lang_attr, LangItem},
+    nameres::MacroSubNs,
     path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
     resolver::{HasResolver, Resolver, TypeNs},
     type_ref::{ConstRefOrPath, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
@@ -378,9 +379,15 @@ impl<'a> TyLoweringContext<'a> {
                 };
                 let ty = {
                     let macro_call = macro_call.to_node(self.db.upcast());
-                    match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, |path| {
-                        self.resolver.resolve_path_as_macro(self.db.upcast(), &path)
-                    }) {
+                    let resolver = |path| {
+                        self.resolver.resolve_path_as_macro(
+                            self.db.upcast(),
+                            &path,
+                            Some(MacroSubNs::Bang),
+                        )
+                    };
+                    match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, resolver)
+                    {
                         Ok(ExpandResult { value: Some((mark, expanded)), .. }) => {
                             let ctx = expander.ctx(self.db.upcast());
                             // FIXME: Report syntax errors in expansion here
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index f747b63d75c..b817937296d 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -120,6 +120,7 @@ impl HasAttrs for AssocItem {
     }
 }
 
+/// Resolves the item `link` points to in the scope of `def`.
 fn resolve_doc_path(
     db: &dyn HirDatabase,
     def: AttrDefId,
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 81ea99522f7..2d2b00b147e 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -10,6 +10,7 @@ use hir_def::{
     hir::Expr,
     lower::LowerCtx,
     macro_id_to_def_id,
+    nameres::MacroSubNs,
     resolver::{self, HasResolver, Resolver, TypeNs},
     type_ref::Mutability,
     AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId,
@@ -616,7 +617,7 @@ impl<'db> SemanticsImpl<'db> {
         let krate = resolver.krate();
         let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
             resolver
-                .resolve_path_as_macro(self.db.upcast(), &path)
+                .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
                 .map(|it| macro_id_to_def_id(self.db.upcast(), it))
         })?;
         hir_expand::db::expand_speculative(
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 159601955f8..dae77fad2f3 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -17,6 +17,7 @@ use hir_def::{
     lang_item::LangItem,
     lower::LowerCtx,
     macro_id_to_def_id,
+    nameres::MacroSubNs,
     path::{ModPath, Path, PathKind},
     resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
     type_ref::Mutability,
@@ -484,7 +485,9 @@ impl SourceAnalyzer {
     ) -> Option<Macro> {
         let ctx = LowerCtx::with_file_id(db.upcast(), macro_call.file_id);
         let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?;
-        self.resolver.resolve_path_as_macro(db.upcast(), path.mod_path()?).map(|it| it.into())
+        self.resolver
+            .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
+            .map(|it| it.into())
     }
 
     pub(crate) fn resolve_bind_pat_to_const(
@@ -678,7 +681,7 @@ impl SourceAnalyzer {
                     }
                 }
             }
-            return match resolve_hir_path_as_macro(db, &self.resolver, &hir_path) {
+            return match resolve_hir_path_as_attr_macro(db, &self.resolver, &hir_path) {
                 Some(m) => Some(PathResolution::Def(ModuleDef::Macro(m))),
                 // this labels any path that starts with a tool module as the tool itself, this is technically wrong
                 // but there is no benefit in differentiating these two cases for the time being
@@ -756,7 +759,7 @@ impl SourceAnalyzer {
         let krate = self.resolver.krate();
         let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
             self.resolver
-                .resolve_path_as_macro(db.upcast(), &path)
+                .resolve_path_as_macro(db.upcast(), &path, Some(MacroSubNs::Bang))
                 .map(|it| macro_id_to_def_id(db.upcast(), it))
         })?;
         Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64)
@@ -956,12 +959,14 @@ pub(crate) fn resolve_hir_path(
 }
 
 #[inline]
-pub(crate) fn resolve_hir_path_as_macro(
+pub(crate) fn resolve_hir_path_as_attr_macro(
     db: &dyn HirDatabase,
     resolver: &Resolver,
     path: &Path,
 ) -> Option<Macro> {
-    resolver.resolve_path_as_macro(db.upcast(), path.mod_path()?).map(Into::into)
+    resolver
+        .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Attr))
+        .map(Into::into)
 }
 
 fn resolve_hir_path_(
@@ -1060,7 +1065,7 @@ fn resolve_hir_path_(
 
     let macros = || {
         resolver
-            .resolve_path_as_macro(db.upcast(), path.mod_path()?)
+            .resolve_path_as_macro(db.upcast(), path.mod_path()?, None)
             .map(|def| PathResolution::Def(ModuleDef::Macro(def.into())))
     };