Skip to content

Commit d0aaf89

Browse files
committed
resolve: Future proof resolutions for potentially built-in attributes
1 parent 730c5de commit d0aaf89

8 files changed

+274
-0
lines changed

src/librustc_resolve/build_reduced_graph.rs

+10
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use syntax::ext::base::{MacroKind, SyntaxExtension};
3939
use syntax::ext::base::Determinacy::Undetermined;
4040
use syntax::ext::hygiene::Mark;
4141
use syntax::ext::tt::macro_rules;
42+
use syntax::feature_gate::is_builtin_attr;
4243
use syntax::parse::token::{self, Token};
4344
use syntax::std_inject::injected_crate_name;
4445
use syntax::symbol::keywords;
@@ -1057,4 +1058,13 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
10571058
}
10581059
}
10591060
}
1061+
1062+
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
1063+
if !attr.is_sugared_doc && is_builtin_attr(attr) {
1064+
self.resolver.current_module.builtin_attrs.borrow_mut().push((
1065+
attr.path.segments[0].ident, self.expansion, self.current_legacy_scope
1066+
));
1067+
}
1068+
visit::walk_attribute(self, attr);
1069+
}
10601070
}

src/librustc_resolve/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,7 @@ pub struct ModuleData<'a> {
10121012
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
10131013
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, Mark, LegacyScope<'a>, Option<Def>)>>,
10141014
macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
1015+
builtin_attrs: RefCell<Vec<(Ident, Mark, LegacyScope<'a>)>>,
10151016

10161017
// Macro invocations that can expand into items in this module.
10171018
unresolved_invocations: RefCell<FxHashSet<Mark>>,
@@ -1050,6 +1051,7 @@ impl<'a> ModuleData<'a> {
10501051
resolutions: RefCell::new(FxHashMap()),
10511052
legacy_macro_resolutions: RefCell::new(Vec::new()),
10521053
macro_resolutions: RefCell::new(Vec::new()),
1054+
builtin_attrs: RefCell::new(Vec::new()),
10531055
unresolved_invocations: RefCell::new(FxHashSet()),
10541056
no_implicit_prelude: false,
10551057
glob_importers: RefCell::new(Vec::new()),

src/librustc_resolve/macros.rs

+20
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,26 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
956956
}
957957
};
958958
}
959+
960+
for &(ident, parent_expansion, parent_legacy_scope)
961+
in module.builtin_attrs.borrow().iter() {
962+
let resolve_legacy = |this: &mut Self| this.resolve_legacy_scope(
963+
ident, parent_expansion, parent_legacy_scope, true, true
964+
);
965+
let resolve_modern = |this: &mut Self| this.resolve_lexical_macro_path_segment(
966+
ident, MacroNS, parent_expansion, true, true, true, ident.span
967+
).map(|(binding, _)| binding).ok();
968+
969+
if let Some(binding) = resolve_legacy(self).or_else(|| resolve_modern(self)) {
970+
if binding.def_ignoring_ambiguity() !=
971+
Def::NonMacroAttr(NonMacroAttrKind::Builtin) {
972+
let builtin_binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
973+
ty::Visibility::Public, ident.span, Mark::root())
974+
.to_name_binding(self.arenas);
975+
self.report_ambiguity_error(ident, binding, builtin_binding);
976+
}
977+
}
978+
}
959979
}
960980

961981
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// aux-build:builtin-attrs.rs
2+
// compile-flags:--test
3+
4+
#![feature(decl_macro, test)]
5+
6+
extern crate test;
7+
extern crate builtin_attrs;
8+
use builtin_attrs::{test, bench};
9+
10+
#[test] // OK, shadowed
11+
fn test() {}
12+
13+
#[bench] // OK, shadowed
14+
fn bench(b: &mut test::Bencher) {}
15+
16+
fn not_main() {
17+
Test;
18+
Bench;
19+
NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0425]: cannot find value `NonExistent` in this scope
2+
--> $DIR/ambiguous-builtin-attrs-test.rs:19:5
3+
|
4+
LL | NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
5+
| ^^^^^^^^^^^ not found in this scope
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0425`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// aux-build:builtin-attrs.rs
2+
3+
#![feature(decl_macro)] //~ ERROR `feature` is ambiguous
4+
5+
extern crate builtin_attrs;
6+
use builtin_attrs::{test, bench};
7+
use builtin_attrs::*;
8+
9+
#[repr(C)] //~ ERROR `repr` is ambiguous
10+
struct S;
11+
#[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous
12+
struct SCond;
13+
14+
#[cfg(all())] //~ ERROR `cfg` is ambiguous
15+
struct A;
16+
#[cfg(any())] // ERROR FIXME
17+
struct A;
18+
19+
#[cfg_attr(all(), cold)] // ERROR FIXME
20+
fn g() {}
21+
#[cfg_attr(any(), cold)] // ERROR FIXME
22+
fn h() {}
23+
24+
#[derive(Clone)] // ERROR FIXME
25+
struct B;
26+
27+
#[test] // OK, shadowed
28+
fn test() {}
29+
30+
#[bench] // OK, shadowed
31+
fn bench() {}
32+
33+
fn non_macro_expanded_location<#[repr(C)] T>() { //~ ERROR `repr` is ambiguous
34+
match 0u8 {
35+
#[repr(C)] //~ ERROR `repr` is ambiguous
36+
_ => {}
37+
}
38+
}
39+
40+
fn main() {
41+
Test;
42+
Bench;
43+
NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
error[E0659]: `repr` is ambiguous
2+
--> $DIR/ambiguous-builtin-attrs.rs:9:3
3+
|
4+
LL | #[repr(C)] //~ ERROR `repr` is ambiguous
5+
| ^^^^ ambiguous name
6+
|
7+
note: `repr` could refer to the name imported here
8+
--> $DIR/ambiguous-builtin-attrs.rs:7:5
9+
|
10+
LL | use builtin_attrs::*;
11+
| ^^^^^^^^^^^^^^^^
12+
note: `repr` could also refer to the name defined here
13+
--> $DIR/ambiguous-builtin-attrs.rs:9:3
14+
|
15+
LL | #[repr(C)] //~ ERROR `repr` is ambiguous
16+
| ^^^^
17+
= note: consider adding an explicit import of `repr` to disambiguate
18+
19+
error[E0659]: `repr` is ambiguous
20+
--> $DIR/ambiguous-builtin-attrs.rs:11:19
21+
|
22+
LL | #[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous
23+
| ^^^^ ambiguous name
24+
|
25+
note: `repr` could refer to the name imported here
26+
--> $DIR/ambiguous-builtin-attrs.rs:7:5
27+
|
28+
LL | use builtin_attrs::*;
29+
| ^^^^^^^^^^^^^^^^
30+
note: `repr` could also refer to the name defined here
31+
--> $DIR/ambiguous-builtin-attrs.rs:11:19
32+
|
33+
LL | #[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous
34+
| ^^^^
35+
= note: consider adding an explicit import of `repr` to disambiguate
36+
37+
error[E0659]: `cfg` is ambiguous
38+
--> $DIR/ambiguous-builtin-attrs.rs:14:3
39+
|
40+
LL | #[cfg(all())] //~ ERROR `cfg` is ambiguous
41+
| ^^^ ambiguous name
42+
|
43+
note: `cfg` could refer to the name imported here
44+
--> $DIR/ambiguous-builtin-attrs.rs:7:5
45+
|
46+
LL | use builtin_attrs::*;
47+
| ^^^^^^^^^^^^^^^^
48+
note: `cfg` could also refer to the name defined here
49+
--> $DIR/ambiguous-builtin-attrs.rs:14:3
50+
|
51+
LL | #[cfg(all())] //~ ERROR `cfg` is ambiguous
52+
| ^^^
53+
= note: consider adding an explicit import of `cfg` to disambiguate
54+
55+
error[E0659]: `repr` is ambiguous
56+
--> $DIR/ambiguous-builtin-attrs.rs:33:34
57+
|
58+
LL | fn non_macro_expanded_location<#[repr(C)] T>() { //~ ERROR `repr` is ambiguous
59+
| ^^^^ ambiguous name
60+
|
61+
note: `repr` could refer to the name imported here
62+
--> $DIR/ambiguous-builtin-attrs.rs:7:5
63+
|
64+
LL | use builtin_attrs::*;
65+
| ^^^^^^^^^^^^^^^^
66+
note: `repr` could also refer to the name defined here
67+
--> $DIR/ambiguous-builtin-attrs.rs:33:34
68+
|
69+
LL | fn non_macro_expanded_location<#[repr(C)] T>() { //~ ERROR `repr` is ambiguous
70+
| ^^^^
71+
= note: consider adding an explicit import of `repr` to disambiguate
72+
73+
error[E0659]: `repr` is ambiguous
74+
--> $DIR/ambiguous-builtin-attrs.rs:35:11
75+
|
76+
LL | #[repr(C)] //~ ERROR `repr` is ambiguous
77+
| ^^^^ ambiguous name
78+
|
79+
note: `repr` could refer to the name imported here
80+
--> $DIR/ambiguous-builtin-attrs.rs:7:5
81+
|
82+
LL | use builtin_attrs::*;
83+
| ^^^^^^^^^^^^^^^^
84+
note: `repr` could also refer to the name defined here
85+
--> $DIR/ambiguous-builtin-attrs.rs:35:11
86+
|
87+
LL | #[repr(C)] //~ ERROR `repr` is ambiguous
88+
| ^^^^
89+
= note: consider adding an explicit import of `repr` to disambiguate
90+
91+
error[E0659]: `feature` is ambiguous
92+
--> $DIR/ambiguous-builtin-attrs.rs:3:4
93+
|
94+
LL | #![feature(decl_macro)] //~ ERROR `feature` is ambiguous
95+
| ^^^^^^^ ambiguous name
96+
|
97+
note: `feature` could refer to the name imported here
98+
--> $DIR/ambiguous-builtin-attrs.rs:7:5
99+
|
100+
LL | use builtin_attrs::*;
101+
| ^^^^^^^^^^^^^^^^
102+
note: `feature` could also refer to the name defined here
103+
--> $DIR/ambiguous-builtin-attrs.rs:3:4
104+
|
105+
LL | #![feature(decl_macro)] //~ ERROR `feature` is ambiguous
106+
| ^^^^^^^
107+
= note: consider adding an explicit import of `feature` to disambiguate
108+
109+
error[E0425]: cannot find value `NonExistent` in this scope
110+
--> $DIR/ambiguous-builtin-attrs.rs:43:5
111+
|
112+
LL | NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
113+
| ^^^^^^^^^^^ not found in this scope
114+
115+
error: aborting due to 7 previous errors
116+
117+
Some errors occurred: E0425, E0659.
118+
For more information about an error, try `rustc --explain E0425`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2016 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+
// no-prefer-dynamic
12+
13+
#![crate_type = "proc-macro"]
14+
15+
extern crate proc_macro;
16+
use proc_macro::*;
17+
18+
#[proc_macro_attribute]
19+
pub fn feature(_: TokenStream, input: TokenStream) -> TokenStream {
20+
input
21+
}
22+
23+
#[proc_macro_attribute]
24+
pub fn repr(_: TokenStream, input: TokenStream) -> TokenStream {
25+
input
26+
}
27+
28+
#[proc_macro_attribute]
29+
pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
30+
input
31+
}
32+
33+
#[proc_macro_attribute]
34+
pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
35+
input
36+
}
37+
38+
#[proc_macro_attribute]
39+
pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream {
40+
input
41+
}
42+
43+
#[proc_macro_attribute]
44+
pub fn test(_: TokenStream, input: TokenStream) -> TokenStream {
45+
"struct Test;".parse().unwrap()
46+
}
47+
48+
#[proc_macro_attribute]
49+
pub fn bench(_: TokenStream, input: TokenStream) -> TokenStream {
50+
"struct Bench;".parse().unwrap()
51+
}

0 commit comments

Comments
 (0)