summaryrefslogtreecommitdiffstats
path: root/src/test/ui/attributes
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/attributes')
-rw-r--r--src/test/ui/attributes/attr-before-view-item.rs10
-rw-r--r--src/test/ui/attributes/attr-before-view-item2.rs12
-rw-r--r--src/test/ui/attributes/attr-eq-token-tree.rs2
-rw-r--r--src/test/ui/attributes/attr-eq-token-tree.stderr8
-rw-r--r--src/test/ui/attributes/attr-mix-new.rs11
-rw-r--r--src/test/ui/attributes/attrs-on-params.rs8
-rw-r--r--src/test/ui/attributes/attrs-on-params.stderr17
-rw-r--r--src/test/ui/attributes/attrs-with-no-formal-in-generics-1.rs13
-rw-r--r--src/test/ui/attributes/attrs-with-no-formal-in-generics-1.stderr8
-rw-r--r--src/test/ui/attributes/attrs-with-no-formal-in-generics-2.rs12
-rw-r--r--src/test/ui/attributes/attrs-with-no-formal-in-generics-2.stderr8
-rw-r--r--src/test/ui/attributes/attrs-with-no-formal-in-generics-3.rs12
-rw-r--r--src/test/ui/attributes/attrs-with-no-formal-in-generics-3.stderr8
-rw-r--r--src/test/ui/attributes/auxiliary/key-value-expansion.rs12
-rw-r--r--src/test/ui/attributes/class-attributes-1.rs19
-rw-r--r--src/test/ui/attributes/class-attributes-2.rs31
-rw-r--r--src/test/ui/attributes/const-stability-on-macro.rs16
-rw-r--r--src/test/ui/attributes/const-stability-on-macro.stderr20
-rw-r--r--src/test/ui/attributes/doc-attr.rs25
-rw-r--r--src/test/ui/attributes/doc-attr.stderr71
-rw-r--r--src/test/ui/attributes/duplicated-attributes.rs41
-rw-r--r--src/test/ui/attributes/duplicated-attributes.stderr22
-rw-r--r--src/test/ui/attributes/extented-attribute-macro-error.rs7
-rw-r--r--src/test/ui/attributes/extented-attribute-macro-error.stderr10
-rw-r--r--src/test/ui/attributes/field-attributes-vis-unresolved.rs25
-rw-r--r--src/test/ui/attributes/field-attributes-vis-unresolved.stderr19
-rw-r--r--src/test/ui/attributes/invalid-doc-attr.rs32
-rw-r--r--src/test/ui/attributes/invalid-doc-attr.stderr78
-rw-r--r--src/test/ui/attributes/issue-40962.rs11
-rw-r--r--src/test/ui/attributes/issue-90873.rs9
-rw-r--r--src/test/ui/attributes/issue-90873.stderr44
-rw-r--r--src/test/ui/attributes/item-attributes.rs174
-rw-r--r--src/test/ui/attributes/key-value-expansion-on-mac.rs14
-rw-r--r--src/test/ui/attributes/key-value-expansion-on-mac.stderr8
-rw-r--r--src/test/ui/attributes/key-value-expansion.rs55
-rw-r--r--src/test/ui/attributes/key-value-expansion.stderr35
-rw-r--r--src/test/ui/attributes/key-value-non-ascii.rs4
-rw-r--r--src/test/ui/attributes/key-value-non-ascii.stderr13
-rw-r--r--src/test/ui/attributes/main-removed-1.rs2
-rw-r--r--src/test/ui/attributes/main-removed-1.stderr10
-rw-r--r--src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs12
-rw-r--r--src/test/ui/attributes/main-removed-2/main.rs11
-rw-r--r--src/test/ui/attributes/method-attributes.rs28
-rw-r--r--src/test/ui/attributes/multiple-invalid.rs10
-rw-r--r--src/test/ui/attributes/multiple-invalid.stderr21
-rw-r--r--src/test/ui/attributes/nonterminal-expansion.rs18
-rw-r--r--src/test/ui/attributes/nonterminal-expansion.stderr25
-rw-r--r--src/test/ui/attributes/obsolete-attr.rs9
-rw-r--r--src/test/ui/attributes/obsolete-attr.stderr14
-rw-r--r--src/test/ui/attributes/register-attr-tool-fail.rs13
-rw-r--r--src/test/ui/attributes/register-attr-tool-fail.stderr42
-rw-r--r--src/test/ui/attributes/register-attr-tool-import.rs17
-rw-r--r--src/test/ui/attributes/register-attr-tool-import.stderr38
-rw-r--r--src/test/ui/attributes/register-attr-tool-prelude.rs14
-rw-r--r--src/test/ui/attributes/register-attr-tool-prelude.stderr15
-rw-r--r--src/test/ui/attributes/register-attr-tool-unused.rs8
-rw-r--r--src/test/ui/attributes/register-attr-tool-unused.stderr21
-rw-r--r--src/test/ui/attributes/register-attr-tool.rs19
-rw-r--r--src/test/ui/attributes/suffixed-literal-meta.rs15
-rw-r--r--src/test/ui/attributes/suffixed-literal-meta.stderr98
-rw-r--r--src/test/ui/attributes/tool_attributes.rs13
-rw-r--r--src/test/ui/attributes/unknown-attr.rs12
-rw-r--r--src/test/ui/attributes/unknown-attr.stderr20
-rw-r--r--src/test/ui/attributes/unnamed-field-attributes-dup.rs11
-rw-r--r--src/test/ui/attributes/unnamed-field-attributes-vis.rs11
-rw-r--r--src/test/ui/attributes/unnamed-field-attributes.rs9
-rw-r--r--src/test/ui/attributes/unrestricted-attribute-tokens.rs8
-rw-r--r--src/test/ui/attributes/used_with_arg.rs19
-rw-r--r--src/test/ui/attributes/used_with_arg.stderr18
-rw-r--r--src/test/ui/attributes/used_with_arg_no_mangle.rs9
-rw-r--r--src/test/ui/attributes/used_with_multi_args.rs6
-rw-r--r--src/test/ui/attributes/used_with_multi_args.stderr8
-rw-r--r--src/test/ui/attributes/variant-attributes.rs37
73 files changed, 1565 insertions, 0 deletions
diff --git a/src/test/ui/attributes/attr-before-view-item.rs b/src/test/ui/attributes/attr-before-view-item.rs
new file mode 100644
index 000000000..e1588aada
--- /dev/null
+++ b/src/test/ui/attributes/attr-before-view-item.rs
@@ -0,0 +1,10 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// pretty-expanded FIXME #23616
+
+#![feature(rustc_attrs)]
+#![feature(test)]
+
+#[rustc_dummy = "bar"]
+extern crate test;
+
+fn main() {}
diff --git a/src/test/ui/attributes/attr-before-view-item2.rs b/src/test/ui/attributes/attr-before-view-item2.rs
new file mode 100644
index 000000000..c1f667372
--- /dev/null
+++ b/src/test/ui/attributes/attr-before-view-item2.rs
@@ -0,0 +1,12 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// pretty-expanded FIXME #23616
+
+#![feature(rustc_attrs)]
+#![feature(test)]
+
+mod m {
+ #[rustc_dummy = "bar"]
+ extern crate test;
+}
+
+fn main() {}
diff --git a/src/test/ui/attributes/attr-eq-token-tree.rs b/src/test/ui/attributes/attr-eq-token-tree.rs
new file mode 100644
index 000000000..330b11977
--- /dev/null
+++ b/src/test/ui/attributes/attr-eq-token-tree.rs
@@ -0,0 +1,2 @@
+#[my_attr = !] //~ ERROR expected expression, found `]`
+fn main() {}
diff --git a/src/test/ui/attributes/attr-eq-token-tree.stderr b/src/test/ui/attributes/attr-eq-token-tree.stderr
new file mode 100644
index 000000000..1846444b6
--- /dev/null
+++ b/src/test/ui/attributes/attr-eq-token-tree.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found `]`
+ --> $DIR/attr-eq-token-tree.rs:1:14
+ |
+LL | #[my_attr = !]
+ | ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/attr-mix-new.rs b/src/test/ui/attributes/attr-mix-new.rs
new file mode 100644
index 000000000..8119df0c4
--- /dev/null
+++ b/src/test/ui/attributes/attr-mix-new.rs
@@ -0,0 +1,11 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// pretty-expanded FIXME #23616
+
+#![feature(rustc_attrs)]
+
+#[rustc_dummy(bar)]
+mod foo {
+ #![feature(globs)]
+}
+
+fn main() {}
diff --git a/src/test/ui/attributes/attrs-on-params.rs b/src/test/ui/attributes/attrs-on-params.rs
new file mode 100644
index 000000000..158a4500b
--- /dev/null
+++ b/src/test/ui/attributes/attrs-on-params.rs
@@ -0,0 +1,8 @@
+// This checks that incorrect params on function parameters are caught
+
+fn function(#[inline] param: u32) {
+ //~^ ERROR attribute should be applied to function or closure
+ //~| ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes
+}
+
+fn main() {}
diff --git a/src/test/ui/attributes/attrs-on-params.stderr b/src/test/ui/attributes/attrs-on-params.stderr
new file mode 100644
index 000000000..306e862cb
--- /dev/null
+++ b/src/test/ui/attributes/attrs-on-params.stderr
@@ -0,0 +1,17 @@
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/attrs-on-params.rs:3:13
+ |
+LL | fn function(#[inline] param: u32) {
+ | ^^^^^^^^^
+
+error[E0518]: attribute should be applied to function or closure
+ --> $DIR/attrs-on-params.rs:3:13
+ |
+LL | fn function(#[inline] param: u32) {
+ | ^^^^^^^^^-----------
+ | |
+ | not a function or closure
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0518`.
diff --git a/src/test/ui/attributes/attrs-with-no-formal-in-generics-1.rs b/src/test/ui/attributes/attrs-with-no-formal-in-generics-1.rs
new file mode 100644
index 000000000..df9c8d894
--- /dev/null
+++ b/src/test/ui/attributes/attrs-with-no-formal-in-generics-1.rs
@@ -0,0 +1,13 @@
+// This test checks variations on `<#[attr] 'a, #[oops]>`, where
+// `#[oops]` is left dangling (that is, it is unattached, with no
+// formal binding following it).
+
+#![feature(rustc_attrs)]
+
+struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
+
+impl<#[rustc_dummy] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
+ //~^ ERROR trailing attribute after generic parameter
+}
+
+fn main() {}
diff --git a/src/test/ui/attributes/attrs-with-no-formal-in-generics-1.stderr b/src/test/ui/attributes/attrs-with-no-formal-in-generics-1.stderr
new file mode 100644
index 000000000..5b4f5222a
--- /dev/null
+++ b/src/test/ui/attributes/attrs-with-no-formal-in-generics-1.stderr
@@ -0,0 +1,8 @@
+error: trailing attribute after generic parameter
+ --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:29
+ |
+LL | impl<#[rustc_dummy] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
+ | ^^^^^^^ attributes must go before parameters
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/attrs-with-no-formal-in-generics-2.rs b/src/test/ui/attributes/attrs-with-no-formal-in-generics-2.rs
new file mode 100644
index 000000000..d1d044035
--- /dev/null
+++ b/src/test/ui/attributes/attrs-with-no-formal-in-generics-2.rs
@@ -0,0 +1,12 @@
+// This test checks variations on `<#[attr] 'a, #[oops]>`, where
+// `#[oops]` is left dangling (that is, it is unattached, with no
+// formal binding following it).
+
+#![feature(rustc_attrs)]
+
+struct RefAny<'a, T>(&'a T);
+
+impl<#[rustc_dummy] 'a, #[rustc_dummy] T, #[oops]> RefAny<'a, T> {}
+//~^ ERROR trailing attribute after generic parameter
+
+fn main() {}
diff --git a/src/test/ui/attributes/attrs-with-no-formal-in-generics-2.stderr b/src/test/ui/attributes/attrs-with-no-formal-in-generics-2.stderr
new file mode 100644
index 000000000..fce3ff7de
--- /dev/null
+++ b/src/test/ui/attributes/attrs-with-no-formal-in-generics-2.stderr
@@ -0,0 +1,8 @@
+error: trailing attribute after generic parameter
+ --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:43
+ |
+LL | impl<#[rustc_dummy] 'a, #[rustc_dummy] T, #[oops]> RefAny<'a, T> {}
+ | ^^^^^^^ attributes must go before parameters
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/attrs-with-no-formal-in-generics-3.rs b/src/test/ui/attributes/attrs-with-no-formal-in-generics-3.rs
new file mode 100644
index 000000000..3cfc70b41
--- /dev/null
+++ b/src/test/ui/attributes/attrs-with-no-formal-in-generics-3.rs
@@ -0,0 +1,12 @@
+// This test checks variations on `<#[attr] 'a, #[oops]>`, where
+// `#[oops]` is left dangling (that is, it is unattached, with no
+// formal binding following it).
+
+struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
+
+fn hof_lt<Q>(_: Q)
+ where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
+ //~^ ERROR trailing attribute after generic parameter
+{}
+
+fn main() {}
diff --git a/src/test/ui/attributes/attrs-with-no-formal-in-generics-3.stderr b/src/test/ui/attributes/attrs-with-no-formal-in-generics-3.stderr
new file mode 100644
index 000000000..b9ca00974
--- /dev/null
+++ b/src/test/ui/attributes/attrs-with-no-formal-in-generics-3.stderr
@@ -0,0 +1,8 @@
+error: trailing attribute after generic parameter
+ --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44
+ |
+LL | where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
+ | ^^^^^^^ attributes must go before parameters
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/auxiliary/key-value-expansion.rs b/src/test/ui/attributes/auxiliary/key-value-expansion.rs
new file mode 100644
index 000000000..b4eb80bb5
--- /dev/null
+++ b/src/test/ui/attributes/auxiliary/key-value-expansion.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive(EthabiContract, attributes(ethabi_contract_options))]
+pub fn ethabi_derive(input: TokenStream) -> TokenStream {
+ Default::default()
+}
diff --git a/src/test/ui/attributes/class-attributes-1.rs b/src/test/ui/attributes/class-attributes-1.rs
new file mode 100644
index 000000000..027b701e5
--- /dev/null
+++ b/src/test/ui/attributes/class-attributes-1.rs
@@ -0,0 +1,19 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// pp-exact - Make sure we actually print the attributes
+
+#![feature(rustc_attrs)]
+
+struct Cat {
+ name: String,
+}
+
+impl Drop for Cat {
+ #[rustc_dummy]
+ fn drop(&mut self) { println!("{} landed on hir feet" , self . name); }
+}
+
+
+#[rustc_dummy]
+fn cat(name: String) -> Cat { Cat{name: name,} }
+
+fn main() { let _kitty = cat("Spotty".to_string()); }
diff --git a/src/test/ui/attributes/class-attributes-2.rs b/src/test/ui/attributes/class-attributes-2.rs
new file mode 100644
index 000000000..6aba6b894
--- /dev/null
+++ b/src/test/ui/attributes/class-attributes-2.rs
@@ -0,0 +1,31 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+
+struct Cat {
+ name: String,
+}
+
+impl Drop for Cat {
+ #[rustc_dummy]
+ /**
+ Actually, cats don't always land on their feet when you drop them.
+ */
+ fn drop(&mut self) {
+ println!("{} landed on hir feet", self.name);
+ }
+}
+
+#[rustc_dummy]
+/**
+Maybe it should technically be a kitten_maker.
+*/
+fn cat(name: String) -> Cat {
+ Cat {
+ name: name
+ }
+}
+
+fn main() {
+ let _kitty = cat("Spotty".to_string());
+}
diff --git a/src/test/ui/attributes/const-stability-on-macro.rs b/src/test/ui/attributes/const-stability-on-macro.rs
new file mode 100644
index 000000000..412af195d
--- /dev/null
+++ b/src/test/ui/attributes/const-stability-on-macro.rs
@@ -0,0 +1,16 @@
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[rustc_const_stable(feature = "foo", since = "0")]
+//~^ ERROR macros cannot have const stability attributes
+macro_rules! foo {
+ () => {};
+}
+
+#[rustc_const_unstable(feature = "bar", issue="none")]
+//~^ ERROR macros cannot have const stability attributes
+macro_rules! bar {
+ () => {};
+}
+
+fn main() {}
diff --git a/src/test/ui/attributes/const-stability-on-macro.stderr b/src/test/ui/attributes/const-stability-on-macro.stderr
new file mode 100644
index 000000000..c3da02c79
--- /dev/null
+++ b/src/test/ui/attributes/const-stability-on-macro.stderr
@@ -0,0 +1,20 @@
+error: macros cannot have const stability attributes
+ --> $DIR/const-stability-on-macro.rs:4:1
+ |
+LL | #[rustc_const_stable(feature = "foo", since = "0")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute
+LL |
+LL | macro_rules! foo {
+ | ---------------- const stability attribute affects this macro
+
+error: macros cannot have const stability attributes
+ --> $DIR/const-stability-on-macro.rs:10:1
+ |
+LL | #[rustc_const_unstable(feature = "bar", issue="none")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute
+LL |
+LL | macro_rules! bar {
+ | ---------------- const stability attribute affects this macro
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/attributes/doc-attr.rs b/src/test/ui/attributes/doc-attr.rs
new file mode 100644
index 000000000..980d1c0e2
--- /dev/null
+++ b/src/test/ui/attributes/doc-attr.rs
@@ -0,0 +1,25 @@
+#![crate_type = "lib"]
+#![deny(warnings)]
+#![doc(as_ptr)]
+//~^ ERROR unknown `doc` attribute
+//~^^ WARN
+
+#[doc(as_ptr)]
+//~^ ERROR unknown `doc` attribute
+//~^^ WARN
+pub fn foo() {}
+
+#[doc(123)]
+//~^ ERROR invalid `doc` attribute
+//~| WARN
+#[doc("hello", "bar")]
+//~^ ERROR invalid `doc` attribute
+//~| WARN
+//~| ERROR invalid `doc` attribute
+//~| WARN
+#[doc(foo::bar, crate::bar::baz = "bye")]
+//~^ ERROR unknown `doc` attribute
+//~| WARN
+//~| ERROR unknown `doc` attribute
+//~| WARN
+fn bar() {}
diff --git a/src/test/ui/attributes/doc-attr.stderr b/src/test/ui/attributes/doc-attr.stderr
new file mode 100644
index 000000000..cc2494c92
--- /dev/null
+++ b/src/test/ui/attributes/doc-attr.stderr
@@ -0,0 +1,71 @@
+error: unknown `doc` attribute `as_ptr`
+ --> $DIR/doc-attr.rs:7:7
+ |
+LL | #[doc(as_ptr)]
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/doc-attr.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: invalid `doc` attribute
+ --> $DIR/doc-attr.rs:12:7
+ |
+LL | #[doc(123)]
+ | ^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: invalid `doc` attribute
+ --> $DIR/doc-attr.rs:15:7
+ |
+LL | #[doc("hello", "bar")]
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: invalid `doc` attribute
+ --> $DIR/doc-attr.rs:15:16
+ |
+LL | #[doc("hello", "bar")]
+ | ^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `foo::bar`
+ --> $DIR/doc-attr.rs:20:7
+ |
+LL | #[doc(foo::bar, crate::bar::baz = "bye")]
+ | ^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `crate::bar::baz`
+ --> $DIR/doc-attr.rs:20:17
+ |
+LL | #[doc(foo::bar, crate::bar::baz = "bye")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `as_ptr`
+ --> $DIR/doc-attr.rs:3:8
+ |
+LL | #![doc(as_ptr)]
+ | ^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/attributes/duplicated-attributes.rs b/src/test/ui/attributes/duplicated-attributes.rs
new file mode 100644
index 000000000..84a5abcf8
--- /dev/null
+++ b/src/test/ui/attributes/duplicated-attributes.rs
@@ -0,0 +1,41 @@
+// Test that, if an item is annotated with a builtin attribute more than once, a warning is
+// emitted.
+// Tests https://github.com/rust-lang/rust/issues/90979
+
+// check-pass
+// compile-flags: --test
+
+#![feature(test)]
+#![feature(cfg_eval)]
+
+#[test]
+#[test]
+//~^ WARNING duplicated attribute
+fn f() {}
+
+// The following shouldn't trigger an error. The attribute is not duplicated.
+#[test]
+fn f2() {}
+
+// The following shouldn't trigger an error either. The second attribute is not #[test].
+#[test]
+#[inline]
+fn f3() {}
+
+extern crate test;
+use test::Bencher;
+
+#[bench]
+#[bench]
+//~^ WARNING duplicated attribute
+fn f4(_: &mut Bencher) {}
+
+#[cfg_eval]
+#[cfg_eval]
+//~^ WARNING duplicated attribute
+struct S;
+
+#[cfg_eval]
+struct S2;
+
+fn main() {}
diff --git a/src/test/ui/attributes/duplicated-attributes.stderr b/src/test/ui/attributes/duplicated-attributes.stderr
new file mode 100644
index 000000000..735d950b2
--- /dev/null
+++ b/src/test/ui/attributes/duplicated-attributes.stderr
@@ -0,0 +1,22 @@
+warning: duplicated attribute
+ --> $DIR/duplicated-attributes.rs:12:1
+ |
+LL | #[test]
+ | ^^^^^^^
+ |
+ = note: `#[warn(duplicate_macro_attributes)]` on by default
+
+warning: duplicated attribute
+ --> $DIR/duplicated-attributes.rs:29:1
+ |
+LL | #[bench]
+ | ^^^^^^^^
+
+warning: duplicated attribute
+ --> $DIR/duplicated-attributes.rs:34:1
+ |
+LL | #[cfg_eval]
+ | ^^^^^^^^^^^
+
+warning: 3 warnings emitted
+
diff --git a/src/test/ui/attributes/extented-attribute-macro-error.rs b/src/test/ui/attributes/extented-attribute-macro-error.rs
new file mode 100644
index 000000000..492f84f56
--- /dev/null
+++ b/src/test/ui/attributes/extented-attribute-macro-error.rs
@@ -0,0 +1,7 @@
+// normalize-stderr-test: "couldn't read.*" -> "couldn't read the file"
+
+#![doc = include_str!("../not_existing_file.md")]
+struct Documented {}
+//~^^ ERROR couldn't read
+
+fn main() {}
diff --git a/src/test/ui/attributes/extented-attribute-macro-error.stderr b/src/test/ui/attributes/extented-attribute-macro-error.stderr
new file mode 100644
index 000000000..0fcde9b7c
--- /dev/null
+++ b/src/test/ui/attributes/extented-attribute-macro-error.stderr
@@ -0,0 +1,10 @@
+error: couldn't read the file
+ --> $DIR/extented-attribute-macro-error.rs:3:10
+ |
+LL | #![doc = include_str!("../not_existing_file.md")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/field-attributes-vis-unresolved.rs b/src/test/ui/attributes/field-attributes-vis-unresolved.rs
new file mode 100644
index 000000000..d1bd2a1e7
--- /dev/null
+++ b/src/test/ui/attributes/field-attributes-vis-unresolved.rs
@@ -0,0 +1,25 @@
+// Non-builtin attributes do not mess with field visibility resolution (issue #67006).
+
+mod internal {
+ struct S {
+ #[rustfmt::skip]
+ pub(in crate::internal) field: u8 // OK
+ }
+
+ struct Z(
+ #[rustfmt::skip]
+ pub(in crate::internal) u8 // OK
+ );
+}
+
+struct S {
+ #[rustfmt::skip]
+ pub(in nonexistent) field: u8 //~ ERROR failed to resolve
+}
+
+struct Z(
+ #[rustfmt::skip]
+ pub(in nonexistent) u8 //~ ERROR failed to resolve
+);
+
+fn main() {}
diff --git a/src/test/ui/attributes/field-attributes-vis-unresolved.stderr b/src/test/ui/attributes/field-attributes-vis-unresolved.stderr
new file mode 100644
index 000000000..439762546
--- /dev/null
+++ b/src/test/ui/attributes/field-attributes-vis-unresolved.stderr
@@ -0,0 +1,19 @@
+error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
+ --> $DIR/field-attributes-vis-unresolved.rs:17:12
+ |
+LL | pub(in nonexistent) field: u8
+ | ^^^^^^^^^^^ maybe a missing crate `nonexistent`?
+ |
+ = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate
+
+error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
+ --> $DIR/field-attributes-vis-unresolved.rs:22:12
+ |
+LL | pub(in nonexistent) u8
+ | ^^^^^^^^^^^ maybe a missing crate `nonexistent`?
+ |
+ = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/attributes/invalid-doc-attr.rs b/src/test/ui/attributes/invalid-doc-attr.rs
new file mode 100644
index 000000000..de004b41e
--- /dev/null
+++ b/src/test/ui/attributes/invalid-doc-attr.rs
@@ -0,0 +1,32 @@
+#![crate_type = "lib"]
+#![deny(warnings)]
+
+#[doc(test(no_crate_inject))]
+//~^ ERROR can only be applied at the crate level
+//~| WARN is being phased out
+//~| HELP to apply to the crate, use an inner attribute
+//~| SUGGESTION #![doc(test(no_crate_inject))]
+#[doc(inline)]
+//~^ ERROR can only be applied to a `use` item
+//~| WARN is being phased out
+pub fn foo() {}
+
+pub mod bar {
+ #![doc(test(no_crate_inject))]
+ //~^ ERROR can only be applied at the crate level
+ //~| WARN is being phased out
+
+ #[doc(test(no_crate_inject))]
+ //~^ ERROR can only be applied at the crate level
+ //~| WARN is being phased out
+ #[doc(inline)]
+ //~^ ERROR can only be applied to a `use` item
+ //~| WARN is being phased out
+ pub fn baz() {}
+}
+
+#[doc(inline)]
+#[doc(no_inline)]
+//~^^ ERROR conflicting doc inlining attributes
+//~| HELP remove one of the conflicting attributes
+pub use bar::baz;
diff --git a/src/test/ui/attributes/invalid-doc-attr.stderr b/src/test/ui/attributes/invalid-doc-attr.stderr
new file mode 100644
index 000000000..a4fa38179
--- /dev/null
+++ b/src/test/ui/attributes/invalid-doc-attr.stderr
@@ -0,0 +1,78 @@
+error: this attribute can only be applied at the crate level
+ --> $DIR/invalid-doc-attr.rs:4:7
+ |
+LL | #[doc(test(no_crate_inject))]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/invalid-doc-attr.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+help: to apply to the crate, use an inner attribute
+ |
+LL | #![doc(test(no_crate_inject))]
+ |
+
+error: this attribute can only be applied to a `use` item
+ --> $DIR/invalid-doc-attr.rs:9:7
+ |
+LL | #[doc(inline)]
+ | ^^^^^^ only applicable on `use` items
+...
+LL | pub fn foo() {}
+ | ------------ not a `use` item
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
+
+error: this attribute can only be applied at the crate level
+ --> $DIR/invalid-doc-attr.rs:15:12
+ |
+LL | #![doc(test(no_crate_inject))]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+
+error: conflicting doc inlining attributes
+ --> $DIR/invalid-doc-attr.rs:28:7
+ |
+LL | #[doc(inline)]
+ | ^^^^^^ this attribute...
+LL | #[doc(no_inline)]
+ | ^^^^^^^^^ ...conflicts with this attribute
+ |
+ = help: remove one of the conflicting attributes
+
+error: this attribute can only be applied at the crate level
+ --> $DIR/invalid-doc-attr.rs:19:11
+ |
+LL | #[doc(test(no_crate_inject))]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+
+error: this attribute can only be applied to a `use` item
+ --> $DIR/invalid-doc-attr.rs:22:11
+ |
+LL | #[doc(inline)]
+ | ^^^^^^ only applicable on `use` items
+...
+LL | pub fn baz() {}
+ | ------------ not a `use` item
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/attributes/issue-40962.rs b/src/test/ui/attributes/issue-40962.rs
new file mode 100644
index 000000000..7b91c0681
--- /dev/null
+++ b/src/test/ui/attributes/issue-40962.rs
@@ -0,0 +1,11 @@
+// check-pass
+macro_rules! m {
+ ($i:meta) => {
+ #[derive($i)]
+ struct S;
+ }
+}
+
+m!(Clone);
+
+fn main() {}
diff --git a/src/test/ui/attributes/issue-90873.rs b/src/test/ui/attributes/issue-90873.rs
new file mode 100644
index 000000000..1411f6174
--- /dev/null
+++ b/src/test/ui/attributes/issue-90873.rs
@@ -0,0 +1,9 @@
+#![u=||{static d=||1;}]
+//~^ unexpected expression
+//~| cannot find attribute `u` in this scope
+//~| missing type for `static` item
+
+#![a={impl std::ops::Neg for i8 {}}]
+//~^ ERROR unexpected expression
+//~| ERROR cannot find attribute `a` in this scope
+//~| ERROR `main` function not found in crate `issue_90873`
diff --git a/src/test/ui/attributes/issue-90873.stderr b/src/test/ui/attributes/issue-90873.stderr
new file mode 100644
index 000000000..0852bb7ca
--- /dev/null
+++ b/src/test/ui/attributes/issue-90873.stderr
@@ -0,0 +1,44 @@
+error: unexpected expression: `||
+ {
+ static d: _ = || 1;
+ }`
+ --> $DIR/issue-90873.rs:1:6
+ |
+LL | #![u=||{static d=||1;}]
+ | ^^^^^^^^^^^^^^^^^
+
+error: unexpected expression: `{
+ impl std::ops::Neg for i8 {}
+ }`
+ --> $DIR/issue-90873.rs:6:6
+ |
+LL | #![a={impl std::ops::Neg for i8 {}}]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find attribute `u` in this scope
+ --> $DIR/issue-90873.rs:1:4
+ |
+LL | #![u=||{static d=||1;}]
+ | ^
+
+error: cannot find attribute `a` in this scope
+ --> $DIR/issue-90873.rs:6:4
+ |
+LL | #![a={impl std::ops::Neg for i8 {}}]
+ | ^
+
+error[E0601]: `main` function not found in crate `issue_90873`
+ --> $DIR/issue-90873.rs:6:37
+ |
+LL | #![a={impl std::ops::Neg for i8 {}}]
+ | ^ consider adding a `main` function to `$DIR/issue-90873.rs`
+
+error: missing type for `static` item
+ --> $DIR/issue-90873.rs:1:16
+ |
+LL | #![u=||{static d=||1;}]
+ | ^ help: provide a type for the item: `d: <type>`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/attributes/item-attributes.rs b/src/test/ui/attributes/item-attributes.rs
new file mode 100644
index 000000000..c6bf6c656
--- /dev/null
+++ b/src/test/ui/attributes/item-attributes.rs
@@ -0,0 +1,174 @@
+// These are attributes of the implicit crate. Really this just needs to parse
+// for completeness since .rs files linked from .rc files support this
+// notation to specify their module's attributes
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![rustc_dummy = "val"]
+#![rustc_dummy = "val"]
+#![rustc_dummy]
+#![rustc_dummy(attr5)]
+
+// These are attributes of the following mod
+#[rustc_dummy = "val"]
+#[rustc_dummy = "val"]
+mod test_first_item_in_file_mod {}
+
+mod test_single_attr_outer {
+ #[rustc_dummy = "val"]
+ pub static X: isize = 10;
+
+ #[rustc_dummy = "val"]
+ pub fn f() {}
+
+ #[rustc_dummy = "val"]
+ pub mod mod1 {}
+
+ pub mod rustrt {
+ #[rustc_dummy = "val"]
+ extern "C" {}
+ }
+}
+
+mod test_multi_attr_outer {
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ pub static X: isize = 10;
+
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ pub fn f() {}
+
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ pub mod mod1 {}
+
+ pub mod rustrt {
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ extern "C" {}
+ }
+
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ struct T {
+ x: isize,
+ }
+}
+
+mod test_stmt_single_attr_outer {
+ pub fn f() {
+ #[rustc_dummy = "val"]
+ static X: isize = 10;
+
+ #[rustc_dummy = "val"]
+ fn f() {}
+
+ #[rustc_dummy = "val"]
+ mod mod1 {}
+
+ mod rustrt {
+ #[rustc_dummy = "val"]
+ extern "C" {}
+ }
+ }
+}
+
+mod test_stmt_multi_attr_outer {
+ pub fn f() {
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ static X: isize = 10;
+
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ fn f() {}
+
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ mod mod1 {}
+
+ mod rustrt {
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ extern "C" {}
+ }
+ }
+}
+
+mod test_attr_inner {
+ pub mod m {
+ // This is an attribute of mod m
+ #![rustc_dummy = "val"]
+ }
+}
+
+mod test_attr_inner_then_outer {
+ pub mod m {
+ // This is an attribute of mod m
+ #![rustc_dummy = "val"]
+ // This is an attribute of fn f
+ #[rustc_dummy = "val"]
+ fn f() {}
+ }
+}
+
+mod test_attr_inner_then_outer_multi {
+ pub mod m {
+ // This is an attribute of mod m
+ #![rustc_dummy = "val"]
+ #![rustc_dummy = "val"]
+ // This is an attribute of fn f
+ #[rustc_dummy = "val"]
+ #[rustc_dummy = "val"]
+ fn f() {}
+ }
+}
+
+mod test_distinguish_syntax_ext {
+ pub fn f() {
+ format!("test{}", "s");
+ #[rustc_dummy = "val"]
+ fn g() {}
+ }
+}
+
+mod test_other_forms {
+ #[rustc_dummy]
+ #[rustc_dummy(word)]
+ #[rustc_dummy(attr(word))]
+ #[rustc_dummy(key1 = "val", key2 = "val", attr)]
+ pub fn f() {}
+}
+
+mod test_foreign_items {
+ pub mod rustrt {
+ extern "C" {
+ #![rustc_dummy]
+
+ #[rustc_dummy]
+ fn rust_get_test_int() -> u32;
+ }
+ }
+}
+
+// FIXME(#623): - these aren't supported yet
+/*mod test_literals {
+ #![str = "s"]
+ #![char = 'c']
+ #![isize = 100]
+ #![usize = 100_usize]
+ #![mach_int = 100u32]
+ #![float = 1.0]
+ #![mach_float = 1.0f32]
+ #![nil = ()]
+ #![bool = true]
+ mod m {}
+}*/
+
+fn test_fn_inner() {
+ #![rustc_dummy]
+}
+
+fn main() {}
diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.rs b/src/test/ui/attributes/key-value-expansion-on-mac.rs
new file mode 100644
index 000000000..c1d68d8cd
--- /dev/null
+++ b/src/test/ui/attributes/key-value-expansion-on-mac.rs
@@ -0,0 +1,14 @@
+#![feature(rustc_attrs)]
+
+#[rustc_dummy = stringify!(a)] // OK
+macro_rules! bar {
+ () => {};
+}
+
+// FIXME?: `bar` here expands before `stringify` has a chance to expand.
+// `#[rustc_dummy = ...]` is validated and dropped during expansion of `bar`,
+// the "unexpected expression" errors comes from the validation.
+#[rustc_dummy = stringify!(b)] //~ ERROR unexpected expression: `stringify!(b)`
+bar!();
+
+fn main() {}
diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.stderr b/src/test/ui/attributes/key-value-expansion-on-mac.stderr
new file mode 100644
index 000000000..64ab892d9
--- /dev/null
+++ b/src/test/ui/attributes/key-value-expansion-on-mac.stderr
@@ -0,0 +1,8 @@
+error: unexpected expression: `stringify!(b)`
+ --> $DIR/key-value-expansion-on-mac.rs:11:17
+ |
+LL | #[rustc_dummy = stringify!(b)]
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/key-value-expansion.rs b/src/test/ui/attributes/key-value-expansion.rs
new file mode 100644
index 000000000..83d601e5e
--- /dev/null
+++ b/src/test/ui/attributes/key-value-expansion.rs
@@ -0,0 +1,55 @@
+// Regression tests for issue #55414, expansion happens in the value of a key-value attribute,
+// and the expanded expression is more complex than simply a macro call.
+
+// aux-build:key-value-expansion.rs
+
+#![feature(rustc_attrs)]
+
+extern crate key_value_expansion;
+
+// Minimized test case.
+
+macro_rules! bug {
+ ($expr:expr) => {
+ #[rustc_dummy = $expr] // Any key-value attribute, not necessarily `doc`
+ struct S;
+ };
+}
+
+// Any expressions containing macro call `X` that's more complex than `X` itself.
+// Parentheses will work.
+bug!((column!())); //~ ERROR unexpected expression: `(7u32)`
+
+// Original test case.
+
+macro_rules! bug {
+ () => {
+ bug!("bug" + stringify!(found)); //~ ERROR unexpected expression: `"bug" + "found"`
+ };
+ ($test:expr) => {
+ #[doc = $test]
+ struct Test {}
+ };
+}
+
+bug!();
+
+// Test case from #66804.
+
+macro_rules! doc_comment {
+ ($x:expr) => {
+ #[doc = $x]
+ extern {}
+ };
+}
+
+macro_rules! some_macro {
+ ($t1: ty) => {
+ doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}
+ //~^ ERROR unexpected expression: `{
+ };
+}
+
+some_macro!(u8);
+
+fn main() {}
diff --git a/src/test/ui/attributes/key-value-expansion.stderr b/src/test/ui/attributes/key-value-expansion.stderr
new file mode 100644
index 000000000..1b776322a
--- /dev/null
+++ b/src/test/ui/attributes/key-value-expansion.stderr
@@ -0,0 +1,35 @@
+error: unexpected expression: `(7u32)`
+ --> $DIR/key-value-expansion.rs:21:6
+ |
+LL | bug!((column!()));
+ | ^^^^^^^^^^^
+
+error: unexpected expression: `"bug" + "found"`
+ --> $DIR/key-value-expansion.rs:27:14
+ |
+LL | bug!("bug" + stringify!(found));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | bug!();
+ | ------ in this macro invocation
+ |
+ = note: this error originates in the macro `bug` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unexpected expression: `{
+ let res =
+ ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""],
+ &[::core::fmt::ArgumentV1::new_display(&"u8")]));
+ res
+ }.as_str()`
+ --> $DIR/key-value-expansion.rs:48:23
+ |
+LL | doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | some_macro!(u8);
+ | --------------- in this macro invocation
+ |
+ = note: this error originates in the macro `some_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/attributes/key-value-non-ascii.rs b/src/test/ui/attributes/key-value-non-ascii.rs
new file mode 100644
index 000000000..12942eabd
--- /dev/null
+++ b/src/test/ui/attributes/key-value-non-ascii.rs
@@ -0,0 +1,4 @@
+#![feature(rustc_attrs)]
+
+#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte constant
+fn main() {}
diff --git a/src/test/ui/attributes/key-value-non-ascii.stderr b/src/test/ui/attributes/key-value-non-ascii.stderr
new file mode 100644
index 000000000..422107867
--- /dev/null
+++ b/src/test/ui/attributes/key-value-non-ascii.stderr
@@ -0,0 +1,13 @@
+error: non-ASCII character in byte constant
+ --> $DIR/key-value-non-ascii.rs:3:19
+ |
+LL | #[rustc_dummy = b"ffi.rs"]
+ | ^ byte constant must be ASCII
+ |
+help: if you meant to use the UTF-8 encoding of 'ffi', use \xHH escapes
+ |
+LL | #[rustc_dummy = b"/xEF/xAC/x83.rs"]
+ | ~~~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/main-removed-1.rs b/src/test/ui/attributes/main-removed-1.rs
new file mode 100644
index 000000000..0e887469d
--- /dev/null
+++ b/src/test/ui/attributes/main-removed-1.rs
@@ -0,0 +1,2 @@
+#[main] //~ ERROR cannot find attribute `main` in this scope
+fn main() {}
diff --git a/src/test/ui/attributes/main-removed-1.stderr b/src/test/ui/attributes/main-removed-1.stderr
new file mode 100644
index 000000000..2422c5c3b
--- /dev/null
+++ b/src/test/ui/attributes/main-removed-1.stderr
@@ -0,0 +1,10 @@
+error: cannot find attribute `main` in this scope
+ --> $DIR/main-removed-1.rs:1:3
+ |
+LL | #[main]
+ | ^^^^
+ |
+ = note: `main` is in scope, but it is a function, not an attribute
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs b/src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs
new file mode 100644
index 000000000..196b5be2d
--- /dev/null
+++ b/src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn main(_: TokenStream, input: TokenStream) -> TokenStream {
+ "fn main() { println!(\"Hello Tokyo!\"); }".parse().unwrap()
+}
diff --git a/src/test/ui/attributes/main-removed-2/main.rs b/src/test/ui/attributes/main-removed-2/main.rs
new file mode 100644
index 000000000..e8fecf825
--- /dev/null
+++ b/src/test/ui/attributes/main-removed-2/main.rs
@@ -0,0 +1,11 @@
+// run-pass
+// aux-build:tokyo.rs
+// compile-flags:--extern tokyo
+// edition:2021
+
+use tokyo::main;
+
+#[main]
+fn main() {
+ panic!("the #[main] macro should replace this with non-panicking code")
+}
diff --git a/src/test/ui/attributes/method-attributes.rs b/src/test/ui/attributes/method-attributes.rs
new file mode 100644
index 000000000..67439718b
--- /dev/null
+++ b/src/test/ui/attributes/method-attributes.rs
@@ -0,0 +1,28 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// pp-exact - Make sure we print all the attributes
+// pretty-expanded FIXME #23616
+
+#![feature(rustc_attrs)]
+
+#[rustc_dummy]
+trait Frobable {
+ #[rustc_dummy]
+ fn frob(&self);
+ #[rustc_dummy]
+ fn defrob(&self);
+}
+
+#[rustc_dummy]
+impl Frobable for isize {
+ #[rustc_dummy]
+ fn frob(&self) {
+ #![rustc_dummy]
+ }
+
+ #[rustc_dummy]
+ fn defrob(&self) {
+ #![rustc_dummy]
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/attributes/multiple-invalid.rs b/src/test/ui/attributes/multiple-invalid.rs
new file mode 100644
index 000000000..ae044eb84
--- /dev/null
+++ b/src/test/ui/attributes/multiple-invalid.rs
@@ -0,0 +1,10 @@
+// This test checks that all expected errors occur when there are multiple invalid attributes
+// on an item.
+
+#[inline]
+//~^ ERROR attribute should be applied to function or closure [E0518]
+#[target_feature(enable = "sse2")]
+//~^ ERROR attribute should be applied to a function
+const FOO: u8 = 0;
+
+fn main() { }
diff --git a/src/test/ui/attributes/multiple-invalid.stderr b/src/test/ui/attributes/multiple-invalid.stderr
new file mode 100644
index 000000000..a8dba0ba3
--- /dev/null
+++ b/src/test/ui/attributes/multiple-invalid.stderr
@@ -0,0 +1,21 @@
+error[E0518]: attribute should be applied to function or closure
+ --> $DIR/multiple-invalid.rs:4:1
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+...
+LL | const FOO: u8 = 0;
+ | ------------------ not a function or closure
+
+error: attribute should be applied to a function definition
+ --> $DIR/multiple-invalid.rs:6:1
+ |
+LL | #[target_feature(enable = "sse2")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | const FOO: u8 = 0;
+ | ------------------ not a function definition
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0518`.
diff --git a/src/test/ui/attributes/nonterminal-expansion.rs b/src/test/ui/attributes/nonterminal-expansion.rs
new file mode 100644
index 000000000..97bf225f0
--- /dev/null
+++ b/src/test/ui/attributes/nonterminal-expansion.rs
@@ -0,0 +1,18 @@
+// Macros were previously expanded in `Expr` nonterminal tokens, now they are not.
+
+macro_rules! pass_nonterminal {
+ ($n:expr) => {
+ #[repr(align($n))]
+ //~^ ERROR expected unsuffixed literal or identifier, found `n!()`
+ //~| ERROR incorrect `repr(align)` attribute format
+ struct S;
+ };
+}
+
+macro_rules! n {
+ () => { 32 };
+}
+
+pass_nonterminal!(n!());
+
+fn main() {}
diff --git a/src/test/ui/attributes/nonterminal-expansion.stderr b/src/test/ui/attributes/nonterminal-expansion.stderr
new file mode 100644
index 000000000..52376ac19
--- /dev/null
+++ b/src/test/ui/attributes/nonterminal-expansion.stderr
@@ -0,0 +1,25 @@
+error: expected unsuffixed literal or identifier, found `n!()`
+ --> $DIR/nonterminal-expansion.rs:5:22
+ |
+LL | #[repr(align($n))]
+ | ^^
+...
+LL | pass_nonterminal!(n!());
+ | ----------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+ --> $DIR/nonterminal-expansion.rs:5:16
+ |
+LL | #[repr(align($n))]
+ | ^^^^^^^^^
+...
+LL | pass_nonterminal!(n!());
+ | ----------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0693`.
diff --git a/src/test/ui/attributes/obsolete-attr.rs b/src/test/ui/attributes/obsolete-attr.rs
new file mode 100644
index 000000000..7019abcaf
--- /dev/null
+++ b/src/test/ui/attributes/obsolete-attr.rs
@@ -0,0 +1,9 @@
+// Obsolete attributes fall back to unstable custom attributes.
+
+#[ab_isize = "stdcall"] extern "C" {}
+//~^ ERROR cannot find attribute `ab_isize` in this scope
+
+#[fixed_stack_segment] fn f() {}
+//~^ ERROR cannot find attribute `fixed_stack_segment` in this scope
+
+fn main() {}
diff --git a/src/test/ui/attributes/obsolete-attr.stderr b/src/test/ui/attributes/obsolete-attr.stderr
new file mode 100644
index 000000000..37c1cd0c9
--- /dev/null
+++ b/src/test/ui/attributes/obsolete-attr.stderr
@@ -0,0 +1,14 @@
+error: cannot find attribute `fixed_stack_segment` in this scope
+ --> $DIR/obsolete-attr.rs:6:3
+ |
+LL | #[fixed_stack_segment] fn f() {}
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: cannot find attribute `ab_isize` in this scope
+ --> $DIR/obsolete-attr.rs:3:3
+ |
+LL | #[ab_isize = "stdcall"] extern "C" {}
+ | ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/attributes/register-attr-tool-fail.rs b/src/test/ui/attributes/register-attr-tool-fail.rs
new file mode 100644
index 000000000..84736be84
--- /dev/null
+++ b/src/test/ui/attributes/register-attr-tool-fail.rs
@@ -0,0 +1,13 @@
+#![feature(register_attr)]
+#![feature(register_tool)]
+
+#![register_attr] //~ ERROR malformed `register_attr` attribute input
+#![register_tool] //~ ERROR malformed `register_tool` attribute input
+
+#![register_attr(a::b)] //~ ERROR `register_attr` only accepts identifiers
+#![register_tool(a::b)] //~ ERROR `register_tool` only accepts identifiers
+
+#![register_attr(attr, attr)] //~ ERROR attribute `attr` was already registered
+#![register_tool(tool, tool)] //~ ERROR tool `tool` was already registered
+
+fn main() {}
diff --git a/src/test/ui/attributes/register-attr-tool-fail.stderr b/src/test/ui/attributes/register-attr-tool-fail.stderr
new file mode 100644
index 000000000..8f6977cb5
--- /dev/null
+++ b/src/test/ui/attributes/register-attr-tool-fail.stderr
@@ -0,0 +1,42 @@
+error: `register_attr` only accepts identifiers
+ --> $DIR/register-attr-tool-fail.rs:7:18
+ |
+LL | #![register_attr(a::b)]
+ | ^^^^ not an identifier
+
+error: attribute `attr` was already registered
+ --> $DIR/register-attr-tool-fail.rs:10:24
+ |
+LL | #![register_attr(attr, attr)]
+ | ---- ^^^^
+ | |
+ | already registered here
+
+error: `register_tool` only accepts identifiers
+ --> $DIR/register-attr-tool-fail.rs:8:18
+ |
+LL | #![register_tool(a::b)]
+ | ^^^^ not an identifier
+
+error: tool `tool` was already registered
+ --> $DIR/register-attr-tool-fail.rs:11:24
+ |
+LL | #![register_tool(tool, tool)]
+ | ---- ^^^^
+ | |
+ | already registered here
+
+error: malformed `register_attr` attribute input
+ --> $DIR/register-attr-tool-fail.rs:4:1
+ |
+LL | #![register_attr]
+ | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#![register_attr(attr1, attr2, ...)]`
+
+error: malformed `register_tool` attribute input
+ --> $DIR/register-attr-tool-fail.rs:5:1
+ |
+LL | #![register_tool]
+ | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#![register_tool(tool1, tool2, ...)]`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/attributes/register-attr-tool-import.rs b/src/test/ui/attributes/register-attr-tool-import.rs
new file mode 100644
index 000000000..d3502c71f
--- /dev/null
+++ b/src/test/ui/attributes/register-attr-tool-import.rs
@@ -0,0 +1,17 @@
+// edition:2018
+// compile-flags: -Zsave-analysis
+// ~^ Also regression test for #69588
+
+#![feature(register_attr)]
+#![feature(register_tool)]
+
+#![register_attr(attr)]
+#![register_tool(tool)]
+
+use attr as renamed_attr; // OK
+use tool as renamed_tool; // OK
+
+#[renamed_attr] //~ ERROR cannot use an explicitly registered attribute through an import
+#[renamed_tool::attr] //~ ERROR cannot use a tool module through an import
+ //~| ERROR cannot use a tool module through an import
+fn main() {}
diff --git a/src/test/ui/attributes/register-attr-tool-import.stderr b/src/test/ui/attributes/register-attr-tool-import.stderr
new file mode 100644
index 000000000..90b7e169a
--- /dev/null
+++ b/src/test/ui/attributes/register-attr-tool-import.stderr
@@ -0,0 +1,38 @@
+error: cannot use an explicitly registered attribute through an import
+ --> $DIR/register-attr-tool-import.rs:14:3
+ |
+LL | #[renamed_attr]
+ | ^^^^^^^^^^^^
+ |
+note: the explicitly registered attribute imported here
+ --> $DIR/register-attr-tool-import.rs:11:5
+ |
+LL | use attr as renamed_attr; // OK
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+ --> $DIR/register-attr-tool-import.rs:15:3
+ |
+LL | #[renamed_tool::attr]
+ | ^^^^^^^^^^^^
+ |
+note: the tool module imported here
+ --> $DIR/register-attr-tool-import.rs:12:5
+ |
+LL | use tool as renamed_tool; // OK
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+ --> $DIR/register-attr-tool-import.rs:15:3
+ |
+LL | #[renamed_tool::attr]
+ | ^^^^^^^^^^^^
+ |
+note: the tool module imported here
+ --> $DIR/register-attr-tool-import.rs:12:5
+ |
+LL | use tool as renamed_tool; // OK
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/attributes/register-attr-tool-prelude.rs b/src/test/ui/attributes/register-attr-tool-prelude.rs
new file mode 100644
index 000000000..d217a8146
--- /dev/null
+++ b/src/test/ui/attributes/register-attr-tool-prelude.rs
@@ -0,0 +1,14 @@
+#![feature(register_attr)]
+#![feature(register_tool)]
+
+#![register_attr(attr)]
+#![register_tool(tool)]
+
+#[no_implicit_prelude]
+mod m {
+ #[attr] //~ ERROR cannot find attribute `attr` in this scope
+ #[tool::attr] //~ ERROR failed to resolve: use of undeclared crate or module `tool`
+ fn check() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/attributes/register-attr-tool-prelude.stderr b/src/test/ui/attributes/register-attr-tool-prelude.stderr
new file mode 100644
index 000000000..905b66120
--- /dev/null
+++ b/src/test/ui/attributes/register-attr-tool-prelude.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `tool`
+ --> $DIR/register-attr-tool-prelude.rs:10:7
+ |
+LL | #[tool::attr]
+ | ^^^^ use of undeclared crate or module `tool`
+
+error: cannot find attribute `attr` in this scope
+ --> $DIR/register-attr-tool-prelude.rs:9:7
+ |
+LL | #[attr]
+ | ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/attributes/register-attr-tool-unused.rs b/src/test/ui/attributes/register-attr-tool-unused.rs
new file mode 100644
index 000000000..680614656
--- /dev/null
+++ b/src/test/ui/attributes/register-attr-tool-unused.rs
@@ -0,0 +1,8 @@
+#![deny(unused)]
+
+#![feature(register_attr)]
+#![feature(register_tool)]
+
+#[register_attr(attr)] //~ ERROR crate-level attribute should be an inner attribute
+#[register_tool(tool)] //~ ERROR crate-level attribute should be an inner attribute
+fn main() {}
diff --git a/src/test/ui/attributes/register-attr-tool-unused.stderr b/src/test/ui/attributes/register-attr-tool-unused.stderr
new file mode 100644
index 000000000..8d2e1b6bc
--- /dev/null
+++ b/src/test/ui/attributes/register-attr-tool-unused.stderr
@@ -0,0 +1,21 @@
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+ --> $DIR/register-attr-tool-unused.rs:6:1
+ |
+LL | #[register_attr(attr)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/register-attr-tool-unused.rs:1:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
+
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+ --> $DIR/register-attr-tool-unused.rs:7:1
+ |
+LL | #[register_tool(tool)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/attributes/register-attr-tool.rs b/src/test/ui/attributes/register-attr-tool.rs
new file mode 100644
index 000000000..ee9da74d4
--- /dev/null
+++ b/src/test/ui/attributes/register-attr-tool.rs
@@ -0,0 +1,19 @@
+// check-pass
+// compile-flags: --cfg foo
+
+#![feature(register_attr)]
+#![feature(register_tool)]
+
+#![register_attr(attr)]
+#![register_tool(tool)]
+#![register_tool(rustfmt, clippy)] // OK
+#![cfg_attr(foo, register_attr(conditional_attr))]
+#![cfg_attr(foo, register_tool(conditional_tool))]
+
+#[attr]
+#[tool::attr]
+#[rustfmt::attr]
+#[clippy::attr]
+#[conditional_attr]
+#[conditional_tool::attr]
+fn main() {}
diff --git a/src/test/ui/attributes/suffixed-literal-meta.rs b/src/test/ui/attributes/suffixed-literal-meta.rs
new file mode 100644
index 000000000..a6531490c
--- /dev/null
+++ b/src/test/ui/attributes/suffixed-literal-meta.rs
@@ -0,0 +1,15 @@
+#![feature(rustc_attrs)]
+
+#[rustc_dummy = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1u16] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1u32] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1u64] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1isize] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1i8] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1i16] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1i32] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1i64] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes
+#[rustc_dummy = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes
+fn main() {}
diff --git a/src/test/ui/attributes/suffixed-literal-meta.stderr b/src/test/ui/attributes/suffixed-literal-meta.stderr
new file mode 100644
index 000000000..5245ffead
--- /dev/null
+++ b/src/test/ui/attributes/suffixed-literal-meta.stderr
@@ -0,0 +1,98 @@
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:3:17
+ |
+LL | #[rustc_dummy = 1usize]
+ | ^^^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:4:17
+ |
+LL | #[rustc_dummy = 1u8]
+ | ^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:5:17
+ |
+LL | #[rustc_dummy = 1u16]
+ | ^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:6:17
+ |
+LL | #[rustc_dummy = 1u32]
+ | ^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:7:17
+ |
+LL | #[rustc_dummy = 1u64]
+ | ^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:8:17
+ |
+LL | #[rustc_dummy = 1isize]
+ | ^^^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:9:17
+ |
+LL | #[rustc_dummy = 1i8]
+ | ^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:10:17
+ |
+LL | #[rustc_dummy = 1i16]
+ | ^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:11:17
+ |
+LL | #[rustc_dummy = 1i32]
+ | ^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:12:17
+ |
+LL | #[rustc_dummy = 1i64]
+ | ^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:13:17
+ |
+LL | #[rustc_dummy = 1.0f32]
+ | ^^^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+ --> $DIR/suffixed-literal-meta.rs:14:17
+ |
+LL | #[rustc_dummy = 1.0f64]
+ | ^^^^^^
+ |
+ = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/attributes/tool_attributes.rs b/src/test/ui/attributes/tool_attributes.rs
new file mode 100644
index 000000000..be4a10c0e
--- /dev/null
+++ b/src/test/ui/attributes/tool_attributes.rs
@@ -0,0 +1,13 @@
+// run-pass
+// Scoped attributes should not trigger an unused attributes lint.
+
+#![deny(unused_attributes)]
+
+fn main() {
+ #[rustfmt::skip]
+ foo ();
+}
+
+fn foo() {
+ assert!(true);
+}
diff --git a/src/test/ui/attributes/unknown-attr.rs b/src/test/ui/attributes/unknown-attr.rs
new file mode 100644
index 000000000..70fef04e9
--- /dev/null
+++ b/src/test/ui/attributes/unknown-attr.rs
@@ -0,0 +1,12 @@
+// Unknown attributes fall back to unstable custom attributes.
+
+#![feature(custom_inner_attributes)]
+
+#![mutable_doc]
+//~^ ERROR cannot find attribute `mutable_doc` in this scope
+
+#[dance] mod a {}
+//~^ ERROR cannot find attribute `dance` in this scope
+
+#[dance] fn main() {}
+//~^ ERROR cannot find attribute `dance` in this scope
diff --git a/src/test/ui/attributes/unknown-attr.stderr b/src/test/ui/attributes/unknown-attr.stderr
new file mode 100644
index 000000000..85c227dc8
--- /dev/null
+++ b/src/test/ui/attributes/unknown-attr.stderr
@@ -0,0 +1,20 @@
+error: cannot find attribute `mutable_doc` in this scope
+ --> $DIR/unknown-attr.rs:5:4
+ |
+LL | #![mutable_doc]
+ | ^^^^^^^^^^^
+
+error: cannot find attribute `dance` in this scope
+ --> $DIR/unknown-attr.rs:8:3
+ |
+LL | #[dance] mod a {}
+ | ^^^^^
+
+error: cannot find attribute `dance` in this scope
+ --> $DIR/unknown-attr.rs:11:3
+ |
+LL | #[dance] fn main() {}
+ | ^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/attributes/unnamed-field-attributes-dup.rs b/src/test/ui/attributes/unnamed-field-attributes-dup.rs
new file mode 100644
index 000000000..7edfd0337
--- /dev/null
+++ b/src/test/ui/attributes/unnamed-field-attributes-dup.rs
@@ -0,0 +1,11 @@
+// Duplicate non-builtin attributes can be used on unnamed fields.
+
+// check-pass
+
+struct S (
+ #[rustfmt::skip]
+ #[rustfmt::skip]
+ u8
+);
+
+fn main() {}
diff --git a/src/test/ui/attributes/unnamed-field-attributes-vis.rs b/src/test/ui/attributes/unnamed-field-attributes-vis.rs
new file mode 100644
index 000000000..d12155f6d
--- /dev/null
+++ b/src/test/ui/attributes/unnamed-field-attributes-vis.rs
@@ -0,0 +1,11 @@
+// Unnamed fields don't lose their visibility due to non-builtin attributes on them.
+
+// check-pass
+
+mod m {
+ pub struct S(#[rustfmt::skip] pub u8);
+}
+
+fn main() {
+ m::S(0);
+}
diff --git a/src/test/ui/attributes/unnamed-field-attributes.rs b/src/test/ui/attributes/unnamed-field-attributes.rs
new file mode 100644
index 000000000..93f364047
--- /dev/null
+++ b/src/test/ui/attributes/unnamed-field-attributes.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+struct S(
+ #[rustfmt::skip] u8,
+ u16,
+ #[rustfmt::skip] u32,
+);
+
+fn main() {}
diff --git a/src/test/ui/attributes/unrestricted-attribute-tokens.rs b/src/test/ui/attributes/unrestricted-attribute-tokens.rs
new file mode 100644
index 000000000..e31bc91a0
--- /dev/null
+++ b/src/test/ui/attributes/unrestricted-attribute-tokens.rs
@@ -0,0 +1,8 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+
+#[rustc_dummy(a b c d)]
+#[rustc_dummy[a b c d]]
+#[rustc_dummy{a b c d}]
+fn main() {}
diff --git a/src/test/ui/attributes/used_with_arg.rs b/src/test/ui/attributes/used_with_arg.rs
new file mode 100644
index 000000000..ad80ff53f
--- /dev/null
+++ b/src/test/ui/attributes/used_with_arg.rs
@@ -0,0 +1,19 @@
+#![feature(used_with_arg)]
+
+#[used(linker)]
+static mut USED_LINKER: [usize; 1] = [0];
+
+#[used(compiler)]
+static mut USED_COMPILER: [usize; 1] = [0];
+
+#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together
+#[used(linker)]
+static mut USED_COMPILER_LINKER2: [usize; 1] = [0];
+
+#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together
+#[used(linker)]
+#[used(compiler)]
+#[used(linker)]
+static mut USED_COMPILER_LINKER3: [usize; 1] = [0];
+
+fn main() {}
diff --git a/src/test/ui/attributes/used_with_arg.stderr b/src/test/ui/attributes/used_with_arg.stderr
new file mode 100644
index 000000000..440e5c4a5
--- /dev/null
+++ b/src/test/ui/attributes/used_with_arg.stderr
@@ -0,0 +1,18 @@
+error: `used(compiler)` and `used(linker)` can't be used together
+ --> $DIR/used_with_arg.rs:9:1
+ |
+LL | #[used(compiler)]
+ | ^^^^^^^^^^^^^^^^^
+LL | #[used(linker)]
+ | ^^^^^^^^^^^^^^^
+
+error: `used(compiler)` and `used(linker)` can't be used together
+ --> $DIR/used_with_arg.rs:13:1
+ |
+LL | #[used(compiler)]
+ | ^^^^^^^^^^^^^^^^^
+LL | #[used(linker)]
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/attributes/used_with_arg_no_mangle.rs b/src/test/ui/attributes/used_with_arg_no_mangle.rs
new file mode 100644
index 000000000..d0bbe76ef
--- /dev/null
+++ b/src/test/ui/attributes/used_with_arg_no_mangle.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+#![feature(used_with_arg)]
+
+#[used(linker)]
+#[no_mangle] // accidentally detected as `used(compiler)`
+pub static GLOB: usize = 0;
+
+fn main() {}
diff --git a/src/test/ui/attributes/used_with_multi_args.rs b/src/test/ui/attributes/used_with_multi_args.rs
new file mode 100644
index 000000000..2e17fcfd7
--- /dev/null
+++ b/src/test/ui/attributes/used_with_multi_args.rs
@@ -0,0 +1,6 @@
+#![feature(used_with_arg)]
+
+#[used(compiler, linker)] //~ expected `used`, `used(compiler)` or `used(linker)`
+static mut USED_COMPILER_LINKER: [usize; 1] = [0];
+
+fn main() {}
diff --git a/src/test/ui/attributes/used_with_multi_args.stderr b/src/test/ui/attributes/used_with_multi_args.stderr
new file mode 100644
index 000000000..c93aafcfc
--- /dev/null
+++ b/src/test/ui/attributes/used_with_multi_args.stderr
@@ -0,0 +1,8 @@
+error: expected `used`, `used(compiler)` or `used(linker)`
+ --> $DIR/used_with_multi_args.rs:3:1
+ |
+LL | #[used(compiler, linker)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/variant-attributes.rs b/src/test/ui/attributes/variant-attributes.rs
new file mode 100644
index 000000000..ffcdeb52a
--- /dev/null
+++ b/src/test/ui/attributes/variant-attributes.rs
@@ -0,0 +1,37 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// pp-exact - Make sure we actually print the attributes
+// pretty-expanded FIXME #23616
+
+#![allow(non_camel_case_types)]
+#![feature(rustc_attrs)]
+
+enum crew_of_enterprise_d {
+
+ #[rustc_dummy]
+ jean_luc_picard,
+
+ #[rustc_dummy]
+ william_t_riker,
+
+ #[rustc_dummy]
+ beverly_crusher,
+
+ #[rustc_dummy]
+ deanna_troi,
+
+ #[rustc_dummy]
+ data,
+
+ #[rustc_dummy]
+ worf,
+
+ #[rustc_dummy]
+ geordi_la_forge,
+}
+
+fn boldly_go(_crew_member: crew_of_enterprise_d, _where: String) { }
+
+fn main() {
+ boldly_go(crew_of_enterprise_d::worf,
+ "where no one has gone before".to_string());
+}