Consider macro sub-namespace during name resolution

This commit is contained in:
Ryo Yoshida 2023-05-11 15:52:13 +09:00
parent 3203ea896d
commit f2a35deb50
No known key found for this signature in database
GPG Key ID: E25698A930586171
15 changed files with 236 additions and 36 deletions

View File

@ -37,7 +37,7 @@
item_scope::BuiltinShadowMode, item_scope::BuiltinShadowMode,
lang_item::LangItem, lang_item::LangItem,
lower::LowerCtx, lower::LowerCtx,
nameres::DefMap, nameres::{DefMap, MacroSubNs},
path::{GenericArgs, Path}, path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef}, type_ref::{Mutability, Rawness, TypeRef},
AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro, AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
@ -800,7 +800,13 @@ fn collect_macro_call<F, T, U>(
let module = self.expander.module.local_id; let module = self.expander.module.local_id;
let res = self.expander.enter_expand(self.db, mcall, |path| { let res = self.expander.enter_expand(self.db, mcall, |path| {
self.def_map 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 .0
.take_macros() .take_macros()
}); });
@ -1056,6 +1062,7 @@ fn collect_pat(&mut self, pat: ast::Pat, binding_list: &mut BindingList) -> PatI
self.expander.module.local_id, self.expander.module.local_id,
&name.clone().into(), &name.clone().into(),
BuiltinShadowMode::Other, BuiltinShadowMode::Other,
None,
); );
match resolved.take_values() { match resolved.take_values() {
Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())), Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),

View File

@ -22,7 +22,7 @@
attr_resolution::ResolvedAttr, attr_resolution::ResolvedAttr,
diagnostics::DefDiagnostic, diagnostics::DefDiagnostic,
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
DefMap, DefMap, MacroSubNs,
}, },
type_ref::{TraitRef, TypeBound, TypeRef}, type_ref::{TraitRef, TypeBound, TypeRef},
visibility::RawVisibility, visibility::RawVisibility,
@ -673,6 +673,7 @@ fn collect_item(
module, module,
&path, &path,
crate::item_scope::BuiltinShadowMode::Other, crate::item_scope::BuiltinShadowMode::Other,
Some(MacroSubNs::Bang),
) )
.0 .0
.take_macros() .take_macros()

View File

@ -543,6 +543,7 @@ fn check_found_path_(ra_fixture: &str, path: &str, prefix_kind: Option<PrefixKin
module.local_id, module.local_id,
&mod_path, &mod_path,
crate::item_scope::BuiltinShadowMode::Module, crate::item_scope::BuiltinShadowMode::Module,
None,
) )
.0 .0
.take_types() .take_types()

View File

@ -22,7 +22,7 @@
dyn_map::{keys, DynMap}, dyn_map::{keys, DynMap},
expander::Expander, expander::Expander,
lower::LowerCtx, lower::LowerCtx,
nameres::DefMap, nameres::{DefMap, MacroSubNs},
src::{HasChildSource, HasSource}, src::{HasChildSource, HasSource},
type_ref::{LifetimeRef, TypeBound, TypeRef}, type_ref::{LifetimeRef, TypeBound, TypeRef},
AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId, AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId,
@ -361,6 +361,7 @@ pub(crate) fn fill_implicit_impl_trait_args(
module, module,
&path, &path,
crate::item_scope::BuiltinShadowMode::Other, crate::item_scope::BuiltinShadowMode::Other,
Some(MacroSubNs::Bang),
) )
.0 .0
.take_macros() .take_macros()

View File

@ -33,8 +33,13 @@
use tt::token_id::{Subtree, TokenId}; use tt::token_id::{Subtree, TokenId};
use crate::{ use crate::{
db::DefDatabase, macro_id_to_def_id, nameres::ModuleSource, resolver::HasResolver, db::DefDatabase,
src::HasSource, test_db::TestDB, AdtId, AsMacroCall, Lookup, ModuleDefId, macro_id_to_def_id,
nameres::{MacroSubNs, ModuleSource},
resolver::HasResolver,
src::HasSource,
test_db::TestDB,
AdtId, AsMacroCall, Lookup, ModuleDefId,
}; };
#[track_caller] #[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 macro_call = InFile::new(source.file_id, &macro_call);
let res = macro_call let res = macro_call
.as_call_id_with_errors(&db, krate, |path| { .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(); .unwrap();
let macro_call_id = res.value.unwrap(); let macro_call_id = res.value.unwrap();

View File

@ -59,7 +59,7 @@
use std::{cmp::Ord, ops::Deref}; 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 hir_expand::{name::Name, InFile, MacroCallId, MacroDefId};
use itertools::Itertools; use itertools::Itertools;
use la_arena::Arena; use la_arena::Arena;
@ -77,7 +77,8 @@
path::ModPath, path::ModPath,
per_ns::PerNs, per_ns::PerNs,
visibility::Visibility, 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. /// Contains the results of (early) name resolution.
@ -380,9 +381,16 @@ pub(crate) fn resolve_path(
original_module: LocalModuleId, original_module: LocalModuleId,
path: &ModPath, path: &ModPath,
shadow: BuiltinShadowMode, shadow: BuiltinShadowMode,
expected_macro_subns: Option<MacroSubNs>,
) -> (PerNs, Option<usize>) { ) -> (PerNs, Option<usize>) {
let res = let res = self.resolve_path_fp_with_macro(
self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow); db,
ResolveMode::Other,
original_module,
path,
shadow,
expected_macro_subns,
);
(res.resolved_def, res.segment_index) (res.resolved_def, res.segment_index)
} }
@ -399,6 +407,7 @@ pub(crate) fn resolve_path_locally(
original_module, original_module,
path, path,
shadow, shadow,
None, // Currently this function isn't used for macro resolution.
); );
(res.resolved_def, res.segment_index) (res.resolved_def, res.segment_index)
} }
@ -568,3 +577,48 @@ pub enum ModuleSource {
Module(ast::Module), Module(ast::Module),
BlockExpr(ast::BlockExpr), 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,
}
}

View File

@ -14,7 +14,7 @@
AstIdWithPath, LocalModuleId, UnresolvedMacro, AstIdWithPath, LocalModuleId, UnresolvedMacro,
}; };
use super::DefMap; use super::{DefMap, MacroSubNs};
pub enum ResolvedAttr { pub enum ResolvedAttr {
/// Attribute resolved to an attribute macro. /// Attribute resolved to an attribute macro.
@ -43,9 +43,12 @@ pub(crate) fn resolve_attr_macro(
original_module, original_module,
&ast_id.path, &ast_id.path,
BuiltinShadowMode::Module, BuiltinShadowMode::Module,
Some(MacroSubNs::Attr),
); );
let def = match resolved_res.resolved_def.take_macros() { let def = match resolved_res.resolved_def.take_macros() {
Some(def) => { 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) { if def.is_attribute(db) {
def def
} else { } else {

View File

@ -44,7 +44,7 @@
mod_resolution::ModDir, mod_resolution::ModDir,
path_resolution::ReachedFixedPoint, path_resolution::ReachedFixedPoint,
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind}, 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}, path::{ImportAlias, ModPath, PathKind},
per_ns::PerNs, per_ns::PerNs,
@ -549,8 +549,13 @@ fn inject_prelude(&mut self, crate_attrs: &Attrs) {
}; };
let path = ModPath::from_segments(path_kind, [krate, name![prelude], edition]); let path = ModPath::from_segments(path_kind, [krate, name![prelude], edition]);
let (per_ns, _) = let (per_ns, _) = self.def_map.resolve_path(
self.def_map.resolve_path(self.db, self.def_map.root, &path, BuiltinShadowMode::Other); self.db,
self.def_map.root,
&path,
BuiltinShadowMode::Other,
None,
);
match per_ns.types { match per_ns.types {
Some((ModuleDefId::ModuleId(m), _)) => { Some((ModuleDefId::ModuleId(m), _)) => {
@ -796,6 +801,7 @@ fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialRe
module_id, module_id,
&import.path, &import.path,
BuiltinShadowMode::Module, BuiltinShadowMode::Module,
None, // An import may resolve to any kind of macro.
); );
let def = res.resolved_def; let def = res.resolved_def;
@ -1093,7 +1099,14 @@ fn resolve_macros(&mut self) -> ReachedFixedPoint {
resolved.push((directive.module_id, directive.depth, directive.container, call_id)); resolved.push((directive.module_id, directive.depth, directive.container, call_id));
}; };
let mut res = ReachedFixedPoint::Yes; let mut res = ReachedFixedPoint::Yes;
// Retain unresolved macros after this round of resolution.
macros.retain(|directive| { macros.retain(|directive| {
let subns = match &directive.kind {
MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang,
MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => {
MacroSubNs::Attr
}
};
let resolver = |path| { let resolver = |path| {
let resolved_res = self.def_map.resolve_path_fp_with_macro( let resolved_res = self.def_map.resolve_path_fp_with_macro(
self.db, self.db,
@ -1101,6 +1114,7 @@ fn resolve_macros(&mut self) -> ReachedFixedPoint {
directive.module_id, directive.module_id,
&path, &path,
BuiltinShadowMode::Module, BuiltinShadowMode::Module,
Some(subns),
); );
resolved_res resolved_res
.resolved_def .resolved_def
@ -1419,6 +1433,7 @@ fn finish(mut self) -> DefMap {
directive.module_id, directive.module_id,
&path, &path,
BuiltinShadowMode::Module, BuiltinShadowMode::Module,
Some(MacroSubNs::Bang),
); );
resolved_res resolved_res
.resolved_def .resolved_def

View File

@ -16,7 +16,7 @@
use crate::{ use crate::{
db::DefDatabase, db::DefDatabase,
item_scope::BUILTIN_SCOPE, item_scope::BUILTIN_SCOPE,
nameres::{BuiltinShadowMode, DefMap}, nameres::{sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs},
path::{ModPath, PathKind}, path::{ModPath, PathKind},
per_ns::PerNs, per_ns::PerNs,
visibility::{RawVisibility, Visibility}, visibility::{RawVisibility, Visibility},
@ -58,6 +58,17 @@ fn with(
} }
} }
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 { impl DefMap {
pub(super) fn resolve_name_in_extern_prelude( pub(super) fn resolve_name_in_extern_prelude(
&self, &self,
@ -83,7 +94,7 @@ pub(crate) fn resolve_visibility(
let mut vis = match visibility { let mut vis = match visibility {
RawVisibility::Module(path) => { RawVisibility::Module(path) => {
let (result, remaining) = 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() { if remaining.is_some() {
return None; return None;
} }
@ -124,6 +135,9 @@ pub(super) fn resolve_path_fp_with_macro(
mut original_module: LocalModuleId, mut original_module: LocalModuleId,
path: &ModPath, path: &ModPath,
shadow: BuiltinShadowMode, 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 { ) -> ResolvePathResult {
let mut result = ResolvePathResult::empty(ReachedFixedPoint::No); let mut result = ResolvePathResult::empty(ReachedFixedPoint::No);
@ -136,6 +150,7 @@ pub(super) fn resolve_path_fp_with_macro(
original_module, original_module,
path, path,
shadow, shadow,
expected_macro_subns,
); );
// Merge `new` into `result`. // Merge `new` into `result`.
@ -169,6 +184,7 @@ pub(super) fn resolve_path_fp_with_macro_single(
original_module: LocalModuleId, original_module: LocalModuleId,
path: &ModPath, path: &ModPath,
shadow: BuiltinShadowMode, shadow: BuiltinShadowMode,
expected_macro_subns: Option<MacroSubNs>,
) -> ResolvePathResult { ) -> ResolvePathResult {
let graph = db.crate_graph(); let graph = db.crate_graph();
let _cx = stdx::panic_context::enter(format!( let _cx = stdx::panic_context::enter(format!(
@ -220,7 +236,13 @@ pub(super) fn resolve_path_fp_with_macro_single(
if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module }; if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module };
tracing::debug!("resolving {:?} in module", segment); 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) => { PathKind::Super(lvl) => {
let mut module = original_module; let mut module = original_module;
@ -245,6 +267,7 @@ pub(super) fn resolve_path_fp_with_macro_single(
block.parent.local_id, block.parent.local_id,
&new_path, &new_path,
shadow, shadow,
expected_macro_subns,
); );
} }
None => { None => {
@ -303,7 +326,12 @@ pub(super) fn resolve_path_fp_with_macro_single(
); );
tracing::debug!("resolving {:?} in other crate", path); tracing::debug!("resolving {:?} in other crate", path);
let defp_map = module.def_map(db); 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( return ResolvePathResult::with(
def, def,
ReachedFixedPoint::Yes, ReachedFixedPoint::Yes,
@ -381,6 +409,7 @@ fn resolve_name_in_module(
module: LocalModuleId, module: LocalModuleId,
name: &Name, name: &Name,
shadow: BuiltinShadowMode, shadow: BuiltinShadowMode,
expected_macro_subns: Option<MacroSubNs>,
) -> PerNs { ) -> PerNs {
// Resolve in: // Resolve in:
// - legacy scope of macro // - legacy scope of macro
@ -392,8 +421,12 @@ fn resolve_name_in_module(
.get_legacy_macro(name) .get_legacy_macro(name)
// FIXME: shadowing // FIXME: shadowing
.and_then(|it| it.last()) .and_then(|it| it.last())
.map_or_else(PerNs::none, |&m| PerNs::macros(m, Visibility::Public)); .copied()
let from_scope = self[module].scope.get(name); .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 { let from_builtin = match self.block {
Some(_) => { Some(_) => {
// Only resolve to builtins in the root `DefMap`. // Only resolve to builtins in the root `DefMap`.

View File

@ -1271,3 +1271,57 @@ macro_rules! bar {
"#]], "#]],
); );
} }
#[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
"#]],
);
}

View File

@ -17,7 +17,7 @@
hir::{BindingId, ExprId, LabelId}, hir::{BindingId, ExprId, LabelId},
item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
lang_item::LangItemTarget, lang_item::LangItemTarget,
nameres::DefMap, nameres::{DefMap, MacroSubNs},
path::{ModPath, Path, PathKind}, path::{ModPath, Path, PathKind},
per_ns::PerNs, per_ns::PerNs,
visibility::{RawVisibility, Visibility}, visibility::{RawVisibility, Visibility},
@ -155,7 +155,8 @@ pub fn resolve_module_path_in_trait_assoc_items(
path: &ModPath, path: &ModPath,
) -> Option<PerNs> { ) -> Option<PerNs> {
let (item_map, module) = self.item_scope(); 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()? { match module_res.take_types()? {
ModuleDefId::TraitId(it) => { ModuleDefId::TraitId(it) => {
let idx = idx?; let idx = idx?;
@ -385,9 +386,17 @@ pub fn resolve_path_in_value_ns_fully(
} }
} }
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(); 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. /// Returns a set of names available in the current scope.
@ -626,7 +635,8 @@ fn resolve_module_path(
shadow: BuiltinShadowMode, shadow: BuiltinShadowMode,
) -> PerNs { ) -> PerNs {
let (item_map, module) = self.item_scope(); 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() { if segment_index.is_some() {
return PerNs::none(); return PerNs::none();
} }

View File

@ -24,6 +24,7 @@
TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
}, },
lang_item::{lang_attr, LangItem}, lang_item::{lang_attr, LangItem},
nameres::MacroSubNs,
path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments}, path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs}, resolver::{HasResolver, Resolver, TypeNs},
type_ref::{ConstRefOrPath, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef}, type_ref::{ConstRefOrPath, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
@ -378,9 +379,15 @@ pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
}; };
let ty = { let ty = {
let macro_call = macro_call.to_node(self.db.upcast()); let macro_call = macro_call.to_node(self.db.upcast());
match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, |path| { let resolver = |path| {
self.resolver.resolve_path_as_macro(self.db.upcast(), &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)), .. }) => { Ok(ExpandResult { value: Some((mark, expanded)), .. }) => {
let ctx = expander.ctx(self.db.upcast()); let ctx = expander.ctx(self.db.upcast());
// FIXME: Report syntax errors in expansion here // FIXME: Report syntax errors in expansion here

View File

@ -120,6 +120,7 @@ fn resolve_doc_path(
} }
} }
/// Resolves the item `link` points to in the scope of `def`.
fn resolve_doc_path( fn resolve_doc_path(
db: &dyn HirDatabase, db: &dyn HirDatabase,
def: AttrDefId, def: AttrDefId,

View File

@ -10,6 +10,7 @@
hir::Expr, hir::Expr,
lower::LowerCtx, lower::LowerCtx,
macro_id_to_def_id, macro_id_to_def_id,
nameres::MacroSubNs,
resolver::{self, HasResolver, Resolver, TypeNs}, resolver::{self, HasResolver, Resolver, TypeNs},
type_ref::Mutability, type_ref::Mutability,
AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId, AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId,
@ -616,7 +617,7 @@ fn speculative_expand(
let krate = resolver.krate(); let krate = resolver.krate();
let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
resolver 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)) .map(|it| macro_id_to_def_id(self.db.upcast(), it))
})?; })?;
hir_expand::db::expand_speculative( hir_expand::db::expand_speculative(

View File

@ -17,6 +17,7 @@
lang_item::LangItem, lang_item::LangItem,
lower::LowerCtx, lower::LowerCtx,
macro_id_to_def_id, macro_id_to_def_id,
nameres::MacroSubNs,
path::{ModPath, Path, PathKind}, path::{ModPath, Path, PathKind},
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
type_ref::Mutability, type_ref::Mutability,
@ -484,7 +485,9 @@ pub(crate) fn resolve_macro_call(
) -> Option<Macro> { ) -> Option<Macro> {
let ctx = LowerCtx::with_file_id(db.upcast(), macro_call.file_id); 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))?; 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( pub(crate) fn resolve_bind_pat_to_const(
@ -678,7 +681,7 @@ pub(crate) fn resolve_path(
} }
} }
} }
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))), 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 // 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 // but there is no benefit in differentiating these two cases for the time being
@ -756,7 +759,7 @@ pub(crate) fn expand(
let krate = self.resolver.krate(); let krate = self.resolver.krate();
let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
self.resolver 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)) .map(|it| macro_id_to_def_id(db.upcast(), it))
})?; })?;
Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64) 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] #[inline]
pub(crate) fn resolve_hir_path_as_macro( pub(crate) fn resolve_hir_path_as_attr_macro(
db: &dyn HirDatabase, db: &dyn HirDatabase,
resolver: &Resolver, resolver: &Resolver,
path: &Path, path: &Path,
) -> Option<Macro> { ) -> 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_( fn resolve_hir_path_(
@ -1060,7 +1065,7 @@ fn resolve_hir_path_(
let macros = || { let macros = || {
resolver 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()))) .map(|def| PathResolution::Def(ModuleDef::Macro(def.into())))
}; };