name: &Name,
) -> ItemOrMacro {
// Resolve in:
+ // - textual scoped macros
// - current module / scope
// - extern prelude
// - std prelude
+ let from_textual_mcro = self[module]
+ .scope
+ .get_textual_macro(name)
+ .map_or_else(|| Either::A(PerNs::none()), Either::B);
let from_scope =
self[module].scope.get_item_or_macro(name).unwrap_or_else(|| Either::A(PerNs::none()));
let from_extern_prelude =
self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
let from_prelude = self.resolve_in_prelude(db, name);
- or(from_scope, or(Either::A(from_extern_prelude), from_prelude))
+ or(from_textual_mcro, or(from_scope, or(Either::A(from_extern_prelude), from_prelude)))
}
fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
raw, CrateDefMap, CrateModuleId, ItemOrMacro, ModuleData, ModuleDef, PerNs,
ReachedFixedPoint, Resolution, ResolveMode,
},
- AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, Static, Struct, Trait,
- TypeAlias, Union,
+ AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static,
+ Struct, Trait, TypeAlias, Union,
};
pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
/// the definition of current module.
/// And also, `macro_use` on a module will import all textual macros visable inside to
/// current textual scope, with possible shadowing.
- ///
- /// In a single module, the order of definition/usage of textual scoped macros matters.
- /// But we ignore it here to make it easy to implement.
fn define_textual_macro(&mut self, module_id: CrateModuleId, name: Name, macro_id: MacroDefId) {
// Always shadowing
self.def_map.modules[module_id]
return;
}
- // Case 3: path to a macro from another crate, expand during name resolution
- self.def_collector.unexpanded_macros.push((self.module_id, ast_id, mac.path.clone()))
+ // Case 3: resolve in module scope, expand during name resolution.
+ // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
+ let mut path = mac.path.clone();
+ if path.is_ident() {
+ path.kind = PathKind::Self_;
+ }
+ self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path));
}
fn import_all_textual_macros(&mut self, module_id: CrateModuleId) {
);
}
+#[test]
+fn infer_textual_scoped_macros_expanded() {
+ assert_snapshot!(
+ infer(r#"
+struct Foo(Vec<i32>);
+
+#[macro_use]
+mod m {
+ macro_rules! foo {
+ ($($item:expr),*) => {
+ {
+ Foo(vec![$($item,)*])
+ }
+ };
+ }
+}
+
+fn main() {
+ let x = foo!(1,2);
+ let y = crate::foo!(1,2);
+}
+"#),
+ @r###"
+ ![0; 17) '{Foo(v...,2,])}': Foo
+ ![1; 4) 'Foo': Foo({unknown}) -> Foo
+ ![1; 16) 'Foo(vec![1,2,])': Foo
+ ![5; 15) 'vec![1,2,]': {unknown}
+ [195; 251) '{ ...,2); }': ()
+ [205; 206) 'x': Foo
+ [228; 229) 'y': {unknown}
+ [232; 248) 'crate:...!(1,2)': {unknown}
+ "###
+ );
+}
+
#[ignore]
#[test]
fn method_resolution_trait_before_autoref() {