Skip to content

Commit beb3b5d

Browse files
committed
resolve: Introduce two sub-namespaces in macro namespace
1 parent 994cdd9 commit beb3b5d

10 files changed

+64
-35
lines changed

src/librustc_resolve/macros.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,21 @@ pub struct ProcMacError {
118118
warn_msg: &'static str,
119119
}
120120

121-
// For compatibility bang macros are skipped when resolving potentially built-in attributes.
122-
fn macro_kind_mismatch(name: Name, requirement: Option<MacroKind>, candidate: Option<MacroKind>)
123-
-> bool {
124-
requirement == Some(MacroKind::Attr) && candidate == Some(MacroKind::Bang) &&
125-
(name == "test" || name == "bench" || is_builtin_attr_name(name))
121+
// Macro namespace is separated into two sub-namespaces, one for bang macros and
122+
// one for attribute-like macros (attributes, derives).
123+
// We ignore resolutions from one sub-namespace when searching names in scope for another.
124+
fn sub_namespace_mismatch(requirement: Option<MacroKind>, candidate: Option<MacroKind>) -> bool {
125+
#[derive(PartialEq)]
126+
enum SubNS { Bang, AttrLike }
127+
let sub_ns = |kind| match kind {
128+
MacroKind::Bang => Some(SubNS::Bang),
129+
MacroKind::Attr | MacroKind::Derive => Some(SubNS::AttrLike),
130+
MacroKind::ProcMacroStub => None,
131+
};
132+
let requirement = requirement.and_then(|kind| sub_ns(kind));
133+
let candidate = candidate.and_then(|kind| sub_ns(kind));
134+
// "No specific sub-namespace" means "matches anything" for both requirements and candidates.
135+
candidate.is_some() && requirement.is_some() && candidate != requirement
126136
}
127137

128138
impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
@@ -641,10 +651,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
641651
}
642652
}
643653
WhereToResolve::BuiltinAttrs => {
644-
// FIXME: Only built-in attributes are not considered as candidates for
645-
// non-attributes to fight off regressions on stable channel (#53205).
646-
// We need to come up with some more principled approach instead.
647-
if kind == Some(MacroKind::Attr) && is_builtin_attr_name(ident.name) {
654+
if is_builtin_attr_name(ident.name) {
648655
let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
649656
ty::Visibility::Public, ident.span, Mark::root())
650657
.to_name_binding(self.arenas);
@@ -765,7 +772,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
765772

766773
match result {
767774
Ok(result) => {
768-
if macro_kind_mismatch(ident.name, kind, result.0.macro_kind()) {
775+
if sub_namespace_mismatch(kind, result.0.macro_kind()) {
769776
continue_search!();
770777
}
771778

@@ -829,7 +836,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
829836
parent_scope: &ParentScope<'a>,
830837
record_used: bool,
831838
) -> Option<&'a NameBinding<'a>> {
832-
if macro_kind_mismatch(ident.name, kind, Some(MacroKind::Bang)) {
839+
if sub_namespace_mismatch(kind, Some(MacroKind::Bang)) {
833840
return None;
834841
}
835842

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#[macro_export]
2+
macro_rules! my_attr { () => () }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// no-prefer-dynamic
2+
3+
#![crate_type = "proc-macro"]
4+
5+
extern crate proc_macro;
6+
use proc_macro::*;
7+
8+
#[proc_macro_derive(MyTrait, attributes(my_attr))]
9+
pub fn foo(_: TokenStream) -> TokenStream {
10+
TokenStream::new()
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// compile-pass
2+
// aux-build:derive-helper-shadowed.rs
3+
// aux-build:derive-helper-shadowed-2.rs
4+
5+
#[macro_use]
6+
extern crate derive_helper_shadowed;
7+
#[macro_use(my_attr)]
8+
extern crate derive_helper_shadowed_2;
9+
10+
macro_rules! my_attr { () => () }
11+
12+
#[derive(MyTrait)]
13+
#[my_attr] // OK
14+
struct S;
15+
16+
fn main() {}

src/test/ui/issues/issue-11692-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
concat!(test!()); //~ ERROR `test` can only be used in attributes
12+
concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
1313
}

src/test/ui/issues/issue-11692-2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
error: `test` can only be used in attributes
1+
error: cannot find macro `test!` in this scope
22
--> $DIR/issue-11692-2.rs:12:13
33
|
4-
LL | concat!(test!()); //~ ERROR `test` can only be used in attributes
4+
LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
55
| ^^^^
66

77
error: aborting due to previous error
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,3 @@
1-
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2-
// file at the top-level directory of this distribution and at
3-
// http://rust-lang.org/COPYRIGHT.
4-
//
5-
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6-
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7-
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8-
// option. This file may not be copied, modified, or distributed
9-
// except according to those terms.
10-
11-
#[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope
12-
struct S;
13-
141
fn main() {
152
inline!(); //~ ERROR cannot find macro `inline!` in this scope
163
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
error: cannot find derive macro `inline` in this scope
2-
--> $DIR/macro-path-prelude-fail-3.rs:11:10
3-
|
4-
LL | #[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope
5-
| ^^^^^^
6-
71
error: cannot find macro `inline!` in this scope
8-
--> $DIR/macro-path-prelude-fail-3.rs:15:5
2+
--> $DIR/macro-path-prelude-fail-3.rs:2:5
93
|
104
LL | inline!(); //~ ERROR cannot find macro `inline!` in this scope
115
| ^^^^^^ help: you could try the macro: `line`
126

13-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
148

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[derive(inline)] //~ ERROR expected a macro, found built-in attribute
2+
struct S;
3+
4+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: expected a macro, found built-in attribute
2+
--> $DIR/macro-path-prelude-fail-4.rs:1:10
3+
|
4+
LL | #[derive(inline)] //~ ERROR expected a macro, found built-in attribute
5+
| ^^^^^^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)