Skip to content

Commit fdf8663

Browse files
committed
Merge branch 'master' of github.com:rust-analyzer/rust-analyzer
2 parents 6d5f392 + fb8fb65 commit fdf8663

File tree

13 files changed

+139
-17
lines changed

13 files changed

+139
-17
lines changed

crates/ra_hir/src/semantics/source_to_def.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl SourceToDefCtx<'_, '_> {
151151
let krate = self.file_to_def(file_id)?.krate;
152152
let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value);
153153
let ast_id = Some(AstId::new(src.file_id, file_ast_id));
154-
Some(MacroDefId { krate: Some(krate), ast_id, kind })
154+
Some(MacroDefId { krate: Some(krate), ast_id, kind, local_inner: false })
155155
}
156156

157157
pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {

crates/ra_hir_def/src/attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ impl Attr {
140140
}
141141
}
142142

143+
#[derive(Debug, Clone, Copy)]
143144
pub struct AttrQuery<'a> {
144145
attrs: &'a Attrs,
145146
key: &'static str,

crates/ra_hir_def/src/body/lower.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ impl ExprCollector<'_> {
466466
krate: Some(self.expander.module.krate),
467467
ast_id: Some(self.expander.ast_id(&e)),
468468
kind: MacroDefKind::Declarative,
469+
local_inner: false,
469470
};
470471
self.body.item_scope.define_legacy_macro(name, mac);
471472

crates/ra_hir_def/src/nameres/collector.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ impl DefCollector<'_> {
204204
ast_id: None,
205205
krate: Some(krate),
206206
kind: MacroDefKind::CustomDerive(expander),
207+
local_inner: false,
207208
};
208209

209210
self.define_proc_macro(name.clone(), macro_id);
@@ -941,6 +942,7 @@ impl ModCollector<'_, '_> {
941942
ast_id: Some(ast_id.ast_id),
942943
krate: Some(self.def_collector.def_map.krate),
943944
kind: MacroDefKind::Declarative,
945+
local_inner: mac.local_inner,
944946
};
945947
self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
946948
}

crates/ra_hir_def/src/nameres/raw.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ pub(super) struct MacroData {
188188
pub(super) path: ModPath,
189189
pub(super) name: Option<Name>,
190190
pub(super) export: bool,
191+
pub(super) local_inner: bool,
191192
pub(super) builtin: bool,
192193
}
193194

@@ -401,14 +402,32 @@ impl RawItemsCollector {
401402

402403
let name = m.name().map(|it| it.as_name());
403404
let ast_id = self.source_ast_id_map.ast_id(&m);
404-
// FIXME: cfg_attr
405-
let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export");
406405

407406
// FIXME: cfg_attr
408-
let builtin =
409-
m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "rustc_builtin_macro");
407+
let export_attr = attrs.by_key("macro_export");
408+
409+
let export = export_attr.exists();
410+
let local_inner = if export {
411+
export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
412+
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
413+
ident.text.contains("local_inner_macros")
414+
}
415+
_ => false,
416+
})
417+
} else {
418+
false
419+
};
420+
421+
let builtin = attrs.by_key("rustc_builtin_macro").exists();
410422

411-
let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export, builtin });
423+
let m = self.raw_items.macros.alloc(MacroData {
424+
ast_id,
425+
path,
426+
name,
427+
export,
428+
local_inner,
429+
builtin,
430+
});
412431
self.push_item(current_module, attrs, RawItemKind::Macro(m));
413432
}
414433

crates/ra_hir_def/src/nameres/tests/macros.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,43 @@ fn macro_rules_export_with_local_inner_macros_are_visible() {
135135
"###);
136136
}
137137

138+
#[test]
139+
fn local_inner_macros_makes_local_macros_usable() {
140+
let map = def_map(
141+
"
142+
//- /main.rs crate:main deps:foo
143+
foo::structs!(Foo, Bar);
144+
mod bar;
145+
//- /bar.rs
146+
use crate::*;
147+
//- /lib.rs crate:foo
148+
#[macro_export(local_inner_macros)]
149+
macro_rules! structs {
150+
($($i:ident),*) => {
151+
inner!($($i),*);
152+
}
153+
}
154+
#[macro_export]
155+
macro_rules! inner {
156+
($($i:ident),*) => {
157+
$(struct $i { field: u32 } )*
158+
}
159+
}
160+
",
161+
);
162+
assert_snapshot!(map, @r###"
163+
⋮crate
164+
⋮Bar: t v
165+
⋮Foo: t v
166+
⋮bar: t
167+
168+
⋮crate::bar
169+
⋮Bar: t v
170+
⋮Foo: t v
171+
⋮bar: t
172+
"###);
173+
}
174+
138175
#[test]
139176
fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
140177
let map = def_map(

crates/ra_hir_def/src/path/lower.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,21 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
116116
}
117117
segments.reverse();
118118
generic_args.reverse();
119+
120+
// handle local_inner_macros :
121+
// Basically, even in rustc it is quite hacky:
122+
// https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456
123+
// We follow what it did anyway :)
124+
if segments.len() == 1 && kind == PathKind::Plain {
125+
if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
126+
if macro_call.is_bang() {
127+
if let Some(crate_id) = hygiene.local_inner_macros() {
128+
kind = PathKind::DollarCrate(crate_id);
129+
}
130+
}
131+
}
132+
}
133+
119134
let mod_path = ModPath { kind, segments };
120135
return Some(Path { type_anchor, mod_path, generic_args });
121136

crates/ra_hir_expand/src/builtin_derive.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ macro_rules! register_builtin {
3838
_ => return None,
3939
};
4040

41-
Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind) })
41+
Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind), local_inner: false })
4242
}
4343
};
4444
}

crates/ra_hir_expand/src/builtin_macro.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,13 @@ pub fn find_builtin_macro(
7373
krate: Some(krate),
7474
ast_id: Some(ast_id),
7575
kind: MacroDefKind::BuiltIn(kind),
76+
local_inner: false,
7677
}),
7778
Either::Right(kind) => Some(MacroDefId {
7879
krate: Some(krate),
7980
ast_id: Some(ast_id),
8081
kind: MacroDefKind::BuiltInEager(kind),
82+
local_inner: false,
8183
}),
8284
}
8385
}
@@ -406,6 +408,7 @@ mod tests {
406408
krate: Some(CrateId(0)),
407409
ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))),
408410
kind: MacroDefKind::BuiltIn(expander),
411+
local_inner: false,
409412
};
410413

411414
let loc = MacroCallLoc {
@@ -425,6 +428,7 @@ mod tests {
425428
krate: Some(CrateId(0)),
426429
ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))),
427430
kind: MacroDefKind::BuiltInEager(expander),
431+
local_inner: false,
428432
};
429433

430434
let args = macro_calls[1].token_tree().unwrap();

crates/ra_hir_expand/src/hygiene.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,34 @@ use crate::{
1616
pub struct Hygiene {
1717
// This is what `$crate` expands to
1818
def_crate: Option<CrateId>,
19+
20+
// Indiciate this is a local inner macro
21+
local_inner: bool,
1922
}
2023

2124
impl Hygiene {
2225
pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene {
23-
let def_crate = match file_id.0 {
24-
HirFileIdRepr::FileId(_) => None,
26+
let (def_crate, local_inner) = match file_id.0 {
27+
HirFileIdRepr::FileId(_) => (None, false),
2528
HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
2629
MacroCallId::LazyMacro(id) => {
2730
let loc = db.lookup_intern_macro(id);
2831
match loc.def.kind {
29-
MacroDefKind::Declarative => loc.def.krate,
30-
MacroDefKind::BuiltIn(_) => None,
31-
MacroDefKind::BuiltInDerive(_) => None,
32-
MacroDefKind::BuiltInEager(_) => None,
33-
MacroDefKind::CustomDerive(_) => None,
32+
MacroDefKind::Declarative => (loc.def.krate, loc.def.local_inner),
33+
MacroDefKind::BuiltIn(_) => (None, false),
34+
MacroDefKind::BuiltInDerive(_) => (None, false),
35+
MacroDefKind::BuiltInEager(_) => (None, false),
36+
MacroDefKind::CustomDerive(_) => (None, false),
3437
}
3538
}
36-
MacroCallId::EagerMacro(_id) => None,
39+
MacroCallId::EagerMacro(_id) => (None, false),
3740
},
3841
};
39-
Hygiene { def_crate }
42+
Hygiene { def_crate, local_inner }
4043
}
4144

4245
pub fn new_unhygienic() -> Hygiene {
43-
Hygiene { def_crate: None }
46+
Hygiene { def_crate: None, local_inner: false }
4447
}
4548

4649
// FIXME: this should just return name
@@ -52,4 +55,12 @@ impl Hygiene {
5255
}
5356
Either::Left(name_ref.as_name())
5457
}
58+
59+
pub fn local_inner_macros(&self) -> Option<CrateId> {
60+
if self.local_inner {
61+
self.def_crate
62+
} else {
63+
None
64+
}
65+
}
5566
}

crates/ra_hir_expand/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ pub struct MacroDefId {
204204
pub krate: Option<CrateId>,
205205
pub ast_id: Option<AstId<ast::MacroCall>>,
206206
pub kind: MacroDefKind,
207+
208+
pub local_inner: bool,
207209
}
208210

209211
impl MacroDefId {

crates/ra_hir_ty/src/tests/macros.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,32 @@ fn main() {
427427
);
428428
}
429429

430+
#[test]
431+
fn infer_local_inner_macros() {
432+
let (db, pos) = TestDB::with_position(
433+
r#"
434+
//- /main.rs crate:main deps:foo
435+
fn test() {
436+
let x = foo::foo!(1);
437+
x<|>;
438+
}
439+
440+
//- /lib.rs crate:foo
441+
#[macro_export(local_inner_macros)]
442+
macro_rules! foo {
443+
(1) => { bar!() };
444+
}
445+
446+
#[macro_export]
447+
macro_rules! bar {
448+
() => { 42 }
449+
}
450+
451+
"#,
452+
);
453+
assert_eq!("i32", type_at_pos(&db, pos));
454+
}
455+
430456
#[test]
431457
fn infer_builtin_macros_line() {
432458
assert_snapshot!(

crates/ra_syntax/src/ast/extensions.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,10 @@ impl ast::MacroCall {
423423
None
424424
}
425425
}
426+
427+
pub fn is_bang(&self) -> bool {
428+
self.is_macro_rules().is_none()
429+
}
426430
}
427431

428432
impl ast::LifetimeParam {

0 commit comments

Comments
 (0)