Skip to content

Commit

Permalink
resolve: Future proof resolutions for potentially built-in attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Sep 10, 2018
1 parent 730c5de commit d0aaf89
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/librustc_resolve/build_reduced_graph.rs
Expand Up @@ -39,6 +39,7 @@ use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::base::Determinacy::Undetermined;
use syntax::ext::hygiene::Mark;
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::is_builtin_attr;
use syntax::parse::token::{self, Token};
use syntax::std_inject::injected_crate_name;
use syntax::symbol::keywords;
Expand Down Expand Up @@ -1057,4 +1058,13 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
}
}
}

fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
if !attr.is_sugared_doc && is_builtin_attr(attr) {
self.resolver.current_module.builtin_attrs.borrow_mut().push((
attr.path.segments[0].ident, self.expansion, self.current_legacy_scope
));
}
visit::walk_attribute(self, attr);
}
}
2 changes: 2 additions & 0 deletions src/librustc_resolve/lib.rs
Expand Up @@ -1012,6 +1012,7 @@ pub struct ModuleData<'a> {
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, Mark, LegacyScope<'a>, Option<Def>)>>,
macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
builtin_attrs: RefCell<Vec<(Ident, Mark, LegacyScope<'a>)>>,

// Macro invocations that can expand into items in this module.
unresolved_invocations: RefCell<FxHashSet<Mark>>,
Expand Down Expand Up @@ -1050,6 +1051,7 @@ impl<'a> ModuleData<'a> {
resolutions: RefCell::new(FxHashMap()),
legacy_macro_resolutions: RefCell::new(Vec::new()),
macro_resolutions: RefCell::new(Vec::new()),
builtin_attrs: RefCell::new(Vec::new()),
unresolved_invocations: RefCell::new(FxHashSet()),
no_implicit_prelude: false,
glob_importers: RefCell::new(Vec::new()),
Expand Down
20 changes: 20 additions & 0 deletions src/librustc_resolve/macros.rs
Expand Up @@ -956,6 +956,26 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}
};
}

for &(ident, parent_expansion, parent_legacy_scope)
in module.builtin_attrs.borrow().iter() {
let resolve_legacy = |this: &mut Self| this.resolve_legacy_scope(
ident, parent_expansion, parent_legacy_scope, true, true
);
let resolve_modern = |this: &mut Self| this.resolve_lexical_macro_path_segment(
ident, MacroNS, parent_expansion, true, true, true, ident.span
).map(|(binding, _)| binding).ok();

if let Some(binding) = resolve_legacy(self).or_else(|| resolve_modern(self)) {
if binding.def_ignoring_ambiguity() !=
Def::NonMacroAttr(NonMacroAttrKind::Builtin) {
let builtin_binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
ty::Visibility::Public, ident.span, Mark::root())
.to_name_binding(self.arenas);
self.report_ambiguity_error(ident, binding, builtin_binding);
}
}
}
}

fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
Expand Down
20 changes: 20 additions & 0 deletions src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs-test.rs
@@ -0,0 +1,20 @@
// aux-build:builtin-attrs.rs
// compile-flags:--test

#![feature(decl_macro, test)]

extern crate test;
extern crate builtin_attrs;
use builtin_attrs::{test, bench};

#[test] // OK, shadowed
fn test() {}

#[bench] // OK, shadowed
fn bench(b: &mut test::Bencher) {}

fn not_main() {
Test;
Bench;
NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
}
@@ -0,0 +1,9 @@
error[E0425]: cannot find value `NonExistent` in this scope
--> $DIR/ambiguous-builtin-attrs-test.rs:19:5
|
LL | NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
| ^^^^^^^^^^^ not found in this scope

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.
44 changes: 44 additions & 0 deletions src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.rs
@@ -0,0 +1,44 @@
// aux-build:builtin-attrs.rs

#![feature(decl_macro)] //~ ERROR `feature` is ambiguous

extern crate builtin_attrs;
use builtin_attrs::{test, bench};
use builtin_attrs::*;

#[repr(C)] //~ ERROR `repr` is ambiguous
struct S;
#[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous
struct SCond;

#[cfg(all())] //~ ERROR `cfg` is ambiguous
struct A;
#[cfg(any())] // ERROR FIXME
struct A;

#[cfg_attr(all(), cold)] // ERROR FIXME
fn g() {}
#[cfg_attr(any(), cold)] // ERROR FIXME
fn h() {}

#[derive(Clone)] // ERROR FIXME
struct B;

#[test] // OK, shadowed
fn test() {}

#[bench] // OK, shadowed
fn bench() {}

fn non_macro_expanded_location<#[repr(C)] T>() { //~ ERROR `repr` is ambiguous
match 0u8 {
#[repr(C)] //~ ERROR `repr` is ambiguous
_ => {}
}
}

fn main() {
Test;
Bench;
NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
}
118 changes: 118 additions & 0 deletions src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr
@@ -0,0 +1,118 @@
error[E0659]: `repr` is ambiguous
--> $DIR/ambiguous-builtin-attrs.rs:9:3
|
LL | #[repr(C)] //~ ERROR `repr` is ambiguous
| ^^^^ ambiguous name
|
note: `repr` could refer to the name imported here
--> $DIR/ambiguous-builtin-attrs.rs:7:5
|
LL | use builtin_attrs::*;
| ^^^^^^^^^^^^^^^^
note: `repr` could also refer to the name defined here
--> $DIR/ambiguous-builtin-attrs.rs:9:3
|
LL | #[repr(C)] //~ ERROR `repr` is ambiguous
| ^^^^
= note: consider adding an explicit import of `repr` to disambiguate

error[E0659]: `repr` is ambiguous
--> $DIR/ambiguous-builtin-attrs.rs:11:19
|
LL | #[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous
| ^^^^ ambiguous name
|
note: `repr` could refer to the name imported here
--> $DIR/ambiguous-builtin-attrs.rs:7:5
|
LL | use builtin_attrs::*;
| ^^^^^^^^^^^^^^^^
note: `repr` could also refer to the name defined here
--> $DIR/ambiguous-builtin-attrs.rs:11:19
|
LL | #[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous
| ^^^^
= note: consider adding an explicit import of `repr` to disambiguate

error[E0659]: `cfg` is ambiguous
--> $DIR/ambiguous-builtin-attrs.rs:14:3
|
LL | #[cfg(all())] //~ ERROR `cfg` is ambiguous
| ^^^ ambiguous name
|
note: `cfg` could refer to the name imported here
--> $DIR/ambiguous-builtin-attrs.rs:7:5
|
LL | use builtin_attrs::*;
| ^^^^^^^^^^^^^^^^
note: `cfg` could also refer to the name defined here
--> $DIR/ambiguous-builtin-attrs.rs:14:3
|
LL | #[cfg(all())] //~ ERROR `cfg` is ambiguous
| ^^^
= note: consider adding an explicit import of `cfg` to disambiguate

error[E0659]: `repr` is ambiguous
--> $DIR/ambiguous-builtin-attrs.rs:33:34
|
LL | fn non_macro_expanded_location<#[repr(C)] T>() { //~ ERROR `repr` is ambiguous
| ^^^^ ambiguous name
|
note: `repr` could refer to the name imported here
--> $DIR/ambiguous-builtin-attrs.rs:7:5
|
LL | use builtin_attrs::*;
| ^^^^^^^^^^^^^^^^
note: `repr` could also refer to the name defined here
--> $DIR/ambiguous-builtin-attrs.rs:33:34
|
LL | fn non_macro_expanded_location<#[repr(C)] T>() { //~ ERROR `repr` is ambiguous
| ^^^^
= note: consider adding an explicit import of `repr` to disambiguate

error[E0659]: `repr` is ambiguous
--> $DIR/ambiguous-builtin-attrs.rs:35:11
|
LL | #[repr(C)] //~ ERROR `repr` is ambiguous
| ^^^^ ambiguous name
|
note: `repr` could refer to the name imported here
--> $DIR/ambiguous-builtin-attrs.rs:7:5
|
LL | use builtin_attrs::*;
| ^^^^^^^^^^^^^^^^
note: `repr` could also refer to the name defined here
--> $DIR/ambiguous-builtin-attrs.rs:35:11
|
LL | #[repr(C)] //~ ERROR `repr` is ambiguous
| ^^^^
= note: consider adding an explicit import of `repr` to disambiguate

error[E0659]: `feature` is ambiguous
--> $DIR/ambiguous-builtin-attrs.rs:3:4
|
LL | #![feature(decl_macro)] //~ ERROR `feature` is ambiguous
| ^^^^^^^ ambiguous name
|
note: `feature` could refer to the name imported here
--> $DIR/ambiguous-builtin-attrs.rs:7:5
|
LL | use builtin_attrs::*;
| ^^^^^^^^^^^^^^^^
note: `feature` could also refer to the name defined here
--> $DIR/ambiguous-builtin-attrs.rs:3:4
|
LL | #![feature(decl_macro)] //~ ERROR `feature` is ambiguous
| ^^^^^^^
= note: consider adding an explicit import of `feature` to disambiguate

error[E0425]: cannot find value `NonExistent` in this scope
--> $DIR/ambiguous-builtin-attrs.rs:43:5
|
LL | NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
| ^^^^^^^^^^^ not found in this scope

error: aborting due to 7 previous errors

Some errors occurred: E0425, E0659.
For more information about an error, try `rustc --explain E0425`.
51 changes: 51 additions & 0 deletions src/test/ui-fulldeps/proc-macro/auxiliary/builtin-attrs.rs
@@ -0,0 +1,51 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// no-prefer-dynamic

#![crate_type = "proc-macro"]

extern crate proc_macro;
use proc_macro::*;

#[proc_macro_attribute]
pub fn feature(_: TokenStream, input: TokenStream) -> TokenStream {
input
}

#[proc_macro_attribute]
pub fn repr(_: TokenStream, input: TokenStream) -> TokenStream {
input
}

#[proc_macro_attribute]
pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
input
}

#[proc_macro_attribute]
pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
input
}

#[proc_macro_attribute]
pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream {
input
}

#[proc_macro_attribute]
pub fn test(_: TokenStream, input: TokenStream) -> TokenStream {
"struct Test;".parse().unwrap()
}

#[proc_macro_attribute]
pub fn bench(_: TokenStream, input: TokenStream) -> TokenStream {
"struct Bench;".parse().unwrap()
}

0 comments on commit d0aaf89

Please sign in to comment.