]> git.lizzy.rs Git - rust.git/commitdiff
resolve: Future proof resolutions for potentially built-in attributes
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sun, 2 Sep 2018 21:04:54 +0000 (00:04 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Mon, 10 Sep 2018 21:30:44 +0000 (00:30 +0300)
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs-test.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs-test.stderr [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/auxiliary/builtin-attrs.rs [new file with mode: 0644]

index 1fa9979edb8d3128e5dec763e5b1aef467ae3ae2..d1a05964c8f6497c0993fc342a40ee201c7e1817 100644 (file)
@@ -39,6 +39,7 @@
 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;
@@ -1057,4 +1058,13 @@ fn visit_token(&mut self, t: Token) {
             }
         }
     }
+
+    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);
+    }
 }
index 2bf110d2723e72577b187b9db5d42cc61c37c7d0..142e987d9521997fa4269aa4954648b58cb2dc02 100644 (file)
@@ -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>>,
@@ -1050,6 +1051,7 @@ fn new(parent: Option<Module<'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()),
index 920d8a6341b3d935eb6168107c2fbb7602d14294..07ea345ca066c24008943491d2344d2fdc878726 100644 (file)
@@ -956,6 +956,26 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
                 }
             };
         }
+
+        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,
diff --git a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs-test.rs b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs-test.rs
new file mode 100644 (file)
index 0000000..6a47e50
--- /dev/null
@@ -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
+}
diff --git a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs-test.stderr b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs-test.stderr
new file mode 100644 (file)
index 0000000..db07055
--- /dev/null
@@ -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`.
diff --git a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.rs
new file mode 100644 (file)
index 0000000..b3a50e8
--- /dev/null
@@ -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
+}
diff --git a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr
new file mode 100644 (file)
index 0000000..2bf3082
--- /dev/null
@@ -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`.
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/builtin-attrs.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/builtin-attrs.rs
new file mode 100644 (file)
index 0000000..332df81
--- /dev/null
@@ -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()
+}