Resolve textual scoped macros inside item

This commit is contained in:
uHOOCCOOHu 2019-09-07 02:44:26 +08:00
parent e0f305a6bf
commit 26b092bd3b
No known key found for this signature in database
GPG key ID: CED392DE0C483D00
4 changed files with 65 additions and 9 deletions

View file

@ -489,16 +489,21 @@ impl CrateDefMap {
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> {

View file

@ -14,8 +14,8 @@ use crate::{
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 {
@ -156,9 +156,6 @@ where
/// 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]
@ -700,8 +697,13 @@ where
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) {

View file

@ -279,7 +279,7 @@ fn prelude_cycle() {
}
#[test]
fn plain_macros_are_textual_scoped_between_modules() {
fn plain_macros_are_textual_scoped() {
let map = def_map(
r#"
//- /main.rs
@ -310,6 +310,15 @@ fn plain_macros_are_textual_scoped_between_modules() {
}
foo!(ok_double_macro_use_shadow);
baz!(NotFoundBefore);
#[macro_use]
mod m7 {
macro_rules! baz {
($x:ident) => { struct $x; }
}
}
baz!(OkAfter);
//- /m1.rs
foo!(NotFoundBeforeInside1);
macro_rules! bar {
@ -337,14 +346,19 @@ fn plain_macros_are_textual_scoped_between_modules() {
assert_snapshot!(map, @r###"
crate
Ok: t v
OkAfter: t v
OkShadowStop: t v
foo: m
m1: t
m2: t
m3: t
m5: t
m7: t
ok_double_macro_use_shadow: v
crate::m7
baz: m
crate::m1
bar: m

View file

@ -2803,6 +2803,41 @@ fn main() {
);
}
#[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() {