Skip to content

Commit 9b33874

Browse files
committed
Auto merge of #14781 - lowr:patch/macro-subns-and-prelude, r=Veykril
Introduce macro sub-namespaces and `macro_use` prelude This PR implements two mechanisms needed for correct macro name resolution: macro sub-namespace and `macro_use` prelude. - [macro sub-namespaces][subns-ref] Macros have two sub-namespaces: one for function-like macro and the other for those in attributes (including custom derive macros). When we're resolving a macro name for function-like macro, we should ignore non-function-like macros, and vice versa. This helps resolve single-segment macro names because we can (and should, as rustc does) fallback to names in preludes when the name in the current module scope is in different sub-namespace. - [`macro_use` prelude][prelude-ref] `#[macro_use]`'d extern crate declarations (including the standard library) bring their macros into scope, but they should not be prioritized over local macros (those defined in place and those explicitly imported). We have been bringing them into legacy (textual) macro scope, which has the highest precedence in name resolution. This PR introduces the `macro_use` prelude in crate-level `DefMap`s, whose precedence is lower than local macros but higher than the standard library prelude. The first 3 commits are drive-by fixes/refactors. Fixes #8828 (prelude) Fixes #12505 (prelude) Fixes #12734 (prelude) Fixes #13683 (prelude) Fixes #13821 (prelude) Fixes #13974 (prelude) Fixes #14254 (namespace) [subns-ref]: https://doc.rust-lang.org/reference/names/namespaces.html#sub-namespaces [prelude-ref]: https://doc.rust-lang.org/reference/names/preludes.html#macro_use-prelude
2 parents b069eb7 + f2a35de commit 9b33874

21 files changed

+425
-169
lines changed

crates/hir-def/src/body/lower.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::{
3737
item_scope::BuiltinShadowMode,
3838
lang_item::LangItem,
3939
lower::LowerCtx,
40-
nameres::DefMap,
40+
nameres::{DefMap, MacroSubNs},
4141
path::{GenericArgs, Path},
4242
type_ref::{Mutability, Rawness, TypeRef},
4343
AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
@@ -800,7 +800,13 @@ impl ExprCollector<'_> {
800800
let module = self.expander.module.local_id;
801801
let res = self.expander.enter_expand(self.db, mcall, |path| {
802802
self.def_map
803-
.resolve_path(self.db, module, &path, crate::item_scope::BuiltinShadowMode::Other)
803+
.resolve_path(
804+
self.db,
805+
module,
806+
&path,
807+
crate::item_scope::BuiltinShadowMode::Other,
808+
Some(MacroSubNs::Bang),
809+
)
804810
.0
805811
.take_macros()
806812
});
@@ -1056,6 +1062,7 @@ impl ExprCollector<'_> {
10561062
self.expander.module.local_id,
10571063
&name.clone().into(),
10581064
BuiltinShadowMode::Other,
1065+
None,
10591066
);
10601067
match resolved.take_values() {
10611068
Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),

crates/hir-def/src/data.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::{
2222
attr_resolution::ResolvedAttr,
2323
diagnostics::DefDiagnostic,
2424
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
25-
DefMap,
25+
DefMap, MacroSubNs,
2626
},
2727
type_ref::{TraitRef, TypeBound, TypeRef},
2828
visibility::RawVisibility,
@@ -673,6 +673,7 @@ impl<'a> AssocItemCollector<'a> {
673673
module,
674674
&path,
675675
crate::item_scope::BuiltinShadowMode::Other,
676+
Some(MacroSubNs::Bang),
676677
)
677678
.0
678679
.take_macros()

crates/hir-def/src/find_path.rs

+1
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ mod tests {
543543
module.local_id,
544544
&mod_path,
545545
crate::item_scope::BuiltinShadowMode::Module,
546+
None,
546547
)
547548
.0
548549
.take_types()

crates/hir-def/src/generics.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::{
2222
dyn_map::{keys, DynMap},
2323
expander::Expander,
2424
lower::LowerCtx,
25-
nameres::DefMap,
25+
nameres::{DefMap, MacroSubNs},
2626
src::{HasChildSource, HasSource},
2727
type_ref::{LifetimeRef, TypeBound, TypeRef},
2828
AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId,
@@ -361,6 +361,7 @@ impl GenericParams {
361361
module,
362362
&path,
363363
crate::item_scope::BuiltinShadowMode::Other,
364+
Some(MacroSubNs::Bang),
364365
)
365366
.0
366367
.take_macros()

crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ macro_rules! column {() => {}}
1313
1414
fn main() { column!(); }
1515
"#,
16-
expect![[r##"
16+
expect![[r#"
1717
#[rustc_builtin_macro]
1818
macro_rules! column {() => {}}
1919
20-
fn main() { 0; }
21-
"##]],
20+
fn main() { 0 as u32; }
21+
"#]],
2222
);
2323
}
2424

@@ -31,12 +31,12 @@ macro_rules! line {() => {}}
3131
3232
fn main() { line!() }
3333
"#,
34-
expect![[r##"
34+
expect![[r#"
3535
#[rustc_builtin_macro]
3636
macro_rules! line {() => {}}
3737
38-
fn main() { 0 }
39-
"##]],
38+
fn main() { 0 as u32 }
39+
"#]],
4040
);
4141
}
4242

crates/hir-def/src/macro_expansion_tests/mbe.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ macro_rules! m {
922922
923923
fn bar() -> &'a Baz<u8> {}
924924
925-
fn bar() -> extern "Rust"fn() -> Ret {}
925+
fn bar() -> extern "Rust" fn() -> Ret {}
926926
"#]],
927927
);
928928
}
@@ -1333,7 +1333,7 @@ macro_rules! matches {
13331333
}
13341334
fn main() {
13351335
match 0 {
1336-
0|1if true =>true , _=>false
1336+
0|1 if true =>true , _=>false
13371337
};
13381338
}
13391339
"#]],

crates/hir-def/src/macro_expansion_tests/mbe/matching.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ fn main() {
7373
macro_rules! asi { ($($stmt:stmt)*) => ($($stmt)*); }
7474
7575
fn main() {
76-
let a = 2let b = 5drop(b-a)println!("{}", a+b)
76+
let a = 2 let b = 5 drop(b-a)println!("{}", a+b)
7777
}
7878
"#]],
7979
)

crates/hir-def/src/macro_expansion_tests/mbe/regression.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -297,55 +297,55 @@ macro_rules! impl_fn_for_zst {
297297
298298
#[derive(Clone)] struct CharEscapeDebugContinue;
299299
impl Fn<(char, )> for CharEscapeDebugContinue {
300-
#[inline] extern "rust-call"fn call(&self , (c, ): (char, )) -> char::EscapeDebug { {
300+
#[inline] extern "rust-call" fn call(&self , (c, ): (char, )) -> char::EscapeDebug { {
301301
c.escape_debug_ext(false )
302302
}
303303
}
304304
}
305305
impl FnMut<(char, )> for CharEscapeDebugContinue {
306-
#[inline] extern "rust-call"fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDebug {
306+
#[inline] extern "rust-call" fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDebug {
307307
Fn::call(&*self , (c, ))
308308
}
309309
}
310310
impl FnOnce<(char, )> for CharEscapeDebugContinue {
311311
type Output = char::EscapeDebug;
312-
#[inline] extern "rust-call"fn call_once(self , (c, ): (char, )) -> char::EscapeDebug {
312+
#[inline] extern "rust-call" fn call_once(self , (c, ): (char, )) -> char::EscapeDebug {
313313
Fn::call(&self , (c, ))
314314
}
315315
}
316316
#[derive(Clone)] struct CharEscapeUnicode;
317317
impl Fn<(char, )> for CharEscapeUnicode {
318-
#[inline] extern "rust-call"fn call(&self , (c, ): (char, )) -> char::EscapeUnicode { {
318+
#[inline] extern "rust-call" fn call(&self , (c, ): (char, )) -> char::EscapeUnicode { {
319319
c.escape_unicode()
320320
}
321321
}
322322
}
323323
impl FnMut<(char, )> for CharEscapeUnicode {
324-
#[inline] extern "rust-call"fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeUnicode {
324+
#[inline] extern "rust-call" fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeUnicode {
325325
Fn::call(&*self , (c, ))
326326
}
327327
}
328328
impl FnOnce<(char, )> for CharEscapeUnicode {
329329
type Output = char::EscapeUnicode;
330-
#[inline] extern "rust-call"fn call_once(self , (c, ): (char, )) -> char::EscapeUnicode {
330+
#[inline] extern "rust-call" fn call_once(self , (c, ): (char, )) -> char::EscapeUnicode {
331331
Fn::call(&self , (c, ))
332332
}
333333
}
334334
#[derive(Clone)] struct CharEscapeDefault;
335335
impl Fn<(char, )> for CharEscapeDefault {
336-
#[inline] extern "rust-call"fn call(&self , (c, ): (char, )) -> char::EscapeDefault { {
336+
#[inline] extern "rust-call" fn call(&self , (c, ): (char, )) -> char::EscapeDefault { {
337337
c.escape_default()
338338
}
339339
}
340340
}
341341
impl FnMut<(char, )> for CharEscapeDefault {
342-
#[inline] extern "rust-call"fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDefault {
342+
#[inline] extern "rust-call" fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDefault {
343343
Fn::call(&*self , (c, ))
344344
}
345345
}
346346
impl FnOnce<(char, )> for CharEscapeDefault {
347347
type Output = char::EscapeDefault;
348-
#[inline] extern "rust-call"fn call_once(self , (c, ): (char, )) -> char::EscapeDefault {
348+
#[inline] extern "rust-call" fn call_once(self , (c, ): (char, )) -> char::EscapeDefault {
349349
Fn::call(&self , (c, ))
350350
}
351351
}
@@ -833,7 +833,7 @@ macro_rules! rgb_color {
833833
/* parse error: expected SEMICOLON */
834834
/* parse error: expected expression, item or let statement */
835835
pub fn new() {
836-
let _ = 0as u32<<(8+8);
836+
let _ = 0 as u32<<(8+8);
837837
}
838838
// MACRO_ITEMS@0..31
839839
// FN@0..31

crates/hir-def/src/macro_expansion_tests/mod.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,13 @@ use syntax::{
3333
use tt::token_id::{Subtree, TokenId};
3434

3535
use crate::{
36-
db::DefDatabase, macro_id_to_def_id, nameres::ModuleSource, resolver::HasResolver,
37-
src::HasSource, test_db::TestDB, AdtId, AsMacroCall, Lookup, ModuleDefId,
36+
db::DefDatabase,
37+
macro_id_to_def_id,
38+
nameres::{MacroSubNs, ModuleSource},
39+
resolver::HasResolver,
40+
src::HasSource,
41+
test_db::TestDB,
42+
AdtId, AsMacroCall, Lookup, ModuleDefId,
3843
};
3944

4045
#[track_caller]
@@ -127,7 +132,9 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
127132
let macro_call = InFile::new(source.file_id, &macro_call);
128133
let res = macro_call
129134
.as_call_id_with_errors(&db, krate, |path| {
130-
resolver.resolve_path_as_macro(&db, &path).map(|it| macro_id_to_def_id(&db, it))
135+
resolver
136+
.resolve_path_as_macro(&db, &path, Some(MacroSubNs::Bang))
137+
.map(|it| macro_id_to_def_id(&db, it))
131138
})
132139
.unwrap();
133140
let macro_call_id = res.value.unwrap();
@@ -280,6 +287,7 @@ fn pretty_print_macro_expansion(expn: SyntaxNode, map: Option<&TokenMap>) -> Str
280287
let curr_kind = token.kind();
281288
let space = match (prev_kind, curr_kind) {
282289
_ if prev_kind.is_trivia() || curr_kind.is_trivia() => "",
290+
_ if prev_kind.is_literal() && !curr_kind.is_punct() => " ",
283291
(T!['{'], T!['}']) => "",
284292
(T![=], _) | (_, T![=]) => " ",
285293
(_, T!['{']) => " ",

crates/hir-def/src/nameres.rs

+64-4
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ mod tests;
5959

6060
use std::{cmp::Ord, ops::Deref};
6161

62-
use base_db::{CrateId, Edition, FileId};
62+
use base_db::{CrateId, Edition, FileId, ProcMacroKind};
6363
use hir_expand::{name::Name, InFile, MacroCallId, MacroDefId};
6464
use itertools::Itertools;
6565
use la_arena::Arena;
@@ -77,7 +77,8 @@ use crate::{
7777
path::ModPath,
7878
per_ns::PerNs,
7979
visibility::Visibility,
80-
AstId, BlockId, BlockLoc, FunctionId, LocalModuleId, MacroId, ModuleId, ProcMacroId,
80+
AstId, BlockId, BlockLoc, FunctionId, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId,
81+
ProcMacroId,
8182
};
8283

8384
/// Contains the results of (early) name resolution.
@@ -105,6 +106,9 @@ pub struct DefMap {
105106
prelude: Option<ModuleId>,
106107
/// The extern prelude is only populated for non-block DefMaps
107108
extern_prelude: FxHashMap<Name, ModuleId>,
109+
/// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that
110+
/// this contains all kinds of macro, not just `macro_rules!` macro.
111+
macro_use_prelude: FxHashMap<Name, MacroId>,
108112

109113
/// Side table for resolving derive helpers.
110114
exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
@@ -277,6 +281,7 @@ impl DefMap {
277281
edition,
278282
recursion_limit: None,
279283
extern_prelude: FxHashMap::default(),
284+
macro_use_prelude: FxHashMap::default(),
280285
exported_derives: FxHashMap::default(),
281286
fn_proc_macro_mapping: FxHashMap::default(),
282287
proc_macro_loading_error: None,
@@ -376,9 +381,16 @@ impl DefMap {
376381
original_module: LocalModuleId,
377382
path: &ModPath,
378383
shadow: BuiltinShadowMode,
384+
expected_macro_subns: Option<MacroSubNs>,
379385
) -> (PerNs, Option<usize>) {
380-
let res =
381-
self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
386+
let res = self.resolve_path_fp_with_macro(
387+
db,
388+
ResolveMode::Other,
389+
original_module,
390+
path,
391+
shadow,
392+
expected_macro_subns,
393+
);
382394
(res.resolved_def, res.segment_index)
383395
}
384396

@@ -395,6 +407,7 @@ impl DefMap {
395407
original_module,
396408
path,
397409
shadow,
410+
None, // Currently this function isn't used for macro resolution.
398411
);
399412
(res.resolved_def, res.segment_index)
400413
}
@@ -489,6 +502,7 @@ impl DefMap {
489502
_c: _,
490503
exported_derives,
491504
extern_prelude,
505+
macro_use_prelude,
492506
diagnostics,
493507
modules,
494508
registered_attrs,
@@ -507,6 +521,7 @@ impl DefMap {
507521
} = self;
508522

509523
extern_prelude.shrink_to_fit();
524+
macro_use_prelude.shrink_to_fit();
510525
exported_derives.shrink_to_fit();
511526
diagnostics.shrink_to_fit();
512527
modules.shrink_to_fit();
@@ -562,3 +577,48 @@ pub enum ModuleSource {
562577
Module(ast::Module),
563578
BlockExpr(ast::BlockExpr),
564579
}
580+
581+
/// See `sub_namespace_match()`.
582+
#[derive(Clone, Copy, PartialEq, Eq)]
583+
pub enum MacroSubNs {
584+
/// Function-like macros, suffixed with `!`.
585+
Bang,
586+
/// Macros inside attributes, i.e. attribute macros and derive macros.
587+
Attr,
588+
}
589+
590+
impl MacroSubNs {
591+
fn from_id(db: &dyn DefDatabase, macro_id: MacroId) -> Self {
592+
let expander = match macro_id {
593+
MacroId::Macro2Id(it) => it.lookup(db).expander,
594+
MacroId::MacroRulesId(it) => it.lookup(db).expander,
595+
MacroId::ProcMacroId(it) => {
596+
return match it.lookup(db).kind {
597+
ProcMacroKind::CustomDerive | ProcMacroKind::Attr => Self::Attr,
598+
ProcMacroKind::FuncLike => Self::Bang,
599+
};
600+
}
601+
};
602+
603+
// Eager macros aren't *guaranteed* to be bang macros, but they *are* all bang macros currently.
604+
match expander {
605+
MacroExpander::Declarative
606+
| MacroExpander::BuiltIn(_)
607+
| MacroExpander::BuiltInEager(_) => Self::Bang,
608+
MacroExpander::BuiltInAttr(_) | MacroExpander::BuiltInDerive(_) => Self::Attr,
609+
}
610+
}
611+
}
612+
613+
/// Quoted from [rustc]:
614+
/// Macro namespace is separated into two sub-namespaces, one for bang macros and
615+
/// one for attribute-like macros (attributes, derives).
616+
/// We ignore resolutions from one sub-namespace when searching names in scope for another.
617+
///
618+
/// [rustc]: https://github.com/rust-lang/rust/blob/1.69.0/compiler/rustc_resolve/src/macros.rs#L75
619+
fn sub_namespace_match(candidate: Option<MacroSubNs>, expected: Option<MacroSubNs>) -> bool {
620+
match (candidate, expected) {
621+
(Some(candidate), Some(expected)) => candidate == expected,
622+
_ => true,
623+
}
624+
}

crates/hir-def/src/nameres/attr_resolution.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414
AstIdWithPath, LocalModuleId, UnresolvedMacro,
1515
};
1616

17-
use super::DefMap;
17+
use super::{DefMap, MacroSubNs};
1818

1919
pub enum ResolvedAttr {
2020
/// Attribute resolved to an attribute macro.
@@ -43,9 +43,12 @@ impl DefMap {
4343
original_module,
4444
&ast_id.path,
4545
BuiltinShadowMode::Module,
46+
Some(MacroSubNs::Attr),
4647
);
4748
let def = match resolved_res.resolved_def.take_macros() {
4849
Some(def) => {
50+
// `MacroSubNs` is just a hint, so the path may still resolve to a custom derive
51+
// macro, or even function-like macro when the path is qualified.
4952
if def.is_attribute(db) {
5053
def
5154
} else {

0 commit comments

Comments
 (0)