Unnamed repository; edit this file 'description' to name the repository.
-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/builtin_fn_macro.rs12
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe.rs4
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe/matching.rs2
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe/regression.rs20
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mod.rs14
-rw-r--r--crates/hir-def/src/nameres.rs68
-rw-r--r--crates/hir-def/src/nameres/attr_resolution.rs5
-rw-r--r--crates/hir-def/src/nameres/collector.rs211
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs58
-rw-r--r--crates/hir-def/src/nameres/tests/macros.rs111
-rw-r--r--crates/hir-def/src/resolver.rs20
-rw-r--r--crates/hir-expand/src/builtin_fn_macro.rs6
-rw-r--r--crates/hir-ty/src/lower.rs13
-rw-r--r--crates/hir-ty/src/tests/macros.rs6
-rw-r--r--crates/hir/src/attrs.rs6
-rw-r--r--crates/hir/src/semantics.rs3
-rw-r--r--crates/hir/src/source_analyzer.rs17
21 files changed, 425 insertions, 169 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index 80aa1af057..d92698a938 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 de67f0b23c..40e6a43087 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 30d6d01930..b401762255 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 c79c170963..f19c3f028f 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/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 0b72ca1eec..6cb741dac7 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -13,12 +13,12 @@ macro_rules! column {() => {}}
fn main() { column!(); }
"#,
- expect![[r##"
+ expect![[r#"
#[rustc_builtin_macro]
macro_rules! column {() => {}}
-fn main() { 0; }
-"##]],
+fn main() { 0 as u32; }
+"#]],
);
}
@@ -31,12 +31,12 @@ macro_rules! line {() => {}}
fn main() { line!() }
"#,
- expect![[r##"
+ expect![[r#"
#[rustc_builtin_macro]
macro_rules! line {() => {}}
-fn main() { 0 }
-"##]],
+fn main() { 0 as u32 }
+"#]],
);
}
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe.rs b/crates/hir-def/src/macro_expansion_tests/mbe.rs
index 99c405fb91..c056c077a5 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe.rs
@@ -922,7 +922,7 @@ macro_rules! m {
fn bar() -> &'a Baz<u8> {}
-fn bar() -> extern "Rust"fn() -> Ret {}
+fn bar() -> extern "Rust" fn() -> Ret {}
"#]],
);
}
@@ -1333,7 +1333,7 @@ macro_rules! matches {
}
fn main() {
match 0 {
- 0|1if true =>true , _=>false
+ 0|1 if true =>true , _=>false
};
}
"#]],
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs b/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
index e5fb15b6be..0909d8c835 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
@@ -73,7 +73,7 @@ fn main() {
macro_rules! asi { ($($stmt:stmt)*) => ($($stmt)*); }
fn main() {
- let a = 2let b = 5drop(b-a)println!("{}", a+b)
+ let a = 2 let b = 5 drop(b-a)println!("{}", a+b)
}
"#]],
)
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
index b663a29178..d8e4a4dcc7 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
@@ -297,55 +297,55 @@ macro_rules! impl_fn_for_zst {
#[derive(Clone)] struct CharEscapeDebugContinue;
impl Fn<(char, )> for CharEscapeDebugContinue {
- #[inline] extern "rust-call"fn call(&self , (c, ): (char, )) -> char::EscapeDebug { {
+ #[inline] extern "rust-call" fn call(&self , (c, ): (char, )) -> char::EscapeDebug { {
c.escape_debug_ext(false )
}
}
}
impl FnMut<(char, )> for CharEscapeDebugContinue {
- #[inline] extern "rust-call"fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDebug {
+ #[inline] extern "rust-call" fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDebug {
Fn::call(&*self , (c, ))
}
}
impl FnOnce<(char, )> for CharEscapeDebugContinue {
type Output = char::EscapeDebug;
- #[inline] extern "rust-call"fn call_once(self , (c, ): (char, )) -> char::EscapeDebug {
+ #[inline] extern "rust-call" fn call_once(self , (c, ): (char, )) -> char::EscapeDebug {
Fn::call(&self , (c, ))
}
}
#[derive(Clone)] struct CharEscapeUnicode;
impl Fn<(char, )> for CharEscapeUnicode {
- #[inline] extern "rust-call"fn call(&self , (c, ): (char, )) -> char::EscapeUnicode { {
+ #[inline] extern "rust-call" fn call(&self , (c, ): (char, )) -> char::EscapeUnicode { {
c.escape_unicode()
}
}
}
impl FnMut<(char, )> for CharEscapeUnicode {
- #[inline] extern "rust-call"fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeUnicode {
+ #[inline] extern "rust-call" fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeUnicode {
Fn::call(&*self , (c, ))
}
}
impl FnOnce<(char, )> for CharEscapeUnicode {
type Output = char::EscapeUnicode;
- #[inline] extern "rust-call"fn call_once(self , (c, ): (char, )) -> char::EscapeUnicode {
+ #[inline] extern "rust-call" fn call_once(self , (c, ): (char, )) -> char::EscapeUnicode {
Fn::call(&self , (c, ))
}
}
#[derive(Clone)] struct CharEscapeDefault;
impl Fn<(char, )> for CharEscapeDefault {
- #[inline] extern "rust-call"fn call(&self , (c, ): (char, )) -> char::EscapeDefault { {
+ #[inline] extern "rust-call" fn call(&self , (c, ): (char, )) -> char::EscapeDefault { {
c.escape_default()
}
}
}
impl FnMut<(char, )> for CharEscapeDefault {
- #[inline] extern "rust-call"fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDefault {
+ #[inline] extern "rust-call" fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDefault {
Fn::call(&*self , (c, ))
}
}
impl FnOnce<(char, )> for CharEscapeDefault {
type Output = char::EscapeDefault;
- #[inline] extern "rust-call"fn call_once(self , (c, ): (char, )) -> char::EscapeDefault {
+ #[inline] extern "rust-call" fn call_once(self , (c, ): (char, )) -> char::EscapeDefault {
Fn::call(&self , (c, ))
}
}
@@ -833,7 +833,7 @@ macro_rules! rgb_color {
/* parse error: expected SEMICOLON */
/* parse error: expected expression, item or let statement */
pub fn new() {
- let _ = 0as u32<<(8+8);
+ let _ = 0 as u32<<(8+8);
}
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index c48c0c1aee..40849d4a66 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();
@@ -280,6 +287,7 @@ fn pretty_print_macro_expansion(expn: SyntaxNode, map: Option<&TokenMap>) -> Str
let curr_kind = token.kind();
let space = match (prev_kind, curr_kind) {
_ if prev_kind.is_trivia() || curr_kind.is_trivia() => "",
+ _ if prev_kind.is_literal() && !curr_kind.is_punct() => " ",
(T!['{'], T!['}']) => "",
(T![=], _) | (_, T![=]) => " ",
(_, T!['{']) => " ",
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 803342fdab..39a56814ed 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.
@@ -105,6 +106,9 @@ pub struct DefMap {
prelude: Option<ModuleId>,
/// The extern prelude is only populated for non-block DefMaps
extern_prelude: FxHashMap<Name, ModuleId>,
+ /// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that
+ /// this contains all kinds of macro, not just `macro_rules!` macro.
+ macro_use_prelude: FxHashMap<Name, MacroId>,
/// Side table for resolving derive helpers.
exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
@@ -277,6 +281,7 @@ impl DefMap {
edition,
recursion_limit: None,
extern_prelude: FxHashMap::default(),
+ macro_use_prelude: FxHashMap::default(),
exported_derives: FxHashMap::default(),
fn_proc_macro_mapping: FxHashMap::default(),
proc_macro_loading_error: None,
@@ -376,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)
}
@@ -395,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)
}
@@ -489,6 +502,7 @@ impl DefMap {
_c: _,
exported_derives,
extern_prelude,
+ macro_use_prelude,
diagnostics,
modules,
registered_attrs,
@@ -507,6 +521,7 @@ impl DefMap {
} = self;
extern_prelude.shrink_to_fit();
+ macro_use_prelude.shrink_to_fit();
exported_derives.shrink_to_fit();
diagnostics.shrink_to_fit();
modules.shrink_to_fit();
@@ -562,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 84271ef51d..6567bda709 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 3ec33f663a..177edcbb7f 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,
@@ -289,80 +289,84 @@ impl DefCollector<'_> {
let module_id = self.def_map.root;
let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
- if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) {
- self.inject_prelude(&attrs);
-
- // Process other crate-level attributes.
- for attr in &*attrs {
- let attr_name = match attr.path.as_ident() {
- Some(name) => name,
- None => continue,
- };
+ if let Some(cfg) = attrs.cfg() {
+ if self.cfg_options.check(&cfg) == Some(false) {
+ return;
+ }
+ }
- if *attr_name == hir_expand::name![recursion_limit] {
- if let Some(limit) = attr.string_value() {
- if let Ok(limit) = limit.parse() {
- self.def_map.recursion_limit = Some(limit);
- }
- }
- continue;
- }
+ self.inject_prelude(&attrs);
- if *attr_name == hir_expand::name![crate_type] {
- if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
- self.is_proc_macro = true;
- }
- continue;
- }
+ // Process other crate-level attributes.
+ for attr in &*attrs {
+ let attr_name = match attr.path.as_ident() {
+ Some(name) => name,
+ None => continue,
+ };
- if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") {
- self.def_map.rustc_coherence_is_core = true;
- continue;
+ if *attr_name == hir_expand::name![recursion_limit] {
+ if let Some(limit) = attr.string_value() {
+ if let Ok(limit) = limit.parse() {
+ self.def_map.recursion_limit = Some(limit);
+ }
}
+ continue;
+ }
- if *attr_name == hir_expand::name![feature] {
- let hygiene = &Hygiene::new_unhygienic();
- let features = attr
- .parse_path_comma_token_tree(self.db.upcast(), hygiene)
- .into_iter()
- .flatten()
- .filter_map(|feat| match feat.segments() {
- [name] => Some(name.to_smol_str()),
- _ => None,
- });
- self.def_map.unstable_features.extend(features);
+ if *attr_name == hir_expand::name![crate_type] {
+ if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
+ self.is_proc_macro = true;
}
+ continue;
+ }
- let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
- || *attr_name == hir_expand::name![register_tool];
- if !attr_is_register_like {
- continue;
- }
+ if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") {
+ self.def_map.rustc_coherence_is_core = true;
+ continue;
+ }
- let registered_name = match attr.single_ident_value() {
- Some(ident) => ident.as_name(),
- _ => continue,
- };
+ if *attr_name == hir_expand::name![feature] {
+ let hygiene = &Hygiene::new_unhygienic();
+ let features = attr
+ .parse_path_comma_token_tree(self.db.upcast(), hygiene)
+ .into_iter()
+ .flatten()
+ .filter_map(|feat| match feat.segments() {
+ [name] => Some(name.to_smol_str()),
+ _ => None,
+ });
+ self.def_map.unstable_features.extend(features);
+ }
- if *attr_name == hir_expand::name![register_attr] {
- self.def_map.registered_attrs.push(registered_name.to_smol_str());
- cov_mark::hit!(register_attr);
- } else {
- self.def_map.registered_tools.push(registered_name.to_smol_str());
- cov_mark::hit!(register_tool);
- }
+ let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
+ || *attr_name == hir_expand::name![register_tool];
+ if !attr_is_register_like {
+ continue;
}
- ModCollector {
- def_collector: self,
- macro_depth: 0,
- module_id,
- tree_id: TreeId::new(file_id.into(), None),
- item_tree: &item_tree,
- mod_dir: ModDir::root(),
+ let registered_name = match attr.single_ident_value() {
+ Some(ident) => ident.as_name(),
+ _ => continue,
+ };
+
+ if *attr_name == hir_expand::name![register_attr] {
+ self.def_map.registered_attrs.push(registered_name.to_smol_str());
+ cov_mark::hit!(register_attr);
+ } else {
+ self.def_map.registered_tools.push(registered_name.to_smol_str());
+ cov_mark::hit!(register_tool);
}
- .collect_in_top_module(item_tree.top_level_items());
}
+
+ ModCollector {
+ def_collector: self,
+ macro_depth: 0,
+ module_id,
+ tree_id: TreeId::new(file_id.into(), None),
+ item_tree: &item_tree,
+ mod_dir: ModDir::root(),
+ }
+ .collect_in_top_module(item_tree.top_level_items());
}
fn seed_with_inner(&mut self, tree_id: TreeId) {
@@ -543,33 +547,26 @@ impl DefCollector<'_> {
Edition::Edition2015 => PathKind::Plain,
_ => PathKind::Abs,
};
- let path =
- ModPath::from_segments(path_kind, [krate.clone(), name![prelude], edition].into_iter());
- // Fall back to the older `std::prelude::v1` for compatibility with Rust <1.52.0
- // FIXME remove this fallback
- let fallback_path =
- ModPath::from_segments(path_kind, [krate, name![prelude], name![v1]].into_iter());
-
- for path in &[path, fallback_path] {
- let (per_ns, _) = self.def_map.resolve_path(
- self.db,
- self.def_map.root,
- path,
- BuiltinShadowMode::Other,
- );
+ 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,
+ None,
+ );
- match per_ns.types {
- Some((ModuleDefId::ModuleId(m), _)) => {
- self.def_map.prelude = Some(m);
- break;
- }
- types => {
- tracing::debug!(
- "could not resolve prelude path `{}` to module (resolved to {:?})",
- path,
- types
- );
- }
+ match per_ns.types {
+ Some((ModuleDefId::ModuleId(m), _)) => {
+ self.def_map.prelude = Some(m);
+ }
+ types => {
+ tracing::debug!(
+ "could not resolve prelude path `{}` to module (resolved to {:?})",
+ path,
+ types
+ );
}
}
}
@@ -715,6 +712,7 @@ impl DefCollector<'_> {
}
/// Import macros from `#[macro_use] extern crate`.
+ // FIXME: Support `#[macro_rules(macro_name, ...)]`.
fn import_macros_from_extern_crate(
&mut self,
current_module_id: LocalModuleId,
@@ -733,7 +731,7 @@ impl DefCollector<'_> {
}
cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
- self.import_all_macros_exported(current_module_id, m.krate);
+ self.import_all_macros_exported(m.krate);
}
}
@@ -742,11 +740,12 @@ impl DefCollector<'_> {
/// Exported macros are just all macros in the root module scope.
/// Note that it contains not only all `#[macro_export]` macros, but also all aliases
/// created by `use` in the root module, ignoring the visibility of `use`.
- fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
+ fn import_all_macros_exported(&mut self, krate: CrateId) {
let def_map = self.db.crate_def_map(krate);
for (name, def) in def_map[def_map.root].scope.macros() {
- // `#[macro_use]` brings macros into legacy scope. Yes, even non-`macro_rules!` macros.
- self.define_legacy_macro(current_module_id, name.clone(), def);
+ // `#[macro_use]` brings macros into macro_use prelude. Yes, even non-`macro_rules!`
+ // macros.
+ self.def_map.macro_use_prelude.insert(name.clone(), def);
}
}
@@ -802,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;
@@ -1099,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,
@@ -1107,6 +1114,7 @@ impl DefCollector<'_> {
directive.module_id,
&path,
BuiltinShadowMode::Module,
+ Some(subns),
);
resolved_res
.resolved_def
@@ -1425,6 +1433,7 @@ impl DefCollector<'_> {
directive.module_id,
&path,
BuiltinShadowMode::Module,
+ Some(MacroSubNs::Bang),
);
resolved_res
.resolved_def
@@ -1517,6 +1526,7 @@ impl ModCollector<'_, '_> {
fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
let krate = self.def_collector.def_map.krate;
+ let is_crate_root = self.module_id == self.def_collector.def_map.root;
// Note: don't assert that inserted value is fresh: it's simply not true
// for macros.
@@ -1524,19 +1534,24 @@ impl ModCollector<'_, '_> {
// Prelude module is always considered to be `#[macro_use]`.
if let Some(prelude_module) = self.def_collector.def_map.prelude {
- if prelude_module.krate != krate {
+ if prelude_module.krate != krate && is_crate_root {
cov_mark::hit!(prelude_is_macro_use);
- self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
+ self.def_collector.import_all_macros_exported(prelude_module.krate);
}
}
// This should be processed eagerly instead of deferred to resolving.
// `#[macro_use] extern crate` is hoisted to imports macros before collecting
// any other items.
- for &item in items {
- let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
- if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
- if let ModItem::ExternCrate(id) = item {
+ //
+ // If we're not at the crate root, `macro_use`d extern crates are an error so let's just
+ // ignore them.
+ // FIXME: Support `#[macro_rules(macro_name, ...)]`.
+ if is_crate_root {
+ for &item in items {
+ let ModItem::ExternCrate(id) = item else { continue; };
+ let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
+ if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
let import = &self.item_tree[id];
let attrs = self.item_tree.attrs(
self.def_collector.db,
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index 8299d9684b..4740fd7f44 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,19 +409,24 @@ impl DefMap {
module: LocalModuleId,
name: &Name,
shadow: BuiltinShadowMode,
+ expected_macro_subns: Option<MacroSubNs>,
) -> PerNs {
// Resolve in:
// - legacy scope of macro
// - current module / scope
- // - extern prelude
+ // - extern prelude / macro_use prelude
// - std prelude
let from_legacy_macro = self[module]
.scope
.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`.
@@ -414,9 +447,18 @@ impl DefMap {
.get(name)
.map_or(PerNs::none(), |&it| PerNs::types(it.into(), Visibility::Public))
};
+ let macro_use_prelude = || {
+ self.macro_use_prelude
+ .get(name)
+ .map_or(PerNs::none(), |&it| PerNs::macros(it.into(), Visibility::Public))
+ };
let prelude = || self.resolve_in_prelude(db, name);
- from_legacy_macro.or(from_scope_or_builtin).or_else(extern_prelude).or_else(prelude)
+ from_legacy_macro
+ .or(from_scope_or_builtin)
+ .or_else(extern_prelude)
+ .or_else(macro_use_prelude)
+ .or_else(prelude)
}
fn resolve_name_in_crate_root_or_extern_prelude(
diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs
index 6ee56c9368..e795b7b9b7 100644
--- a/crates/hir-def/src/nameres/tests/macros.rs
+++ b/crates/hir-def/src/nameres/tests/macros.rs
@@ -1216,17 +1216,112 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
"#,
);
- let root = &def_map[def_map.root()].scope;
- let actual = root
- .legacy_macros()
- .sorted_by(|a, b| std::cmp::Ord::cmp(&a.0, &b.0))
- .map(|(name, _)| format!("{name}\n"))
- .collect::<String>();
+ let root_module = &def_map[def_map.root()].scope;
+ assert!(
+ root_module.legacy_macros().count() == 0,
+ "`#[macro_use]` shouldn't bring macros into textual macro scope",
+ );
+
+ let actual = def_map.macro_use_prelude.iter().map(|(name, _)| name).sorted().join("\n");
expect![[r#"
legacy
macro20
- proc_attr
- "#]]
+ proc_attr"#]]
.assert_eq(&actual);
}
+
+#[test]
+fn non_prelude_macros_take_precedence_over_macro_use_prelude() {
+ check(
+ r#"
+//- /lib.rs edition:2021 crate:lib deps:dep,core
+#[macro_use]
+extern crate dep;
+
+macro foo() { struct Ok; }
+macro bar() { fn ok() {} }
+
+foo!();
+bar!();
+
+//- /dep.rs crate:dep
+#[macro_export]
+macro_rules! foo {
+ () => { struct NotOk; }
+}
+
+//- /core.rs crate:core
+pub mod prelude {
+ pub mod rust_2021 {
+ #[macro_export]
+ macro_rules! bar {
+ () => { fn not_ok() {} }
+ }
+ }
+}
+ "#,
+ expect![[r#"
+ crate
+ Ok: t v
+ bar: m
+ dep: t
+ foo: m
+ ok: v
+ "#]],
+ );
+}
+
+#[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 45ec454b9e..4bec2b4dea 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-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 9a25141d8f..9c8dc4ed1f 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -135,9 +135,8 @@ fn line_expand(
_tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// dummy implementation for type-checking purposes
- let line_num = 0;
let expanded = quote! {
- #line_num
+ 0 as u32
};
ExpandResult::ok(expanded)
@@ -179,9 +178,8 @@ fn column_expand(
_tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// dummy implementation for type-checking purposes
- let col_num = 0;
let expanded = quote! {
- #col_num
+ 0 as u32
};
ExpandResult::ok(expanded)
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 0f823580cb..0c68891fe4 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-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs
index d45edf730a..9377a3a5f2 100644
--- a/crates/hir-ty/src/tests/macros.rs
+++ b/crates/hir-ty/src/tests/macros.rs
@@ -661,8 +661,9 @@ fn infer_builtin_macros_line() {
"#,
expect![[r#"
!0..1 '0': i32
+ !0..6 '0asu32': u32
63..87 '{ ...!(); }': ()
- 73..74 'x': i32
+ 73..74 'x': u32
"#]],
);
}
@@ -699,8 +700,9 @@ fn infer_builtin_macros_column() {
"#,
expect![[r#"
!0..1 '0': i32
+ !0..6 '0asu32': u32
65..91 '{ ...!(); }': ()
- 75..76 'x': i32
+ 75..76 'x': u32
"#]],
);
}
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index d025aa8f5a..b817937296 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -4,7 +4,6 @@ use hir_def::{
attr::{AttrsWithOwner, Documentation},
item_scope::ItemInNs,
path::ModPath,
- per_ns::PerNs,
resolver::HasResolver,
AttrDefId, GenericParamId, ModuleDefId,
};
@@ -121,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,
@@ -155,14 +155,14 @@ fn resolve_doc_path(
.syntax_node()
.descendants()
.find_map(ast::Path::cast)?;
- if ast_path.to_string() != link {
+ if ast_path.syntax().text() != link {
return None;
}
ModPath::from_src(db.upcast(), ast_path, &Hygiene::new_unhygienic())?
};
let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath);
- let resolved = if resolved == PerNs::none() {
+ let resolved = if resolved.is_none() {
resolver.resolve_module_path_in_trait_assoc_items(db.upcast(), &modpath)?
} else {
resolved
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 81ea99522f..2d2b00b147 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 159601955f..dae77fad2f 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())))
};