diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/proc-macro | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/proc-macro')
434 files changed, 18620 insertions, 0 deletions
diff --git a/src/test/ui/proc-macro/add-impl.rs b/src/test/ui/proc-macro/add-impl.rs new file mode 100644 index 000000000..ff2897a5e --- /dev/null +++ b/src/test/ui/proc-macro/add-impl.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:add-impl.rs + +#[macro_use] +extern crate add_impl; + +#[derive(AddImpl)] +struct B; + +fn main() { + B.foo(); + foo(); + bar::foo(); +} diff --git a/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs b/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs new file mode 100644 index 000000000..25243aeef --- /dev/null +++ b/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs @@ -0,0 +1,78 @@ +// aux-build:attr-stmt-expr.rs +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// check-pass + +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] +#![allow(dead_code)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate attr_stmt_expr; +extern crate test_macros; +use attr_stmt_expr::{expect_let, expect_my_macro_stmt, expect_expr, expect_my_macro_expr}; +use test_macros::print_attr; + +// We don't use `std::println` so that we avoid loading hygiene +// information from libstd, which would affect the SyntaxContext ids +macro_rules! my_macro { + ($($tt:tt)*) => { () } +} + + +fn print_str(string: &'static str) { + // macros are handled a bit differently + #[expect_my_macro_expr] + my_macro!("{}", string) +} + +macro_rules! make_stmt { + ($stmt:stmt) => { + #[print_attr] + #[rustc_dummy] + $stmt; // This semicolon is *not* passed to the macro, + // since `$stmt` is already a statement. + } +} + +macro_rules! second_make_stmt { + ($stmt:stmt) => { + make_stmt!($stmt); + } +} + +// The macro will see a semicolon here +#[print_attr] +struct ItemWithSemi; + + +fn main() { + make_stmt!(struct Foo {}); + + #[print_attr] + #[expect_let] + let string = "Hello, world!"; + + #[print_attr] + #[expect_my_macro_stmt] + my_macro!("{}", string); + + #[print_attr] + second_make_stmt!(#[allow(dead_code)] struct Bar {}); + + #[print_attr] + #[rustc_dummy] + struct Other {}; + + // The macro also sees a semicolon, + // for consistency with the `ItemWithSemi` case above. + #[print_attr] + #[rustc_dummy] + struct NonBracedStruct; + + #[expect_expr] + print_str("string") +} diff --git a/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout b/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout new file mode 100644 index 000000000..091862de3 --- /dev/null +++ b/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout @@ -0,0 +1,321 @@ +PRINT-ATTR INPUT (DISPLAY): struct ItemWithSemi ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:49:1: 49:7 (#0), + }, + Ident { + ident: "ItemWithSemi", + span: $DIR/allowed-attr-stmt-expr.rs:49:8: 49:20 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:49:20: 49:21 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:35:9: 35:10 (#11), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/allowed-attr-stmt-expr.rs:35:11: 35:22 (#11), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:35:10: 35:23 (#11), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:53:16: 53:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/allowed-attr-stmt-expr.rs:53:23: 53:26 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:53:27: 53:29 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:56:5: 56:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_let", + span: $DIR/allowed-attr-stmt-expr.rs:56:7: 56:17 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:56:6: 56:18 (#0), + }, + Ident { + ident: "let", + span: $DIR/allowed-attr-stmt-expr.rs:57:5: 57:8 (#0), + }, + Ident { + ident: "string", + span: $DIR/allowed-attr-stmt-expr.rs:57:9: 57:15 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:57:16: 57:17 (#0), + }, + Literal { + kind: Str, + symbol: "Hello, world!", + suffix: None, + span: $DIR/allowed-attr-stmt-expr.rs:57:18: 57:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:57:33: 57:34 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:60:5: 60:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_my_macro_stmt", + span: $DIR/allowed-attr-stmt-expr.rs:60:7: 60:27 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:60:6: 60:28 (#0), + }, + Ident { + ident: "my_macro", + span: $DIR/allowed-attr-stmt-expr.rs:61:5: 61:13 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:61:13: 61:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "{}", + suffix: None, + span: $DIR/allowed-attr-stmt-expr.rs:61:15: 61:19 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:61:19: 61:20 (#0), + }, + Ident { + ident: "string", + span: $DIR/allowed-attr-stmt-expr.rs:61:21: 61:27 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:61:14: 61:28 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:61:28: 61:29 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_make_stmt", + span: $DIR/allowed-attr-stmt-expr.rs:64:5: 64:21 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:64:21: 64:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:64:23: 64:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/allowed-attr-stmt-expr.rs:64:25: 64:30 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/allowed-attr-stmt-expr.rs:64:31: 64:40 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:30: 64:41 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:24: 64:42 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:64:43: 64:49 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/allowed-attr-stmt-expr.rs:64:50: 64:53 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:64:54: 64:56 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:22: 64:57 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:64:57: 64:58 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:35:9: 35:10 (#32), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/allowed-attr-stmt-expr.rs:35:11: 35:22 (#32), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:35:10: 35:23 (#32), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:64:23: 64:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/allowed-attr-stmt-expr.rs:64:25: 64:30 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/allowed-attr-stmt-expr.rs:64:31: 64:40 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:30: 64:41 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:24: 64:42 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:64:43: 64:49 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/allowed-attr-stmt-expr.rs:64:50: 64:53 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:64:54: 64:56 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:67:5: 67:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/allowed-attr-stmt-expr.rs:67:7: 67:18 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:67:6: 67:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:68:5: 68:11 (#0), + }, + Ident { + ident: "Other", + span: $DIR/allowed-attr-stmt-expr.rs:68:12: 68:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:68:18: 68:20 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct NonBracedStruct ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:73:5: 73:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/allowed-attr-stmt-expr.rs:73:7: 73:18 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:73:6: 73:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:74:5: 74:11 (#0), + }, + Ident { + ident: "NonBracedStruct", + span: $DIR/allowed-attr-stmt-expr.rs:74:12: 74:27 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:74:27: 74:28 (#0), + }, +] diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.rs new file mode 100644 index 000000000..6a47e50f6 --- /dev/null +++ b/src/test/ui/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 +} diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr new file mode 100644 index 000000000..316eb636b --- /dev/null +++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `NonExistent` in this scope + --> $DIR/ambiguous-builtin-attrs-test.rs:19:5 + | +LL | NonExistent; + | ^^^^^^^^^^^ 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/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs new file mode 100644 index 000000000..695ea69c8 --- /dev/null +++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs @@ -0,0 +1,39 @@ +// edition:2018 +// aux-build:builtin-attrs.rs +#![feature(decl_macro)] //~ ERROR `feature` is ambiguous + +extern crate builtin_attrs; +use builtin_attrs::*; +use builtin_attrs::{bench, test}; + +#[repr(C)] //~ ERROR `repr` is ambiguous +struct S; +#[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous +struct SCond; + +#[test] // OK, shadowed +fn test() {} + +#[bench] // OK, shadowed +fn bench() {} + +fn non_macro_expanded_location<#[repr(C)] T>() { + //~^ ERROR `repr` is ambiguous + //~| ERROR attribute should be applied to a struct, enum, or union + match 0u8 { + #[repr(C)] + //~^ ERROR `repr` is ambiguous + //~| ERROR attribute should be applied to a struct, enum, or union + _ => {} + } +} + +fn main() { + Test; + Bench; + NonExistent; //~ ERROR cannot find value `NonExistent` in this scope +} + +use deny as allow; +#[allow(unused)] //~ ERROR `allow` is ambiguous +fn builtin_renamed() {} diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr new file mode 100644 index 000000000..0f4ddc065 --- /dev/null +++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr @@ -0,0 +1,115 @@ +error[E0425]: cannot find value `NonExistent` in this scope + --> $DIR/ambiguous-builtin-attrs.rs:34:5 + | +LL | NonExistent; + | ^^^^^^^^^^^ not found in this scope + +error[E0659]: `repr` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:9:3 + | +LL | #[repr(C)] + | ^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `repr` could refer to a built-in attribute +note: `repr` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::repr` to refer to this attribute macro unambiguously + +error[E0659]: `repr` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:11:19 + | +LL | #[cfg_attr(all(), repr(C))] + | ^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `repr` could refer to a built-in attribute +note: `repr` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::repr` to refer to this attribute macro unambiguously + +error[E0659]: `repr` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:20:34 + | +LL | fn non_macro_expanded_location<#[repr(C)] T>() { + | ^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `repr` could refer to a built-in attribute +note: `repr` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::repr` to refer to this attribute macro unambiguously + +error[E0659]: `repr` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:24:11 + | +LL | #[repr(C)] + | ^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `repr` could refer to a built-in attribute +note: `repr` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::repr` to refer to this attribute macro unambiguously + +error[E0659]: `allow` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:38:3 + | +LL | #[allow(unused)] + | ^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `allow` could refer to a built-in attribute +note: `allow` could also refer to the built-in attribute imported here + --> $DIR/ambiguous-builtin-attrs.rs:37:5 + | +LL | use deny as allow; + | ^^^^^^^^^^^^^ + = help: use `crate::allow` to refer to this built-in attribute unambiguously + +error[E0659]: `feature` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:3:4 + | +LL | #![feature(decl_macro)] + | ^^^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `feature` could refer to a built-in attribute +note: `feature` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::feature` to refer to this attribute macro unambiguously + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/ambiguous-builtin-attrs.rs:20:39 + | +LL | fn non_macro_expanded_location<#[repr(C)] T>() { + | ^ - not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/ambiguous-builtin-attrs.rs:24:16 + | +LL | #[repr(C)] + | ^ +... +LL | _ => {} + | ------- not a struct, enum, or union + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0425, E0517, E0659. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/proc-macro/amputate-span.fixed b/src/test/ui/proc-macro/amputate-span.fixed new file mode 100644 index 000000000..1afc3501a --- /dev/null +++ b/src/test/ui/proc-macro/amputate-span.fixed @@ -0,0 +1,69 @@ +// aux-build:amputate-span.rs +// run-rustfix +// edition:2018 +// compile-flags: --extern amputate_span + +// This test has been crafted to ensure the following things: +// +// 1. There's a resolution error that prompts the compiler to suggest +// adding a `use` item. +// +// 2. There are no `use` or `extern crate` items in the source +// code. In fact, there is only one item, the `fn main` +// declaration. +// +// 3. The single `fn main` declaration has an attribute attached to it +// that just deletes the first token from the given item. +// +// You need all of these conditions to hold in order to replicate the +// scenario that yielded issue 87613, where the compiler's suggestion +// looks like: +// +// ``` +// help: consider importing this struct +// | +// 47 | hey */ async use std::process::Command; +// | ++++++++++++++++++++++++++ +// ``` +// +// The first condition is necessary to force the compiler issue a +// suggestion. The second condition is necessary to force the +// suggestion to be issued at a span associated with the sole +// `fn`-item of this crate. The third condition is necessary in order +// to yield the weird state where the associated span of the `fn`-item +// does not actually cover all of the original source code of the +// `fn`-item (which is why we are calling it an "amputated" span +// here). +// +// Note that satisfying conditions 2 and 3 requires the use of the +// `--extern` compile flag. +// +// You might ask yourself: What code would do such a thing? The +// answer is: the #[tokio::main] attribute does *exactly* this (as +// well as injecting some other code into the `fn main` that it +// constructs). + +use std::process::Command; + +#[amputate_span::drop_first_token] +/* what the +hey */ async fn main() { + Command::new("git"); //~ ERROR [E0433] +} + +// (The /* ... */ comment in the above is not part of the original +// bug. It is just meant to illustrate one particular facet of the +// original non-ideal behavior, where we were transcribing the +// trailing comment as part of the emitted suggestion, for better or +// for worse.) + +#[allow(dead_code)] +mod inner { + use std::process::Command; + +#[amputate_span::drop_first_token] + /* another interesting + case */ async fn foo() { + Command::new("git"); //~ ERROR [E0433] + } +} diff --git a/src/test/ui/proc-macro/amputate-span.rs b/src/test/ui/proc-macro/amputate-span.rs new file mode 100644 index 000000000..894a06dd5 --- /dev/null +++ b/src/test/ui/proc-macro/amputate-span.rs @@ -0,0 +1,65 @@ +// aux-build:amputate-span.rs +// run-rustfix +// edition:2018 +// compile-flags: --extern amputate_span + +// This test has been crafted to ensure the following things: +// +// 1. There's a resolution error that prompts the compiler to suggest +// adding a `use` item. +// +// 2. There are no `use` or `extern crate` items in the source +// code. In fact, there is only one item, the `fn main` +// declaration. +// +// 3. The single `fn main` declaration has an attribute attached to it +// that just deletes the first token from the given item. +// +// You need all of these conditions to hold in order to replicate the +// scenario that yielded issue 87613, where the compiler's suggestion +// looks like: +// +// ``` +// help: consider importing this struct +// | +// 47 | hey */ async use std::process::Command; +// | ++++++++++++++++++++++++++ +// ``` +// +// The first condition is necessary to force the compiler issue a +// suggestion. The second condition is necessary to force the +// suggestion to be issued at a span associated with the sole +// `fn`-item of this crate. The third condition is necessary in order +// to yield the weird state where the associated span of the `fn`-item +// does not actually cover all of the original source code of the +// `fn`-item (which is why we are calling it an "amputated" span +// here). +// +// Note that satisfying conditions 2 and 3 requires the use of the +// `--extern` compile flag. +// +// You might ask yourself: What code would do such a thing? The +// answer is: the #[tokio::main] attribute does *exactly* this (as +// well as injecting some other code into the `fn main` that it +// constructs). + +#[amputate_span::drop_first_token] +/* what the +hey */ async fn main() { + Command::new("git"); //~ ERROR [E0433] +} + +// (The /* ... */ comment in the above is not part of the original +// bug. It is just meant to illustrate one particular facet of the +// original non-ideal behavior, where we were transcribing the +// trailing comment as part of the emitted suggestion, for better or +// for worse.) + +#[allow(dead_code)] +mod inner { + #[amputate_span::drop_first_token] + /* another interesting + case */ async fn foo() { + Command::new("git"); //~ ERROR [E0433] + } +} diff --git a/src/test/ui/proc-macro/amputate-span.stderr b/src/test/ui/proc-macro/amputate-span.stderr new file mode 100644 index 000000000..9553ba3da --- /dev/null +++ b/src/test/ui/proc-macro/amputate-span.stderr @@ -0,0 +1,25 @@ +error[E0433]: failed to resolve: use of undeclared type `Command` + --> $DIR/amputate-span.rs:49:5 + | +LL | Command::new("git"); + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::process::Command; + | + +error[E0433]: failed to resolve: use of undeclared type `Command` + --> $DIR/amputate-span.rs:63:9 + | +LL | Command::new("git"); + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::process::Command; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/proc-macro/append-impl.rs b/src/test/ui/proc-macro/append-impl.rs new file mode 100644 index 000000000..a49384013 --- /dev/null +++ b/src/test/ui/proc-macro/append-impl.rs @@ -0,0 +1,22 @@ +// run-pass +// aux-build:append-impl.rs + +#![allow(warnings)] + +#[macro_use] +extern crate append_impl; + +trait Append { + fn foo(&self); +} + +#[derive(PartialEq, + Append, + Eq)] +struct A { + inner: u32, +} + +fn main() { + A { inner: 3 }.foo(); +} diff --git a/src/test/ui/proc-macro/attr-args.rs b/src/test/ui/proc-macro/attr-args.rs new file mode 100644 index 000000000..764f507ab --- /dev/null +++ b/src/test/ui/proc-macro/attr-args.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:attr-args.rs + +#![allow(warnings)] + +extern crate attr_args; +use attr_args::{attr_with_args, identity}; + +#[attr_with_args(text = "Hello, world!")] +fn foo() {} + +#[identity(fn main() { assert_eq!(foo(), "Hello, world!"); })] +struct Dummy; diff --git a/src/test/ui/proc-macro/attr-cfg.rs b/src/test/ui/proc-macro/attr-cfg.rs new file mode 100644 index 000000000..2aed9e2e8 --- /dev/null +++ b/src/test/ui/proc-macro/attr-cfg.rs @@ -0,0 +1,27 @@ +// run-pass +// aux-build:attr-cfg.rs +// revisions: foo bar + +extern crate attr_cfg; +use attr_cfg::attr_cfg; + +#[attr_cfg] +fn outer() -> u8 { + #[cfg(foo)] + fn inner() -> u8 { 1 } + + #[cfg(bar)] + fn inner() -> u8 { 2 } + + inner() +} + +#[cfg(foo)] +fn main() { + assert_eq!(outer(), 1); +} + +#[cfg(bar)] +fn main() { + assert_eq!(outer(), 2); +} diff --git a/src/test/ui/proc-macro/attr-complex-fn.rs b/src/test/ui/proc-macro/attr-complex-fn.rs new file mode 100644 index 000000000..47734c94f --- /dev/null +++ b/src/test/ui/proc-macro/attr-complex-fn.rs @@ -0,0 +1,26 @@ +// check-pass +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs + +#![feature(stmt_expr_attributes)] +#![feature(custom_inner_attributes)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +trait MyTrait<T> {} +struct MyStruct<const N: bool>; + +#[print_attr] +fn foo<T: MyTrait<MyStruct<{ true }>>>() {} + +impl<T> MyTrait<T> for MyStruct<{true}> { + #![print_attr] + #![rustc_dummy] +} + +fn main() {} diff --git a/src/test/ui/proc-macro/attr-complex-fn.stdout b/src/test/ui/proc-macro/attr-complex-fn.stdout new file mode 100644 index 000000000..fc69a13dd --- /dev/null +++ b/src/test/ui/proc-macro/attr-complex-fn.stdout @@ -0,0 +1,171 @@ +PRINT-ATTR INPUT (DISPLAY): fn foo < T : MyTrait < MyStruct < { true } >> > () {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/attr-complex-fn.rs:19:1: 19:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/attr-complex-fn.rs:19:4: 19:7 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:7: 19:8 (#0), + }, + Ident { + ident: "T", + span: $DIR/attr-complex-fn.rs:19:8: 19:9 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:9: 19:10 (#0), + }, + Ident { + ident: "MyTrait", + span: $DIR/attr-complex-fn.rs:19:11: 19:18 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:18: 19:19 (#0), + }, + Ident { + ident: "MyStruct", + span: $DIR/attr-complex-fn.rs:19:19: 19:27 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:27: 19:28 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/attr-complex-fn.rs:19:30: 19:34 (#0), + }, + ], + span: $DIR/attr-complex-fn.rs:19:28: 19:36 (#0), + }, + Punct { + ch: '>', + spacing: Joint, + span: $DIR/attr-complex-fn.rs:19:36: 19:38 (#0), + }, + Punct { + ch: '>', + spacing: Joint, + span: $DIR/attr-complex-fn.rs:19:36: 19:38 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:38: 19:39 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/attr-complex-fn.rs:19:39: 19:41 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-complex-fn.rs:19:42: 19:44 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): impl < T > MyTrait < T > for MyStruct < { true } > { #! [rustc_dummy] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/attr-complex-fn.rs:21:1: 21:5 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:5: 21:6 (#0), + }, + Ident { + ident: "T", + span: $DIR/attr-complex-fn.rs:21:6: 21:7 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:7: 21:8 (#0), + }, + Ident { + ident: "MyTrait", + span: $DIR/attr-complex-fn.rs:21:9: 21:16 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:16: 21:17 (#0), + }, + Ident { + ident: "T", + span: $DIR/attr-complex-fn.rs:21:17: 21:18 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:18: 21:19 (#0), + }, + Ident { + ident: "for", + span: $DIR/attr-complex-fn.rs:21:20: 21:23 (#0), + }, + Ident { + ident: "MyStruct", + span: $DIR/attr-complex-fn.rs:21:24: 21:32 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:32: 21:33 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/attr-complex-fn.rs:21:34: 21:38 (#0), + }, + ], + span: $DIR/attr-complex-fn.rs:21:33: 21:39 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:39: 21:40 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/attr-complex-fn.rs:23:5: 23:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:23:6: 23:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/attr-complex-fn.rs:23:8: 23:19 (#0), + }, + ], + span: $DIR/attr-complex-fn.rs:23:7: 23:20 (#0), + }, + ], + span: $DIR/attr-complex-fn.rs:21:41: 24:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.rs b/src/test/ui/proc-macro/attr-invalid-exprs.rs new file mode 100644 index 000000000..9dcffc340 --- /dev/null +++ b/src/test/ui/proc-macro/attr-invalid-exprs.rs @@ -0,0 +1,28 @@ +//! Attributes producing expressions in invalid locations + +// aux-build:attr-stmt-expr.rs + +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] + +extern crate attr_stmt_expr; +use attr_stmt_expr::{duplicate, no_output}; + +fn main() { + let _ = #[no_output] "Hello, world!"; + //~^ ERROR expected expression, found end of macro arguments + + let _ = #[duplicate] "Hello, world!"; + //~^ ERROR macro expansion ignores token `,` and any following + + let _ = { + #[no_output] + "Hello, world!" + }; + + let _ = { + #[duplicate] + //~^ ERROR macro expansion ignores token `,` and any following + "Hello, world!" + }; +} diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.stderr b/src/test/ui/proc-macro/attr-invalid-exprs.stderr new file mode 100644 index 000000000..bcb54df0e --- /dev/null +++ b/src/test/ui/proc-macro/attr-invalid-exprs.stderr @@ -0,0 +1,28 @@ +error: expected expression, found end of macro arguments + --> $DIR/attr-invalid-exprs.rs:12:13 + | +LL | let _ = #[no_output] "Hello, world!"; + | ^^^^^^^^^^^^ + +error: macro expansion ignores token `,` and any following + --> $DIR/attr-invalid-exprs.rs:15:13 + | +LL | let _ = #[duplicate] "Hello, world!"; + | ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;` + | | + | caused by the macro expansion here + | + = note: the usage of `duplicate!` is likely invalid in expression context + +error: macro expansion ignores token `,` and any following + --> $DIR/attr-invalid-exprs.rs:24:9 + | +LL | #[duplicate] + | ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;` + | | + | caused by the macro expansion here + | + = note: the usage of `duplicate!` is likely invalid in expression context + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/proc-macro/attr-on-trait.rs b/src/test/ui/proc-macro/attr-on-trait.rs new file mode 100644 index 000000000..e0edee630 --- /dev/null +++ b/src/test/ui/proc-macro/attr-on-trait.rs @@ -0,0 +1,19 @@ +// run-pass +// aux-build:attr-on-trait.rs + +extern crate attr_on_trait; + +use attr_on_trait::foo; + +trait Foo { + #[foo] + fn foo() {} +} + +impl Foo for i32 { + fn foo(&self) {} +} + +fn main() { + 3i32.foo(); +} diff --git a/src/test/ui/proc-macro/attr-stmt-expr-rpass.rs b/src/test/ui/proc-macro/attr-stmt-expr-rpass.rs new file mode 100644 index 000000000..16b8fabfc --- /dev/null +++ b/src/test/ui/proc-macro/attr-stmt-expr-rpass.rs @@ -0,0 +1,36 @@ +// run-pass +// aux-build:attr-stmt-expr-rpass.rs + +#![feature(stmt_expr_attributes, proc_macro_hygiene)] + +extern crate attr_stmt_expr_rpass as attr_stmt_expr; +use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr, + no_output, noop}; + +fn print_str(string: &'static str) { + // macros are handled a bit differently + #[expect_print_expr] + println!("{}", string) +} + +fn main() { + #[expect_let] + let string = "Hello, world!"; + + #[expect_print_stmt] + println!("{}", string); + + let _: () = { + #[no_output] + "Hello, world!" + }; + + let _: &'static str = #[noop] "Hello, world!"; + + let _: &'static str = { + #[noop] "Hello, world!" + }; + + #[expect_expr] + print_str("string") +} diff --git a/src/test/ui/proc-macro/attr-stmt-expr.rs b/src/test/ui/proc-macro/attr-stmt-expr.rs new file mode 100644 index 000000000..0403684cd --- /dev/null +++ b/src/test/ui/proc-macro/attr-stmt-expr.rs @@ -0,0 +1,66 @@ +// aux-build:attr-stmt-expr.rs +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![feature(proc_macro_hygiene)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; +extern crate test_macros; +extern crate attr_stmt_expr; + +use test_macros::print_attr; +use attr_stmt_expr::{expect_let, expect_my_macro_stmt, expect_expr, expect_my_macro_expr}; + +// We don't use `std::println` so that we avoid loading hygiene +// information from libstd, which would affect the SyntaxContext ids +macro_rules! my_macro { + ($($tt:tt)*) => { () } +} + +fn print_str(string: &'static str) { + // macros are handled a bit differently + #[expect_my_macro_expr] + //~^ ERROR attributes on expressions are experimental + //~| HELP add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + my_macro!("{}", string) +} + +macro_rules! make_stmt { + ($stmt:stmt) => { + #[print_attr] + #[rustc_dummy] + $stmt + } +} + +macro_rules! second_make_stmt { + ($stmt:stmt) => { + make_stmt!($stmt); + } +} + +fn main() { + make_stmt!(struct Foo {}); + + #[print_attr] + #[expect_let] + let string = "Hello, world!"; + + #[print_attr] + #[expect_my_macro_stmt] + my_macro!("{}", string); + + #[print_attr] + second_make_stmt!(#[allow(dead_code)] struct Bar {}); + + #[print_attr] + #[rustc_dummy] + struct Other {} + + #[expect_expr] + //~^ ERROR attributes on expressions are experimental + //~| HELP add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + print_str("string") +} diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stderr b/src/test/ui/proc-macro/attr-stmt-expr.stderr new file mode 100644 index 000000000..56178259d --- /dev/null +++ b/src/test/ui/proc-macro/attr-stmt-expr.stderr @@ -0,0 +1,21 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/attr-stmt-expr.rs:24:5 + | +LL | #[expect_my_macro_expr] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/attr-stmt-expr.rs:62:5 + | +LL | #[expect_expr] + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stdout b/src/test/ui/proc-macro/attr-stmt-expr.stdout new file mode 100644 index 000000000..f9b2305c7 --- /dev/null +++ b/src/test/ui/proc-macro/attr-stmt-expr.stdout @@ -0,0 +1,274 @@ +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:33:9: 33:10 (#8), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/attr-stmt-expr.rs:33:11: 33:22 (#8), + }, + ], + span: $DIR/attr-stmt-expr.rs:33:10: 33:23 (#8), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:45:16: 45:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/attr-stmt-expr.rs:45:23: 45:26 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:45:27: 45:29 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:48:5: 48:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_let", + span: $DIR/attr-stmt-expr.rs:48:7: 48:17 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:48:6: 48:18 (#0), + }, + Ident { + ident: "let", + span: $DIR/attr-stmt-expr.rs:49:5: 49:8 (#0), + }, + Ident { + ident: "string", + span: $DIR/attr-stmt-expr.rs:49:9: 49:15 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:49:16: 49:17 (#0), + }, + Literal { + kind: Str, + symbol: "Hello, world!", + suffix: None, + span: $DIR/attr-stmt-expr.rs:49:18: 49:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:49:33: 49:34 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:52:5: 52:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_my_macro_stmt", + span: $DIR/attr-stmt-expr.rs:52:7: 52:27 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:52:6: 52:28 (#0), + }, + Ident { + ident: "my_macro", + span: $DIR/attr-stmt-expr.rs:53:5: 53:13 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:53:13: 53:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "{}", + suffix: None, + span: $DIR/attr-stmt-expr.rs:53:15: 53:19 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:53:19: 53:20 (#0), + }, + Ident { + ident: "string", + span: $DIR/attr-stmt-expr.rs:53:21: 53:27 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:53:14: 53:28 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:53:28: 53:29 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_make_stmt", + span: $DIR/attr-stmt-expr.rs:56:5: 56:21 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:56:21: 56:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:56:23: 56:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/attr-stmt-expr.rs:56:25: 56:30 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/attr-stmt-expr.rs:56:31: 56:40 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:30: 56:41 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:24: 56:42 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:56:43: 56:49 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/attr-stmt-expr.rs:56:50: 56:53 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:56:54: 56:56 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:22: 56:57 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:56:57: 56:58 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:33:9: 33:10 (#29), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/attr-stmt-expr.rs:33:11: 33:22 (#29), + }, + ], + span: $DIR/attr-stmt-expr.rs:33:10: 33:23 (#29), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:56:23: 56:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/attr-stmt-expr.rs:56:25: 56:30 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/attr-stmt-expr.rs:56:31: 56:40 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:30: 56:41 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:24: 56:42 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:56:43: 56:49 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/attr-stmt-expr.rs:56:50: 56:53 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:56:54: 56:56 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:59:5: 59:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/attr-stmt-expr.rs:59:7: 59:18 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:59:6: 59:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:60:5: 60:11 (#0), + }, + Ident { + ident: "Other", + span: $DIR/attr-stmt-expr.rs:60:12: 60:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:60:18: 60:20 (#0), + }, +] diff --git a/src/test/ui/proc-macro/attribute-after-derive.rs b/src/test/ui/proc-macro/attribute-after-derive.rs new file mode 100644 index 000000000..0f0f27bff --- /dev/null +++ b/src/test/ui/proc-macro/attribute-after-derive.rs @@ -0,0 +1,28 @@ +// Macro attributes are allowed after `#[derive]` and +// `#[derive]` fully configures the item for following attributes. + +// check-pass +// compile-flags: -Z span-debug +// aux-build: test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[print_attr] +#[derive(Print)] +struct AttributeDerive { + #[cfg(FALSE)] + field: u8, +} + +#[derive(Print)] +#[print_attr] +struct DeriveAttribute { + #[cfg(FALSE)] + field: u8, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/attribute-after-derive.stdout b/src/test/ui/proc-macro/attribute-after-derive.stdout new file mode 100644 index 000000000..1b17d6047 --- /dev/null +++ b/src/test/ui/proc-macro/attribute-after-derive.stdout @@ -0,0 +1,192 @@ +PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field : u8, } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:15:1: 15:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "derive", + span: $DIR/attribute-after-derive.rs:15:3: 15:9 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "Print", + span: $DIR/attribute-after-derive.rs:15:10: 15:15 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:15:9: 15:16 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:15:2: 15:17 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0), + }, + Ident { + ident: "AttributeDerive", + span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:17:5: 17:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/attribute-after-derive.rs:17:7: 17:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:17:10: 17:17 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:17:6: 17:18 (#0), + }, + Ident { + ident: "field", + span: $DIR/attribute-after-derive.rs:18:5: 18:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:18:10: 18:11 (#0), + }, + Ident { + ident: "u8", + span: $DIR/attribute-after-derive.rs:18:12: 18:14 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:18:14: 18:15 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive {} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0), + }, + Ident { + ident: "AttributeDerive", + span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute {} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:22:1: 22:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_attr", + span: $DIR/attribute-after-derive.rs:22:3: 22:13 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:22:2: 22:14 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0), + }, + Ident { + ident: "DeriveAttribute", + span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field : u8, } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0), + }, + Ident { + ident: "DeriveAttribute", + span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:24:5: 24:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/attribute-after-derive.rs:24:7: 24:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/attribute-after-derive.rs:24:11: 24:16 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:24:10: 24:17 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:24:6: 24:18 (#0), + }, + Ident { + ident: "field", + span: $DIR/attribute-after-derive.rs:25:5: 25:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:25:10: 25:11 (#0), + }, + Ident { + ident: "u8", + span: $DIR/attribute-after-derive.rs:25:12: 25:14 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:25:14: 25:15 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.rs b/src/test/ui/proc-macro/attribute-spans-preserved.rs new file mode 100644 index 000000000..c01fce905 --- /dev/null +++ b/src/test/ui/proc-macro/attribute-spans-preserved.rs @@ -0,0 +1,10 @@ +// aux-build:attribute-spans-preserved.rs + +extern crate attribute_spans_preserved as foo; + +use foo::foo; + +#[ foo ( let y: u32 = "z"; ) ] //~ ERROR: mismatched types +#[ bar { let x: u32 = "y"; } ] //~ ERROR: mismatched types +fn main() { +} diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stderr b/src/test/ui/proc-macro/attribute-spans-preserved.stderr new file mode 100644 index 000000000..193482a42 --- /dev/null +++ b/src/test/ui/proc-macro/attribute-spans-preserved.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/attribute-spans-preserved.rs:7:23 + | +LL | #[ foo ( let y: u32 = "z"; ) ] + | --- ^^^ expected `u32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/attribute-spans-preserved.rs:8:23 + | +LL | #[ bar { let x: u32 = "y"; } ] + | --- ^^^ expected `u32`, found `&str` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stdout b/src/test/ui/proc-macro/attribute-spans-preserved.stdout new file mode 100644 index 000000000..cf9a97491 --- /dev/null +++ b/src/test/ui/proc-macro/attribute-spans-preserved.stdout @@ -0,0 +1 @@ +fn main() { let y : u32 = "z" ; { let x : u32 = "y" ; } } diff --git a/src/test/ui/proc-macro/attribute-with-error.rs b/src/test/ui/proc-macro/attribute-with-error.rs new file mode 100644 index 000000000..aaa6c07dd --- /dev/null +++ b/src/test/ui/proc-macro/attribute-with-error.rs @@ -0,0 +1,42 @@ +// aux-build:test-macros.rs + +#![feature(custom_inner_attributes)] + +#[macro_use] +extern crate test_macros; + +#[recollect_attr] +fn test1() { + let a: i32 = "foo"; + //~^ ERROR: mismatched types + let b: i32 = "f'oo"; + //~^ ERROR: mismatched types +} + +fn test2() { + #![recollect_attr] + + // FIXME: should have a type error here and assert it works but it doesn't +} + +trait A { + // FIXME: should have a #[recollect_attr] attribute here and assert that it works + fn foo(&self) { + let a: i32 = "foo"; + //~^ ERROR: mismatched types + } +} + +struct B; + +impl A for B { + #[recollect_attr] + fn foo(&self) { + let a: i32 = "foo"; + //~^ ERROR: mismatched types + } +} + +#[recollect_attr] +fn main() { +} diff --git a/src/test/ui/proc-macro/attribute-with-error.stderr b/src/test/ui/proc-macro/attribute-with-error.stderr new file mode 100644 index 000000000..7f3a7e670 --- /dev/null +++ b/src/test/ui/proc-macro/attribute-with-error.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:10:18 + | +LL | let a: i32 = "foo"; + | --- ^^^^^ expected `i32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:12:18 + | +LL | let b: i32 = "f'oo"; + | --- ^^^^^^ expected `i32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:25:22 + | +LL | let a: i32 = "foo"; + | --- ^^^^^ expected `i32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:35:22 + | +LL | let a: i32 = "foo"; + | --- ^^^^^ expected `i32`, found `&str` + | | + | expected due to this + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs new file mode 100644 index 000000000..5531b3236 --- /dev/null +++ b/src/test/ui/proc-macro/attribute.rs @@ -0,0 +1,73 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive] //~ ERROR malformed `proc_macro_derive` attribute +pub fn foo1(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive = ""] //~ ERROR malformed `proc_macro_derive` attribute +pub fn foo2(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d3, a, b)] +//~^ ERROR attribute must have either one or two arguments +pub fn foo3(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d4, attributes(a), b)] +//~^ ERROR attribute must have either one or two arguments +pub fn foo4(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive("a")] +//~^ ERROR: not a meta item +pub fn foo5(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d6 = "")] +//~^ ERROR: must only be one word +pub fn foo6(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(m::d7)] +//~^ ERROR: must only be one word +pub fn foo7(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d8(a))] +//~^ ERROR: must only be one word +pub fn foo8(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(self)] +//~^ ERROR: `self` cannot be a name of derive macro +pub fn foo9(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(PartialEq)] // OK +pub fn foo10(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d11, a)] +//~^ ERROR: second argument must be `attributes` +//~| ERROR: attribute must be of form: `attributes(foo, bar)` +pub fn foo11(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d12, attributes)] +//~^ ERROR: attribute must be of form: `attributes(foo, bar)` +pub fn foo12(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d13, attributes("a"))] +//~^ ERROR: not a meta item +pub fn foo13(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d14, attributes(a = ""))] +//~^ ERROR: must only be one word +pub fn foo14(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d15, attributes(m::a))] +//~^ ERROR: must only be one word +pub fn foo15(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d16, attributes(a(b)))] +//~^ ERROR: must only be one word +pub fn foo16(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d17, attributes(self))] +//~^ ERROR: `self` cannot be a name of derive helper attribute +pub fn foo17(input: TokenStream) -> TokenStream { input } diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr new file mode 100644 index 000000000..021e7cad0 --- /dev/null +++ b/src/test/ui/proc-macro/attribute.stderr @@ -0,0 +1,104 @@ +error: malformed `proc_macro_derive` attribute input + --> $DIR/attribute.rs:9:1 + | +LL | #[proc_macro_derive] + | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + +error: malformed `proc_macro_derive` attribute input + --> $DIR/attribute.rs:12:1 + | +LL | #[proc_macro_derive = ""] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + +error: attribute must have either one or two arguments + --> $DIR/attribute.rs:15:1 + | +LL | #[proc_macro_derive(d3, a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute must have either one or two arguments + --> $DIR/attribute.rs:19:1 + | +LL | #[proc_macro_derive(d4, attributes(a), b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: not a meta item + --> $DIR/attribute.rs:23:21 + | +LL | #[proc_macro_derive("a")] + | ^^^ + +error: must only be one word + --> $DIR/attribute.rs:27:21 + | +LL | #[proc_macro_derive(d6 = "")] + | ^^^^^^^ + +error: must only be one word + --> $DIR/attribute.rs:31:21 + | +LL | #[proc_macro_derive(m::d7)] + | ^^^^^ + +error: must only be one word + --> $DIR/attribute.rs:35:21 + | +LL | #[proc_macro_derive(d8(a))] + | ^^^^^ + +error: `self` cannot be a name of derive macro + --> $DIR/attribute.rs:39:21 + | +LL | #[proc_macro_derive(self)] + | ^^^^ + +error: second argument must be `attributes` + --> $DIR/attribute.rs:46:26 + | +LL | #[proc_macro_derive(d11, a)] + | ^ + +error: attribute must be of form: `attributes(foo, bar)` + --> $DIR/attribute.rs:46:26 + | +LL | #[proc_macro_derive(d11, a)] + | ^ + +error: attribute must be of form: `attributes(foo, bar)` + --> $DIR/attribute.rs:51:26 + | +LL | #[proc_macro_derive(d12, attributes)] + | ^^^^^^^^^^ + +error: not a meta item + --> $DIR/attribute.rs:55:37 + | +LL | #[proc_macro_derive(d13, attributes("a"))] + | ^^^ + +error: must only be one word + --> $DIR/attribute.rs:59:37 + | +LL | #[proc_macro_derive(d14, attributes(a = ""))] + | ^^^^^^ + +error: must only be one word + --> $DIR/attribute.rs:63:37 + | +LL | #[proc_macro_derive(d15, attributes(m::a))] + | ^^^^ + +error: must only be one word + --> $DIR/attribute.rs:67:37 + | +LL | #[proc_macro_derive(d16, attributes(a(b)))] + | ^^^^ + +error: `self` cannot be a name of derive helper attribute + --> $DIR/attribute.rs:71:37 + | +LL | #[proc_macro_derive(d17, attributes(self))] + | ^^^^ + +error: aborting due to 17 previous errors + diff --git a/src/test/ui/proc-macro/attributes-included.rs b/src/test/ui/proc-macro/attributes-included.rs new file mode 100644 index 000000000..95e8e10a3 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-included.rs @@ -0,0 +1,22 @@ +// aux-build:attributes-included.rs +// check-pass + +#![warn(unused)] + +extern crate attributes_included; + +use attributes_included::*; + +#[bar] +#[inline] +/// doc +#[foo] +#[inline] +/// doc +fn foo() { + let a: i32 = "foo"; //~ WARN: unused variable +} + +fn main() { + foo() +} diff --git a/src/test/ui/proc-macro/attributes-included.stderr b/src/test/ui/proc-macro/attributes-included.stderr new file mode 100644 index 000000000..72c88d5d8 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-included.stderr @@ -0,0 +1,15 @@ +warning: unused variable: `a` + --> $DIR/attributes-included.rs:17:9 + | +LL | let a: i32 = "foo"; + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/attributes-included.rs:4:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: 1 warning emitted + diff --git a/src/test/ui/proc-macro/attributes-on-definitions.rs b/src/test/ui/proc-macro/attributes-on-definitions.rs new file mode 100644 index 000000000..c0733c8b4 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-definitions.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:attributes-on-definitions.rs + +#![forbid(unsafe_code)] + +extern crate attributes_on_definitions; + +attributes_on_definitions::with_attrs!(); +//~^ WARN use of deprecated +// No errors about the use of unstable and unsafe code inside the macro. + +fn main() {} diff --git a/src/test/ui/proc-macro/attributes-on-definitions.stderr b/src/test/ui/proc-macro/attributes-on-definitions.stderr new file mode 100644 index 000000000..c63dd0011 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-definitions.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated macro `attributes_on_definitions::with_attrs`: test + --> $DIR/attributes-on-definitions.rs:8:1 + | +LL | attributes_on_definitions::with_attrs!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/proc-macro/attributes-on-modules-fail.rs b/src/test/ui/proc-macro/attributes-on-modules-fail.rs new file mode 100644 index 000000000..6c30e8f4f --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-modules-fail.rs @@ -0,0 +1,46 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[identity_attr] +mod m { + pub struct X; + + type A = Y; //~ ERROR cannot find type `Y` in this scope +} + +struct Y; +type A = X; //~ ERROR cannot find type `X` in this scope + +#[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s +mod n {} + +#[empty_attr] +mod module; //~ ERROR non-inline modules in proc macro input are unstable + +#[empty_attr] +mod outer { + mod inner; //~ ERROR non-inline modules in proc macro input are unstable + + mod inner_inline {} // OK +} + +#[derive(Empty)] +struct S { + field: [u8; { + #[path = "outer/inner.rs"] + mod inner; //~ ERROR non-inline modules in proc macro input are unstable + mod inner_inline {} // OK + 0 + }] +} + +#[identity_attr] +fn f() { + #[path = "outer/inner.rs"] + mod inner; //~ ERROR non-inline modules in proc macro input are unstable + mod inner_inline {} // OK +} + +fn main() {} diff --git a/src/test/ui/proc-macro/attributes-on-modules-fail.stderr b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr new file mode 100644 index 000000000..bb6cbb698 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr @@ -0,0 +1,70 @@ +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/attributes-on-modules-fail.rs:16:1 + | +LL | #[derive(Copy)] + | ^^^^^^^^^^^^^^^ not applicable here +LL | mod n {} + | -------- not a `struct`, `enum` or `union` + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/attributes-on-modules-fail.rs:20:1 + | +LL | mod module; + | ^^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/attributes-on-modules-fail.rs:24:5 + | +LL | mod inner; + | ^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/attributes-on-modules-fail.rs:33:9 + | +LL | mod inner; + | ^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/attributes-on-modules-fail.rs:42:5 + | +LL | mod inner; + | ^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0412]: cannot find type `Y` in this scope + --> $DIR/attributes-on-modules-fail.rs:10:14 + | +LL | type A = Y; + | ^ not found in this scope + | +help: consider importing this struct + | +LL | use Y; + | + +error[E0412]: cannot find type `X` in this scope + --> $DIR/attributes-on-modules-fail.rs:14:10 + | +LL | type A = X; + | ^ not found in this scope + | +help: consider importing this struct + | +LL | use m::X; + | + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0412, E0658, E0774. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/proc-macro/attributes-on-modules.rs b/src/test/ui/proc-macro/attributes-on-modules.rs new file mode 100644 index 000000000..6c73b0bf1 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-modules.rs @@ -0,0 +1,19 @@ +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[identity_attr] +mod m { + pub struct S; +} + +#[identity_attr] +fn f() { + mod m {} +} + +fn main() { + let s = m::S; +} diff --git a/src/test/ui/proc-macro/auxiliary/add-impl.rs b/src/test/ui/proc-macro/auxiliary/add-impl.rs new file mode 100644 index 000000000..741e64875 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/add-impl.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(AddImpl)] +// #[cfg(proc_macro)] +pub fn derive(input: TokenStream) -> TokenStream { + "impl B { + fn foo(&self) {} + } + + fn foo() {} + + mod bar { pub fn foo() {} } + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/amputate-span.rs b/src/test/ui/proc-macro/auxiliary/amputate-span.rs new file mode 100644 index 000000000..1a82119ae --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/amputate-span.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn drop_first_token(attr: TokenStream, input: TokenStream) -> TokenStream { + assert!(attr.is_empty()); + input.into_iter().skip(1).collect() +} diff --git a/src/test/ui/proc-macro/auxiliary/api/cmp.rs b/src/test/ui/proc-macro/auxiliary/api/cmp.rs new file mode 100644 index 000000000..5784a6e5d --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/api/cmp.rs @@ -0,0 +1,21 @@ +use proc_macro::{LineColumn, Punct, Spacing}; + +pub fn test() { + test_line_column_ord(); + test_punct_eq(); +} + +fn test_line_column_ord() { + let line0_column0 = LineColumn { line: 0, column: 0 }; + let line0_column1 = LineColumn { line: 0, column: 1 }; + let line1_column0 = LineColumn { line: 1, column: 0 }; + assert!(line0_column0 < line0_column1); + assert!(line0_column1 < line1_column0); +} + +fn test_punct_eq() { + let colon_alone = Punct::new(':', Spacing::Alone); + assert_eq!(colon_alone, ':'); + let colon_joint = Punct::new(':', Spacing::Joint); + assert_eq!(colon_joint, ':'); +} diff --git a/src/test/ui/proc-macro/auxiliary/api/mod.rs b/src/test/ui/proc-macro/auxiliary/api/mod.rs new file mode 100644 index 000000000..739c25132 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/api/mod.rs @@ -0,0 +1,24 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![crate_name = "proc_macro_api_tests"] +#![feature(proc_macro_span)] +#![deny(dead_code)] // catch if a test function is never called + +extern crate proc_macro; + +mod cmp; +mod parse; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn run(input: TokenStream) -> TokenStream { + assert!(input.is_empty()); + + cmp::test(); + parse::test(); + + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs new file mode 100644 index 000000000..27391f831 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/api/parse.rs @@ -0,0 +1,55 @@ +// ignore-tidy-linelength + +use proc_macro::Literal; + +pub fn test() { + test_display_literal(); + test_parse_literal(); +} + +fn test_display_literal() { + assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10"); + assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize"); + assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0"); + assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32"); + assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0"); + assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64"); + assert_eq!( + Literal::f64_unsuffixed(1e100).to_string(), + "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", + ); + + assert_eq!( + Literal::string("a \t ❤ ' \" \u{1}").to_string(), + "\"a \\t ❤ ' \\\" \\u{1}\"", + ); + assert_eq!(Literal::character('a').to_string(), "'a'"); + assert_eq!(Literal::character('\t').to_string(), "'\\t'"); + assert_eq!(Literal::character('❤').to_string(), "'❤'"); + assert_eq!(Literal::character('\'').to_string(), "'\\''"); + assert_eq!(Literal::character('"').to_string(), "'\"'"); + assert_eq!(Literal::character('\u{1}').to_string(), "'\\u{1}'"); +} + +fn test_parse_literal() { + assert_eq!("1".parse::<Literal>().unwrap().to_string(), "1"); + assert_eq!("1.0".parse::<Literal>().unwrap().to_string(), "1.0"); + assert_eq!("'a'".parse::<Literal>().unwrap().to_string(), "'a'"); + assert_eq!("\"\n\"".parse::<Literal>().unwrap().to_string(), "\"\n\""); + assert_eq!("b\"\"".parse::<Literal>().unwrap().to_string(), "b\"\""); + assert_eq!("r##\"\"##".parse::<Literal>().unwrap().to_string(), "r##\"\"##"); + assert_eq!("10ulong".parse::<Literal>().unwrap().to_string(), "10ulong"); + assert_eq!("-10ulong".parse::<Literal>().unwrap().to_string(), "-10ulong"); + + assert!("true".parse::<Literal>().is_err()); + assert!(".8".parse::<Literal>().is_err()); + assert!("0 1".parse::<Literal>().is_err()); + assert!("'a".parse::<Literal>().is_err()); + assert!(" 0".parse::<Literal>().is_err()); + assert!("0 ".parse::<Literal>().is_err()); + assert!("/* comment */0".parse::<Literal>().is_err()); + assert!("0/* comment */".parse::<Literal>().is_err()); + assert!("0// comment".parse::<Literal>().is_err()); + assert!("- 10".parse::<Literal>().is_err()); + assert!("-'x'".parse::<Literal>().is_err()); +} diff --git a/src/test/ui/proc-macro/auxiliary/append-impl.rs b/src/test/ui/proc-macro/auxiliary/append-impl.rs new file mode 100644 index 000000000..b032b1337 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/append-impl.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Append)] +pub fn derive_a(input: TokenStream) -> TokenStream { + "impl Append for A { + fn foo(&self) {} + } + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/assert-span-pos.rs b/src/test/ui/proc-macro/auxiliary/assert-span-pos.rs new file mode 100644 index 000000000..455c5c7c3 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/assert-span-pos.rs @@ -0,0 +1,37 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_diagnostic, proc_macro_span)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span}; + +fn lit_span(tt: TokenTree) -> (Span, String) { + match tt { + TokenTree::Literal(..) | + TokenTree::Group(..) => (tt.span(), tt.to_string().trim().into()), + _ => panic!("expected a literal in token tree, got: {:?}", tt) + } +} + +#[proc_macro] +pub fn assert_span_pos(input: TokenStream) -> TokenStream { + let mut tokens = input.into_iter(); + let (sp1, str1) = lit_span(tokens.next().expect("first argument")); + let _ = tokens.next(); + let (_sp2, str2) = lit_span(tokens.next().expect("second argument")); + + let line: usize = str1.parse().unwrap(); + let col: usize = str2.parse().unwrap(); + + let sp1s = sp1.start(); + if (line, col) != (sp1s.line, sp1s.column) { + let msg = format!("line/column mismatch: ({}, {}) != ({}, {})", line, col, + sp1s.line, sp1s.column); + sp1.error(msg).emit(); + } + + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/attr-args.rs b/src/test/ui/proc-macro/auxiliary/attr-args.rs new file mode 100644 index 000000000..5f76a4484 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attr-args.rs @@ -0,0 +1,28 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream { + let args = args.to_string(); + + assert_eq!(args, r#"text = "Hello, world!""#); + + let input = input.to_string(); + + assert_eq!(input, "fn foo() {}"); + + r#" + fn foo() -> &'static str { "Hello, world!" } + "#.parse().unwrap() +} + +#[proc_macro_attribute] +pub fn identity(attr_args: TokenStream, _: TokenStream) -> TokenStream { + attr_args +} diff --git a/src/test/ui/proc-macro/auxiliary/attr-cfg.rs b/src/test/ui/proc-macro/auxiliary/attr-cfg.rs new file mode 100644 index 000000000..2f0054cc1 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attr-cfg.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream { + let input_str = input.to_string(); + + assert_eq!(input_str, "fn outer() -> u8 +{ + #[cfg(foo)] fn inner() -> u8 { 1 } #[cfg(bar)] fn inner() -> u8 { 2 } + inner() +}"); + + input +} diff --git a/src/test/ui/proc-macro/auxiliary/attr-on-trait.rs b/src/test/ui/proc-macro/auxiliary/attr-on-trait.rs new file mode 100644 index 000000000..3787b8eec --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attr-on-trait.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn foo(attr: TokenStream, item: TokenStream) -> TokenStream { + drop(attr); + assert_eq!(item.to_string(), "fn foo() {}"); + "fn foo(&self);".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs new file mode 100644 index 000000000..5b386b46b --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs @@ -0,0 +1,51 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;"); + item +} + +#[proc_macro_attribute] +pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "println! (\"{}\", string) ;"); + item +} + +#[proc_macro_attribute] +pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "print_str(\"string\")"); + item +} + +#[proc_macro_attribute] +pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "println! (\"{}\", string)"); + item +} + +#[proc_macro_attribute] +pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + "".parse().unwrap() + +} + +#[proc_macro_attribute] +pub fn noop(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + item +} diff --git a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs new file mode 100644 index 000000000..4d6dc06b4 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs @@ -0,0 +1,49 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;"); + item +} + +#[proc_macro_attribute] +pub fn expect_my_macro_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "my_macro! (\"{}\", string) ;"); + item +} + +#[proc_macro_attribute] +pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "print_str(\"string\")"); + item +} + +#[proc_macro_attribute] +pub fn expect_my_macro_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "my_macro! (\"{}\", string)"); + item +} + +#[proc_macro_attribute] +pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + format!("{}, {}", item, item).parse().unwrap() +} + +#[proc_macro_attribute] +pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/attribute-spans-preserved.rs b/src/test/ui/proc-macro/auxiliary/attribute-spans-preserved.rs new file mode 100644 index 000000000..4d3279584 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attribute-spans-preserved.rs @@ -0,0 +1,35 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn foo(attr: TokenStream, f: TokenStream) -> TokenStream { + let mut tokens = f.into_iter(); + assert_eq!(tokens.next().unwrap().to_string(), "#"); + let next_attr = match tokens.next().unwrap() { + TokenTree::Group(g) => g, + _ => panic!(), + }; + + let fn_tok = tokens.next().unwrap(); + let ident_tok = tokens.next().unwrap(); + let args_tok = tokens.next().unwrap(); + let body = tokens.next().unwrap(); + + let new_body = attr.into_iter() + .chain(next_attr.stream().into_iter().skip(1)); + + let tokens = vec![ + fn_tok, + ident_tok, + args_tok, + Group::new(Delimiter::Brace, new_body.collect()).into(), + ].into_iter().collect::<TokenStream>(); + println!("{}", tokens); + return tokens +} diff --git a/src/test/ui/proc-macro/auxiliary/attributes-included.rs b/src/test/ui/proc-macro/auxiliary/attributes-included.rs new file mode 100644 index 000000000..a5eb40b28 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attributes-included.rs @@ -0,0 +1,150 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Delimiter, Literal, Spacing, Group}; + +#[proc_macro_attribute] +pub fn foo(attr: TokenStream, input: TokenStream) -> TokenStream { + assert!(attr.is_empty()); + let input = input.into_iter().collect::<Vec<_>>(); + { + let mut cursor = &input[..]; + assert_inline(&mut cursor); + assert_doc(&mut cursor); + assert_inline(&mut cursor); + assert_doc(&mut cursor); + assert_foo(&mut cursor); + assert!(cursor.is_empty()); + } + fold_stream(input.into_iter().collect()) +} + +#[proc_macro_attribute] +pub fn bar(attr: TokenStream, input: TokenStream) -> TokenStream { + assert!(attr.is_empty()); + let input = input.into_iter().collect::<Vec<_>>(); + { + let mut cursor = &input[..]; + assert_inline(&mut cursor); + assert_doc(&mut cursor); + assert_invoc(&mut cursor); + assert_inline(&mut cursor); + assert_doc(&mut cursor); + assert_foo(&mut cursor); + assert!(cursor.is_empty()); + } + input.into_iter().collect() +} + +fn assert_inline(slice: &mut &[TokenTree]) { + match &slice[0] { + TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'), + _ => panic!("expected '#' char"), + } + match &slice[1] { + TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket), + _ => panic!("expected brackets"), + } + *slice = &slice[2..]; +} + +fn assert_doc(slice: &mut &[TokenTree]) { + match &slice[0] { + TokenTree::Punct(tt) => { + assert_eq!(tt.as_char(), '#'); + assert_eq!(tt.spacing(), Spacing::Alone); + } + _ => panic!("expected #"), + } + let inner = match &slice[1] { + TokenTree::Group(tt) => { + assert_eq!(tt.delimiter(), Delimiter::Bracket); + tt.stream() + } + _ => panic!("expected brackets"), + }; + let tokens = inner.into_iter().collect::<Vec<_>>(); + let tokens = &tokens[..]; + + if tokens.len() != 3 { + panic!("expected three tokens in doc") + } + + match &tokens[0] { + TokenTree::Ident(tt) => assert_eq!("doc", &*tt.to_string()), + _ => panic!("expected `doc`"), + } + match &tokens[1] { + TokenTree::Punct(tt) => { + assert_eq!(tt.as_char(), '='); + assert_eq!(tt.spacing(), Spacing::Alone); + } + _ => panic!("expected equals"), + } + match tokens[2] { + TokenTree::Literal(_) => {} + _ => panic!("expected literal"), + } + + *slice = &slice[2..]; +} + +fn assert_invoc(slice: &mut &[TokenTree]) { + match &slice[0] { + TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'), + _ => panic!("expected '#' char"), + } + match &slice[1] { + TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket), + _ => panic!("expected brackets"), + } + *slice = &slice[2..]; +} + +fn assert_foo(slice: &mut &[TokenTree]) { + match &slice[0] { + TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "fn"), + _ => panic!("expected fn"), + } + match &slice[1] { + TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "foo"), + _ => panic!("expected foo"), + } + match &slice[2] { + TokenTree::Group(tt) => { + assert_eq!(tt.delimiter(), Delimiter::Parenthesis); + assert!(tt.stream().is_empty()); + } + _ => panic!("expected parens"), + } + match &slice[3] { + TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Brace), + _ => panic!("expected braces"), + } + *slice = &slice[4..]; +} + +fn fold_stream(input: TokenStream) -> TokenStream { + input.into_iter().map(fold_tree).collect() +} + +fn fold_tree(input: TokenTree) -> TokenTree { + match input { + TokenTree::Group(b) => { + TokenTree::Group(Group::new(b.delimiter(), fold_stream(b.stream()))) + } + TokenTree::Punct(b) => TokenTree::Punct(b), + TokenTree::Ident(a) => TokenTree::Ident(a), + TokenTree::Literal(a) => { + if a.to_string() != "\"foo\"" { + TokenTree::Literal(a) + } else { + TokenTree::Literal(Literal::i32_unsuffixed(3)) + } + } + } +} diff --git a/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs new file mode 100644 index 000000000..93a339840 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs @@ -0,0 +1,23 @@ +// force-host +// no-prefer-dynamic + +#![feature(allow_internal_unsafe)] +#![feature(allow_internal_unstable)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +#[allow_internal_unstable(proc_macro_internals)] +#[allow_internal_unsafe] +#[deprecated(since = "1.0.0", note = "test")] +pub fn with_attrs(_: TokenStream) -> TokenStream { + " + extern crate proc_macro; + use ::proc_macro::bridge; + + fn contains_unsafe() { unsafe {} } + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/bang-macro.rs b/src/test/ui/proc-macro/auxiliary/bang-macro.rs new file mode 100644 index 000000000..ff0002282 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/bang-macro.rs @@ -0,0 +1,17 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn rewrite(input: TokenStream) -> TokenStream { + let input = input.to_string(); + + assert_eq!(input, r#""Hello, world!""#); + + r#""NOT Hello, world!""#.parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs b/src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs new file mode 100644 index 000000000..fcaaba602 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn bang_proc_macro2(_: TokenStream) -> TokenStream { + "let x = foobar2;".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/builtin-attrs.rs b/src/test/ui/proc-macro/auxiliary/builtin-attrs.rs new file mode 100644 index 000000000..6edafae39 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/builtin-attrs.rs @@ -0,0 +1,27 @@ +// force-host +// 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 test(_: TokenStream, input: TokenStream) -> TokenStream { + "struct Test;".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn bench(_: TokenStream, input: TokenStream) -> TokenStream { + "struct Bench;".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/call-deprecated.rs b/src/test/ui/proc-macro/auxiliary/call-deprecated.rs new file mode 100644 index 000000000..2f484809a --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/call-deprecated.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +#[deprecated(since = "1.0.0", note = "test")] +pub fn attr(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +#[deprecated(since = "1.0.0", note = "test")] +pub fn attr_remove(_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/call-site.rs b/src/test/ui/proc-macro/auxiliary/call-site.rs new file mode 100644 index 000000000..e64a5a343 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/call-site.rs @@ -0,0 +1,27 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn check(input: TokenStream) -> TokenStream { + // Parsed `x2` can refer to `x2` from `input` + let parsed1: TokenStream = "let x3 = x2;".parse().unwrap(); + // `x3` parsed from one string can refer to `x3` parsed from another string. + let parsed2: TokenStream = "let x4 = x3;".parse().unwrap(); + // Manually assembled `x4` can refer to parsed `x4`. + let manual: Vec<TokenTree> = vec![ + Ident::new("let", Span::call_site()).into(), + Ident::new("x5", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Ident::new("x4", Span::call_site()).into(), + Punct::new(';', Spacing::Alone).into(), + ]; + input.into_iter().chain(parsed1.into_iter()) + .chain(parsed2.into_iter()) + .chain(manual.into_iter()) + .collect() +} diff --git a/src/test/ui/proc-macro/auxiliary/cond_plugin.rs b/src/test/ui/proc-macro/auxiliary/cond_plugin.rs new file mode 100644 index 000000000..8d3c4ec23 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/cond_plugin.rs @@ -0,0 +1,38 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn cond(input: TokenStream) -> TokenStream { + let mut conds = Vec::new(); + let mut input = input.into_iter().peekable(); + while let Some(tree) = input.next() { + let cond = match tree { + TokenTree::Group(tt) => tt.stream(), + _ => panic!("Invalid input"), + }; + let mut cond_trees = cond.clone().into_iter(); + let test = cond_trees.next().expect("Unexpected empty condition in `cond!`"); + let rhs = cond_trees.collect::<TokenStream>(); + if rhs.is_empty() { + panic!("Invalid macro usage in cond: {}", cond); + } + let is_else = match test { + TokenTree::Ident(ref word) => &*word.to_string() == "else", + _ => false, + }; + conds.push(if is_else || input.peek().is_none() { + quote!({ $rhs }) + } else { + quote!(if $test { $rhs } else) + }); + } + + conds.into_iter().flat_map(|x| x.into_iter()).collect() +} diff --git a/src/test/ui/proc-macro/auxiliary/count_compound_ops.rs b/src/test/ui/proc-macro/auxiliary/count_compound_ops.rs new file mode 100644 index 000000000..3a656d648 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/count_compound_ops.rs @@ -0,0 +1,32 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Spacing, Literal, quote}; + +#[proc_macro] +pub fn count_compound_ops(input: TokenStream) -> TokenStream { + assert_eq!(count_compound_ops_helper(quote!(++ (&&) 4@a)), 3); + let l = Literal::u32_suffixed(count_compound_ops_helper(input)); + TokenTree::from(l).into() +} + +fn count_compound_ops_helper(input: TokenStream) -> u32 { + let mut count = 0; + for token in input { + match &token { + TokenTree::Punct(tt) if tt.spacing() == Spacing::Alone => { + count += 1; + } + TokenTree::Group(tt) => { + count += count_compound_ops_helper(tt.stream()); + } + _ => {} + } + } + count +} diff --git a/src/test/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs b/src/test/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs new file mode 100644 index 000000000..41f73f596 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo)] +pub fn foo(a: TokenStream) -> TokenStream { + "".parse().unwrap() +} + +#[proc_macro_derive(Bar, attributes(custom))] +pub fn bar(a: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/custom-quote.rs b/src/test/ui/proc-macro/auxiliary/custom-quote.rs new file mode 100644 index 000000000..3b7811748 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/custom-quote.rs @@ -0,0 +1,32 @@ +// force-host +// no-prefer-dynamic +// ignore-tidy-linelength + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use std::iter::FromIterator; +use std::str::FromStr; +use proc_macro::*; + +#[proc_macro] +pub fn custom_quote(input: TokenStream) -> TokenStream { + let mut tokens: Vec<_> = input.into_iter().collect(); + assert_eq!(tokens.len(), 1, "Unexpected input: {:?}", tokens); + match tokens.pop() { + Some(TokenTree::Ident(ident)) => { + assert_eq!(ident.to_string(), "my_ident"); + + let proc_macro_crate = TokenStream::from_str("::proc_macro").unwrap(); + let quoted_span = proc_macro::quote_span(proc_macro_crate, ident.span()); + let prefix = TokenStream::from_str(r#"let mut ident = proc_macro::Ident::new("my_ident", proc_macro::Span::call_site());"#).unwrap(); + let set_span_method = TokenStream::from_str("ident.set_span").unwrap(); + let set_span_arg = TokenStream::from(TokenTree::Group(Group::new(Delimiter::Parenthesis, quoted_span))); + let suffix = TokenStream::from_str(";proc_macro::TokenStream::from(proc_macro::TokenTree::Ident(ident))").unwrap(); + let full_stream = TokenStream::from_iter([prefix, set_span_method, set_span_arg, suffix]); + full_stream + } + _ => unreachable!() + } +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-a.rs b/src/test/ui/proc-macro/auxiliary/derive-a.rs new file mode 100644 index 000000000..79a3864bf --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-a.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(A)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert!(input.contains("struct A ;")); + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-atob.rs b/src/test/ui/proc-macro/auxiliary/derive-atob.rs new file mode 100644 index 000000000..207b7fd32 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-atob.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(AToB)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert_eq!(input, "struct A ;"); + "struct B;".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-attr-cfg.rs b/src/test/ui/proc-macro/auxiliary/derive-attr-cfg.rs new file mode 100644 index 000000000..e7e9634e0 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-attr-cfg.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo, attributes(foo))] +pub fn derive(input: TokenStream) -> TokenStream { + assert!(!input.to_string().contains("#[cfg(any())]")); + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs b/src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs new file mode 100644 index 000000000..641a95f78 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs @@ -0,0 +1,17 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(B, attributes(B, C))] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert!(input.contains("#[B [arbitrary tokens]]")); + assert!(input.contains("struct B {")); + assert!(input.contains("#[C]")); + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-b.rs b/src/test/ui/proc-macro/auxiliary/derive-b.rs new file mode 100644 index 000000000..e7ab6c072 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-b.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(B, attributes(B))] +pub fn derive_b(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-bad.rs b/src/test/ui/proc-macro/auxiliary/derive-bad.rs new file mode 100644 index 000000000..90bb9b1ba --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-bad.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(A)] +pub fn derive_a(_input: TokenStream) -> TokenStream { + "struct A { inner }".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-clona.rs b/src/test/ui/proc-macro/auxiliary/derive-clona.rs new file mode 100644 index 000000000..4a35c9d0d --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-clona.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Clona)] +pub fn derive_clonea(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-ctod.rs b/src/test/ui/proc-macro/auxiliary/derive-ctod.rs new file mode 100644 index 000000000..2efe5a913 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-ctod.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(CToD)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert_eq!(input, "struct C ;"); + "struct D;".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-foo.rs b/src/test/ui/proc-macro/auxiliary/derive-foo.rs new file mode 100644 index 000000000..3ea027d4f --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-foo.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(FooWithLongName)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs new file mode 100644 index 000000000..ab532da29 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs @@ -0,0 +1,2 @@ +#[macro_export] +macro_rules! empty_helper { () => () } diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs new file mode 100644 index 000000000..370a1a279 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive(same_name, attributes(same_name))] +pub fn derive_a(_: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs new file mode 100644 index 000000000..41d3a1846 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive(GenHelperUse)] +pub fn derive_a(_: TokenStream) -> TokenStream { + " + #[empty_helper] + struct Uwu; + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-nothing.rs b/src/test/ui/proc-macro/auxiliary/derive-nothing.rs new file mode 100644 index 000000000..b6d1e133a --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-nothing.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Nothing)] +pub fn nothing(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-same-struct.rs b/src/test/ui/proc-macro/auxiliary/derive-same-struct.rs new file mode 100644 index 000000000..7598d632c --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-same-struct.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(AToB)] +pub fn derive1(input: TokenStream) -> TokenStream { + println!("input1: {:?}", input.to_string()); + assert_eq!(input.to_string(), "struct A ;"); + "#[derive(BToC)] struct B;".parse().unwrap() +} + +#[proc_macro_derive(BToC)] +pub fn derive2(input: TokenStream) -> TokenStream { + assert_eq!(input.to_string(), "struct B ;"); + "struct C;".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-two-attrs.rs b/src/test/ui/proc-macro/auxiliary/derive-two-attrs.rs new file mode 100644 index 000000000..a6f0eec12 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-two-attrs.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_derive(A, attributes(b))] +pub fn foo(_x: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-union.rs b/src/test/ui/proc-macro/auxiliary/derive-union.rs new file mode 100644 index 000000000..05883170c --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-union.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(UnionTest)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert!(input.contains("#[repr(C)]")); + assert!(input.contains("union Test {")); + assert!(input.contains("a : u8,")); + assert!(input.contains("}")); + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs new file mode 100644 index 000000000..eac21b049 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs @@ -0,0 +1,17 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Unstable)] +pub fn derive(_input: TokenStream) -> TokenStream { + + " + #[rustc_foo] + fn foo() {} + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/derive-unstable.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs new file mode 100644 index 000000000..2ccd3f882 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Unstable)] +pub fn derive(_input: TokenStream) -> TokenStream { + + "unsafe fn foo() -> u32 { ::std::intrinsics::abort() }".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs new file mode 100644 index 000000000..bdcdb7922 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs @@ -0,0 +1,22 @@ +pub type S = u8; + +#[macro_export] +macro_rules! external { + () => { + print_bang! { + struct M($crate::S); + } + + #[print_attr] + struct A($crate::S); + + #[derive(Print)] + struct D($crate::S); + }; +} + +#[macro_export] +macro_rules! issue_62325 { () => { + #[print_attr] + struct B(identity!($crate::S)); +}} diff --git a/src/test/ui/proc-macro/auxiliary/double.rs b/src/test/ui/proc-macro/auxiliary/double.rs new file mode 100644 index 000000000..99eb4e375 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/double.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +// Outputs another copy of the struct. Useful for testing the tokens +// seen by the proc_macro. +#[proc_macro_derive(Double)] +pub fn derive(input: TokenStream) -> TokenStream { + quote!(mod foo { $input }) +} diff --git a/src/test/ui/proc-macro/auxiliary/duplicate.rs b/src/test/ui/proc-macro/auxiliary/duplicate.rs new file mode 100644 index 000000000..b8f82b46f --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/duplicate.rs @@ -0,0 +1,32 @@ +// force-host +// no-prefer-dynamic + +#![deny(unused)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream { + let mut new_name = Some(attr.into_iter().nth(0).unwrap()); + let mut encountered_idents = 0; + let input = item.to_string(); + let ret = item + .into_iter() + .map(move |token| match token { + TokenTree::Ident(_) if encountered_idents == 1 => { + encountered_idents += 1; + new_name.take().unwrap() + } + TokenTree::Ident(_) => { + encountered_idents += 1; + token + } + _ => token, + }) + .collect::<TokenStream>(); + let mut input_again = input.parse::<TokenStream>().unwrap(); + input_again.extend(ret); + input_again +} diff --git a/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs b/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs new file mode 100644 index 000000000..27c59b805 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs @@ -0,0 +1,20 @@ +// edition:2015 +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Derive2015)] +pub fn derive_2015(_: TokenStream) -> TokenStream { + " + use import::Path; + + fn check_absolute() { + let x = ::absolute::Path; + } + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/empty-crate.rs b/src/test/ui/proc-macro/auxiliary/empty-crate.rs new file mode 100644 index 000000000..1cf7534b2 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/empty-crate.rs @@ -0,0 +1,5 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(unused_variables)] diff --git a/src/test/ui/proc-macro/auxiliary/expand-expr.rs b/src/test/ui/proc-macro/auxiliary/expand-expr.rs new file mode 100644 index 000000000..5463e79d7 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/expand-expr.rs @@ -0,0 +1,149 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(warnings)] +#![feature(proc_macro_expand, proc_macro_span)] + +extern crate proc_macro; + +use proc_macro::*; +use std::str::FromStr; + +// Flatten the TokenStream, removing any toplevel `Delimiter::None`s for +// comparison. +fn flatten(ts: TokenStream) -> Vec<TokenTree> { + ts.into_iter() + .flat_map(|tt| match &tt { + TokenTree::Group(group) if group.delimiter() == Delimiter::None => { + flatten(group.stream()) + } + _ => vec![tt], + }) + .collect() +} + +// Assert that two TokenStream values are roughly equal to one-another. +fn assert_ts_eq(lhs: &TokenStream, rhs: &TokenStream) { + let ltts = flatten(lhs.clone()); + let rtts = flatten(rhs.clone()); + + if ltts.len() != rtts.len() { + panic!( + "expected the same number of tts ({} == {})\nlhs:\n{:#?}\nrhs:\n{:#?}", + ltts.len(), + rtts.len(), + lhs, + rhs + ) + } + + for (ltt, rtt) in ltts.iter().zip(&rtts) { + match (ltt, rtt) { + (TokenTree::Group(l), TokenTree::Group(r)) => { + assert_eq!( + l.delimiter(), + r.delimiter(), + "expected delimiters to match for {:?} and {:?}", + l, + r + ); + assert_ts_eq(&l.stream(), &r.stream()); + } + (TokenTree::Punct(l), TokenTree::Punct(r)) => assert_eq!( + (l.as_char(), l.spacing()), + (r.as_char(), r.spacing()), + "expected punct to match for {:?} and {:?}", + l, + r + ), + (TokenTree::Ident(l), TokenTree::Ident(r)) => assert_eq!( + l.to_string(), + r.to_string(), + "expected ident to match for {:?} and {:?}", + l, + r + ), + (TokenTree::Literal(l), TokenTree::Literal(r)) => assert_eq!( + l.to_string(), + r.to_string(), + "expected literal to match for {:?} and {:?}", + l, + r + ), + (l, r) => panic!("expected type to match for {:?} and {:?}", l, r), + } + } +} + +#[proc_macro] +pub fn expand_expr_is(input: TokenStream) -> TokenStream { + let mut iter = input.into_iter(); + let mut expected_tts = Vec::new(); + loop { + match iter.next() { + Some(TokenTree::Punct(ref p)) if p.as_char() == ',' => break, + Some(tt) => expected_tts.push(tt), + None => panic!("expected comma"), + } + } + + let expected = expected_tts.into_iter().collect::<TokenStream>(); + let expanded = iter.collect::<TokenStream>().expand_expr().expect("expand_expr failed"); + assert!( + expected.to_string() == expanded.to_string(), + "assert failed\nexpected: `{}`\nexpanded: `{}`", + expected.to_string(), + expanded.to_string() + ); + + // Also compare the raw tts to make sure they line up. + assert_ts_eq(&expected, &expanded); + + TokenStream::new() +} + +#[proc_macro] +pub fn expand_expr_fail(input: TokenStream) -> TokenStream { + match input.expand_expr() { + Ok(ts) => panic!("expand_expr unexpectedly succeeded: `{}`", ts), + Err(_) => TokenStream::new(), + } +} + +#[proc_macro] +pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream { + // Check that the passed in `file!()` invocation and a parsed `file!` + // invocation expand to the same literal. + let input_t = ts.expand_expr().expect("expand_expr failed on macro input").to_string(); + let parse_t = TokenStream::from_str("file!{}") + .unwrap() + .expand_expr() + .expect("expand_expr failed on internal macro") + .to_string(); + assert_eq!(input_t, parse_t); + + // Check that the literal matches `Span::call_site().source_file().path()` + let expect_t = + Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string(); + assert_eq!(input_t, expect_t); + + TokenStream::new() +} + +#[proc_macro] +pub fn recursive_expand(_: TokenStream) -> TokenStream { + // Recursively call until we hit the recursion limit and get an error. + // + // NOTE: This doesn't panic if expansion fails because that'll cause a very + // large number of errors to fill the output. + TokenStream::from_str("recursive_expand!{}") + .unwrap() + .expand_expr() + .unwrap_or(std::iter::once(TokenTree::Literal(Literal::u32_suffixed(0))).collect()) +} + +#[proc_macro] +pub fn echo_pm(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs b/src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs new file mode 100644 index 000000000..d779d57af --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(warnings)] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(A)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert!(input.contains("struct A ;")); + r#" + impl A { + fn a(&self) { + panic!("hello"); + } + } + "#.parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/external-crate-var.rs b/src/test/ui/proc-macro/auxiliary/external-crate-var.rs new file mode 100644 index 000000000..4319e9212 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/external-crate-var.rs @@ -0,0 +1,40 @@ +pub struct ExternFoo; + +pub trait ExternTrait { + const CONST: u32; + type Assoc; +} + +impl ExternTrait for ExternFoo { + const CONST: u32 = 0; + type Assoc = ExternFoo; +} + +#[macro_export] +macro_rules! external { () => { + mod bar { + #[derive(Double)] + struct Bar($crate::ExternFoo); + } + + mod qself { + #[derive(Double)] + struct QSelf(<$crate::ExternFoo as $crate::ExternTrait>::Assoc); + } + + mod qself_recurse { + #[derive(Double)] + struct QSelfRecurse(< + <$crate::ExternFoo as $crate::ExternTrait>::Assoc + as $crate::ExternTrait>::Assoc + ); + } + + mod qself_in_const { + #[derive(Double)] + #[repr(u32)] + enum QSelfInConst { + Variant = <$crate::ExternFoo as $crate::ExternTrait>::CONST, + } + } +} } diff --git a/src/test/ui/proc-macro/auxiliary/first-second.rs b/src/test/ui/proc-macro/auxiliary/first-second.rs new file mode 100644 index 000000000..6331608fb --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/first-second.rs @@ -0,0 +1,20 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Group, Delimiter}; + +#[proc_macro_attribute] +pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream { + let tokens: TokenStream = "#[derive(Second)]".parse().unwrap(); + let wrapped = TokenTree::Group(Group::new(Delimiter::None, item.into_iter().collect())); + tokens.into_iter().chain(std::iter::once(wrapped)).collect() +} + +#[proc_macro_derive(Second)] +pub fn second(item: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/gen-lifetime-token.rs b/src/test/ui/proc-macro/auxiliary/gen-lifetime-token.rs new file mode 100644 index 000000000..d1a1c584f --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/gen-lifetime-token.rs @@ -0,0 +1,25 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn bar(_input: TokenStream) -> TokenStream { + let mut ret = Vec::<TokenTree>::new(); + ret.push(Ident::new("static", Span::call_site()).into()); + ret.push(Ident::new("FOO", Span::call_site()).into()); + ret.push(Punct::new(':', Spacing::Alone).into()); + ret.push(Punct::new('&', Spacing::Alone).into()); + ret.push(Punct::new('\'', Spacing::Joint).into()); + ret.push(Ident::new("static", Span::call_site()).into()); + ret.push(Ident::new("i32", Span::call_site()).into()); + ret.push(Punct::new('=', Spacing::Alone).into()); + ret.push(Punct::new('&', Spacing::Alone).into()); + ret.push(Literal::i32_unsuffixed(1).into()); + ret.push(Punct::new(';', Spacing::Alone).into()); + ret.into_iter().collect() +} diff --git a/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs new file mode 100644 index 000000000..548fefe76 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs @@ -0,0 +1,23 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn gen_macro_rules(_: TokenStream) -> TokenStream { + " + macro_rules! generated {() => { + struct ItemDef; + let local_def = 0; + + ItemUse; // OK + local_use; // ERROR + break 'label_use; // ERROR + + type DollarCrate = $crate::ItemUse; // OK + }} + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs new file mode 100644 index 000000000..d4b67d6b0 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(repro)] +pub fn proc_macro_hack_expr(_input: TokenStream) -> TokenStream { + "macro_rules! m {()=>{}}".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs b/src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs new file mode 100644 index 000000000..3f3e12eed --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn dollar_ident(input: TokenStream) -> TokenStream { + let black_hole = input.into_iter().next().unwrap(); + quote! { + $black_hole!($$var); + } +} diff --git a/src/test/ui/proc-macro/auxiliary/generate-mod.rs b/src/test/ui/proc-macro/auxiliary/generate-mod.rs new file mode 100644 index 000000000..e950f7d62 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/generate-mod.rs @@ -0,0 +1,58 @@ +// run-pass +// force-host +// no-prefer-dynamic +// ignore-pass + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn check(_: TokenStream) -> TokenStream { + " + type Alias = FromOutside; // OK + struct Outer; + mod inner { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = Outer; // `Outer` shouldn't be available from here + } + ".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn check_attr(_: TokenStream, _: TokenStream) -> TokenStream { + " + type AliasAttr = FromOutside; // OK + struct OuterAttr; + mod inner_attr { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = OuterAttr; // `OuterAttr` shouldn't be available from here + } + ".parse().unwrap() +} + +#[proc_macro_derive(CheckDerive)] +pub fn check_derive(_: TokenStream) -> TokenStream { + " + type AliasDerive = FromOutside; // OK + struct OuterDerive; + mod inner_derive { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = OuterDerive; // `OuterDerive` shouldn't be available from here + } + ".parse().unwrap() +} + +#[proc_macro_derive(CheckDeriveLint)] +pub fn check_derive_lint(_: TokenStream) -> TokenStream { + " + type AliasDeriveLint = FromOutside; // OK + struct OuterDeriveLint; + #[allow(proc_macro_derive_resolution_fallback)] + mod inner_derive_lint { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = OuterDeriveLint; // `OuterDeriveLint` shouldn't be available from here + } + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/hygiene_example.rs b/src/test/ui/proc-macro/auxiliary/hygiene_example.rs new file mode 100644 index 000000000..f7e7e0b57 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/hygiene_example.rs @@ -0,0 +1,7 @@ +extern crate hygiene_example_codegen; + +pub use hygiene_example_codegen::hello; + +pub fn print(string: &str) { + println!("{}", string); +} diff --git a/src/test/ui/proc-macro/auxiliary/hygiene_example_codegen.rs b/src/test/ui/proc-macro/auxiliary/hygiene_example_codegen.rs new file mode 100644 index 000000000..2bd4d3336 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/hygiene_example_codegen.rs @@ -0,0 +1,27 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro as proc_macro_renamed; // This does not break `quote!` + +use proc_macro_renamed::{TokenStream, quote}; + +#[proc_macro] +pub fn hello(input: TokenStream) -> TokenStream { + quote!(hello_helper!($input)) + //^ `hello_helper!` always resolves to the following proc macro, + //| no matter where `hello!` is used. +} + +#[proc_macro] +pub fn hello_helper(input: TokenStream) -> TokenStream { + quote! { + extern crate hygiene_example; // This is never a conflict error + let string = format!("hello {}", $input); + //^ `format!` always resolves to the prelude macro, + //| even if a different `format!` is in scope where `hello!` is used. + hygiene_example::print(&string) + } +} diff --git a/src/test/ui/proc-macro/auxiliary/included-file.txt b/src/test/ui/proc-macro/auxiliary/included-file.txt new file mode 100644 index 000000000..b4720047d --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/included-file.txt @@ -0,0 +1 @@ +Included file contents diff --git a/src/test/ui/proc-macro/auxiliary/invalid-punct-ident.rs b/src/test/ui/proc-macro/auxiliary/invalid-punct-ident.rs new file mode 100644 index 000000000..518dfd0d6 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/invalid-punct-ident.rs @@ -0,0 +1,28 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_raw_ident)] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn invalid_punct(_: TokenStream) -> TokenStream { + TokenTree::from(Punct::new('`', Spacing::Alone)).into() +} + +#[proc_macro] +pub fn invalid_ident(_: TokenStream) -> TokenStream { + TokenTree::from(Ident::new("*", Span::call_site())).into() +} + +#[proc_macro] +pub fn invalid_raw_ident(_: TokenStream) -> TokenStream { + TokenTree::from(Ident::new_raw("self", Span::call_site())).into() +} + +#[proc_macro] +pub fn lexer_failure(_: TokenStream) -> TokenStream { + "a b ) c".parse().expect("parsing failed without panic") +} diff --git a/src/test/ui/proc-macro/auxiliary/is-available.rs b/src/test/ui/proc-macro/auxiliary/is-available.rs new file mode 100644 index 000000000..03f5265e3 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/is-available.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Literal, TokenStream, TokenTree}; + +#[proc_macro] +pub fn from_inside_proc_macro(_input: TokenStream) -> TokenStream { + proc_macro::is_available().to_string().parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-38586.rs b/src/test/ui/proc-macro/auxiliary/issue-38586.rs new file mode 100644 index 000000000..f3a19081c --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-38586.rs @@ -0,0 +1,11 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +#[proc_macro_derive(A)] +pub fn derive_a(_: proc_macro::TokenStream) -> proc_macro::TokenStream { + "fn f() { println!(\"{}\", foo); }".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-39889.rs b/src/test/ui/proc-macro/auxiliary/issue-39889.rs new file mode 100644 index 000000000..e7af66da7 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-39889.rs @@ -0,0 +1,17 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(Issue39889)] +pub fn f(_input: TokenStream) -> TokenStream { + let rules = r#" + macro_rules! id { + ($($tt:tt)*) => { $($tt)* }; + } + "#; + rules.parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-42708.rs b/src/test/ui/proc-macro/auxiliary/issue-42708.rs new file mode 100644 index 000000000..dae05204b --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-42708.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Test)] +pub fn derive(_input: TokenStream) -> TokenStream { + "fn f(s: S) { s.x }".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn attr_test(_attr: TokenStream, input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-50061.rs b/src/test/ui/proc-macro/auxiliary/issue-50061.rs new file mode 100644 index 000000000..f5fe8cabb --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-50061.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 check(_a: TokenStream, b: TokenStream) -> TokenStream { + b.into_iter().collect() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-50493.rs b/src/test/ui/proc-macro/auxiliary/issue-50493.rs new file mode 100644 index 000000000..f72024948 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-50493.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(Derive)] +pub fn derive(_: TokenStream) -> TokenStream { + let code = " + fn one(r: Restricted) { + r.field; + } + fn two(r: Restricted) { + r.field; + } + "; + + code.parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-59191.rs b/src/test/ui/proc-macro/auxiliary/issue-59191.rs new file mode 100644 index 000000000..d9ee77067 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-59191.rs @@ -0,0 +1,16 @@ +// edition:2018 +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn no_main(_attrs: TokenStream, _input: TokenStream) -> TokenStream { + let new_krate = r#" + fn main() {} + "#; + new_krate.parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-66286.rs b/src/test/ui/proc-macro/auxiliary/issue-66286.rs new file mode 100644 index 000000000..6217f1c7e --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-66286.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn vec_ice(_attr: TokenStream, input: TokenStream) -> TokenStream { + // This redundant convert is necessary to reproduce ICE. + input.into_iter().collect() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-75801.rs b/src/test/ui/proc-macro/auxiliary/issue-75801.rs new file mode 100644 index 000000000..d6c031d7d --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-75801.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn foo(_args: TokenStream, item: TokenStream) -> TokenStream { + item +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-79242.rs b/src/test/ui/proc-macro/auxiliary/issue-79242.rs new file mode 100644 index 000000000..e586980f0 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-79242.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn dummy(input: TokenStream) -> TokenStream { + // Iterate to force internal conversion of nonterminals + // to `proc_macro` structs + for _ in input {} + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-79825.rs b/src/test/ui/proc-macro/auxiliary/issue-79825.rs new file mode 100644 index 000000000..930891b1d --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-79825.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn assert_input(args: TokenStream, input: TokenStream) -> TokenStream { + assert_eq!(input.to_string(), "trait Alias = Sized ;"); + assert!(args.is_empty()); + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-83510.rs b/src/test/ui/proc-macro/auxiliary/issue-83510.rs new file mode 100644 index 000000000..1d6ef3914 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-83510.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn dance_like_you_want_to_ice(_: TokenStream) -> TokenStream { + r#" + impl Foo { + type Bar = Box<()> + Baz; + } + "# + .parse() + .unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-91800-macro.rs b/src/test/ui/proc-macro/auxiliary/issue-91800-macro.rs new file mode 100644 index 000000000..958a8bed9 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-91800-macro.rs @@ -0,0 +1,26 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +fn compile_error() -> TokenStream { + r#"compile_error!("")"#.parse().unwrap() +} + +#[proc_macro_derive(MyTrait)] +pub fn derive(input: TokenStream) -> TokenStream { + compile_error() +} +#[proc_macro_attribute] +pub fn attribute_macro(_attr: TokenStream, mut input: TokenStream) -> TokenStream { + input.extend(compile_error()); + input +} +#[proc_macro] +pub fn fn_macro(_item: TokenStream) -> TokenStream { + compile_error() +} diff --git a/src/test/ui/proc-macro/auxiliary/lifetimes-rpass.rs b/src/test/ui/proc-macro/auxiliary/lifetimes-rpass.rs new file mode 100644 index 000000000..4e5d22e6e --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/lifetimes-rpass.rs @@ -0,0 +1,26 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn lifetimes_bang(input: TokenStream) -> TokenStream { + // Roundtrip through token trees + input.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn lifetimes_attr(_: TokenStream, input: TokenStream) -> TokenStream { + // Roundtrip through AST + input +} + +#[proc_macro_derive(Lifetimes)] +pub fn lifetimes_derive(input: TokenStream) -> TokenStream { + // Roundtrip through a string + format!("mod m {{ {} }}", input).parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/lifetimes.rs b/src/test/ui/proc-macro/auxiliary/lifetimes.rs new file mode 100644 index 000000000..212164dd2 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/lifetimes.rs @@ -0,0 +1,20 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn single_quote_alone(_: TokenStream) -> TokenStream { + // `&'a u8`, but the `'` token is not joint + let trees: Vec<TokenTree> = vec![ + Punct::new('&', Spacing::Alone).into(), + Punct::new('\'', Spacing::Alone).into(), + Ident::new("a", Span::call_site()).into(), + Ident::new("u8", Span::call_site()).into(), + ]; + trees.into_iter().collect() +} diff --git a/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs b/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs new file mode 100644 index 000000000..c72306c3d --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs @@ -0,0 +1,89 @@ +// force-host +// no-prefer-dynamic + +// These are tests for syntax that is accepted by the Rust parser but +// unconditionally rejected semantically after macro expansion. Attribute macros +// are permitted to accept such syntax as long as they replace it with something +// that makes sense to Rust. +// +// We also inspect some of the spans to verify the syntax is not triggering the +// lossy string reparse hack (https://github.com/rust-lang/rust/issues/43081). + +#![crate_type = "proc-macro"] +#![feature(proc_macro_span)] + +extern crate proc_macro; +use proc_macro::{token_stream, Delimiter, TokenStream, TokenTree}; +use std::path::Component; + +// unsafe mod m { +// pub unsafe mod inner; +// } +#[proc_macro_attribute] +pub fn expect_unsafe_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "unsafe"); + expect(tokens, "mod"); + expect(tokens, "m"); + let tokens = &mut expect_brace(tokens); + expect(tokens, "pub"); + expect(tokens, "unsafe"); + expect(tokens, "mod"); + let ident = expect(tokens, "inner"); + expect(tokens, ";"); + check_useful_span(ident, "unsafe-mod.rs"); + TokenStream::new() +} + +// unsafe extern { +// type T; +// } +#[proc_macro_attribute] +pub fn expect_unsafe_foreign_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "unsafe"); + expect(tokens, "extern"); + let tokens = &mut expect_brace(tokens); + expect(tokens, "type"); + let ident = expect(tokens, "T"); + expect(tokens, ";"); + check_useful_span(ident, "unsafe-foreign-mod.rs"); + TokenStream::new() +} + +// unsafe extern "C++" {} +#[proc_macro_attribute] +pub fn expect_unsafe_extern_cpp_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "unsafe"); + expect(tokens, "extern"); + let abi = expect(tokens, "\"C++\""); + expect_brace(tokens); + check_useful_span(abi, "unsafe-foreign-mod.rs"); + TokenStream::new() +} + +fn expect(tokens: &mut token_stream::IntoIter, expected: &str) -> TokenTree { + match tokens.next() { + Some(token) if token.to_string() == expected => token, + wrong => panic!("unexpected token: {:?}, expected `{}`", wrong, expected), + } +} + +fn expect_brace(tokens: &mut token_stream::IntoIter) -> token_stream::IntoIter { + match tokens.next() { + Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => { + group.stream().into_iter() + } + wrong => panic!("unexpected token: {:?}, expected `{{`", wrong), + } +} + +fn check_useful_span(token: TokenTree, expected_filename: &str) { + let span = token.span(); + assert!(span.start().column < span.end().column); + + let source_path = span.source_file().path(); + let filename = source_path.components().last().unwrap(); + assert_eq!(filename, Component::Normal(expected_filename.as_ref())); +} diff --git a/src/test/ui/proc-macro/auxiliary/make-macro.rs b/src/test/ui/proc-macro/auxiliary/make-macro.rs new file mode 100644 index 000000000..3c851b6de --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/make-macro.rs @@ -0,0 +1,18 @@ +// force-host + +#[macro_export] +macro_rules! make_it { + ($name:ident) => { + #[proc_macro] + pub fn $name(input: TokenStream) -> TokenStream { + println!("Def site: {:?}", Span::def_site()); + println!("Input: {:?}", input); + let new: TokenStream = input.into_iter().map(|mut t| { + t.set_span(Span::def_site()); + t + }).collect(); + println!("Respanned: {:?}", new); + new + } + }; +} diff --git a/src/test/ui/proc-macro/auxiliary/meta-delim.rs b/src/test/ui/proc-macro/auxiliary/meta-delim.rs new file mode 100644 index 000000000..54e3d7857 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/meta-delim.rs @@ -0,0 +1,12 @@ +macro_rules! produce_it { + ($dollar_one:tt $foo:ident $my_name:ident) => { + #[macro_export] + macro_rules! meta_delim { + ($dollar_one ($dollar_one $my_name:ident)*) => { + stringify!($dollar_one ($dollar_one $my_name)*) + } + } + } +} + +produce_it!($my_name name); diff --git a/src/test/ui/proc-macro/auxiliary/meta-macro.rs b/src/test/ui/proc-macro/auxiliary/meta-macro.rs new file mode 100644 index 000000000..0a9b9887d --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/meta-macro.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic +// edition:2018 + +#![feature(proc_macro_def_site)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +extern crate make_macro; +use proc_macro::{TokenStream, Span}; + +make_macro::make_it!(print_def_site); + +#[proc_macro] +pub fn dummy(input: TokenStream) -> TokenStream { input } diff --git a/src/test/ui/proc-macro/auxiliary/mixed-site-span.rs b/src/test/ui/proc-macro/auxiliary/mixed-site-span.rs new file mode 100644 index 000000000..c2a498700 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/mixed-site-span.rs @@ -0,0 +1,40 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn proc_macro_rules(input: TokenStream) -> TokenStream { + if input.is_empty() { + let id = |s| TokenTree::from(Ident::new(s, Span::mixed_site())); + let item_def = id("ItemDef"); + let local_def = id("local_def"); + let item_use = id("ItemUse"); + let local_use = id("local_use"); + let mut single_quote = Punct::new('\'', Spacing::Joint); + single_quote.set_span(Span::mixed_site()); + let label_use: TokenStream = [ + TokenTree::from(single_quote), + id("label_use"), + ].iter().cloned().collect(); + quote!( + struct $item_def; + let $local_def = 0; + + $item_use; // OK + $local_use; // ERROR + break $label_use; // ERROR + ) + } else { + let mut dollar_crate = input.into_iter().next().unwrap(); + dollar_crate.set_span(Span::mixed_site()); + quote!( + type A = $dollar_crate::ItemUse; + ) + } +} diff --git a/src/test/ui/proc-macro/auxiliary/modify-ast.rs b/src/test/ui/proc-macro/auxiliary/modify-ast.rs new file mode 100644 index 000000000..cc582c152 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/modify-ast.rs @@ -0,0 +1,47 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn assert1(_a: TokenStream, b: TokenStream) -> TokenStream { + assert_eq(b.clone(), "pub fn foo() {}".parse().unwrap()); + b +} + +#[proc_macro_derive(Foo, attributes(foo))] +pub fn assert2(a: TokenStream) -> TokenStream { + assert_eq(a, "pub struct MyStructc { _a: i32, }".parse().unwrap()); + TokenStream::new() +} + +fn assert_eq(a: TokenStream, b: TokenStream) { + let mut a = a.into_iter(); + let mut b = b.into_iter(); + for (a, b) in a.by_ref().zip(&mut b) { + match (a, b) { + (TokenTree::Group(a), TokenTree::Group(b)) => { + assert_eq!(a.delimiter(), b.delimiter()); + assert_eq(a.stream(), b.stream()); + } + (TokenTree::Punct(a), TokenTree::Punct(b)) => { + assert_eq!(a.as_char(), b.as_char()); + assert_eq!(a.spacing(), b.spacing()); + } + (TokenTree::Literal(a), TokenTree::Literal(b)) => { + assert_eq!(a.to_string(), b.to_string()); + } + (TokenTree::Ident(a), TokenTree::Ident(b)) => { + assert_eq!(a.to_string(), b.to_string()); + } + (a, b) => panic!("{:?} != {:?}", a, b), + } + } + + assert!(a.next().is_none()); + assert!(b.next().is_none()); +} diff --git a/src/test/ui/proc-macro/auxiliary/multiple-derives.rs b/src/test/ui/proc-macro/auxiliary/multiple-derives.rs new file mode 100644 index 000000000..e3f6607b2 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/multiple-derives.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +macro_rules! make_derives { + ($($name:ident),*) => { + $( + #[proc_macro_derive($name)] + pub fn $name(input: TokenStream) -> TokenStream { + println!("Derive {}: {}", stringify!($name), input); + TokenStream::new() + } + )* + } +} + +make_derives!(First, Second, Third, Fourth, Fifth); diff --git a/src/test/ui/proc-macro/auxiliary/multispan.rs b/src/test/ui/proc-macro/auxiliary/multispan.rs new file mode 100644 index 000000000..c05d15643 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/multispan.rs @@ -0,0 +1,37 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + let mut hi_spans = vec![]; + for tree in input { + if let TokenTree::Ident(ref ident) = tree { + if ident.to_string() == "hi" { + hi_spans.push(ident.span()); + } + } + } + + if !hi_spans.is_empty() { + return Err(Span::def_site() + .error("hello to you, too!") + .span_note(hi_spans, "found these 'hi's")); + } + + Ok(()) +} + +#[proc_macro] +pub fn hello(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + } + + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/negative-token.rs b/src/test/ui/proc-macro/auxiliary/negative-token.rs new file mode 100644 index 000000000..8b89f2e37 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/negative-token.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn neg_one(_input: TokenStream) -> TokenStream { + TokenTree::Literal(Literal::i32_suffixed(-1)).into() +} + +#[proc_macro] +pub fn neg_one_float(_input: TokenStream) -> TokenStream { + TokenTree::Literal(Literal::f32_suffixed(-1.0)).into() +} diff --git a/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs new file mode 100644 index 000000000..27676a5cb --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs @@ -0,0 +1,16 @@ +pub struct FirstStruct; + +#[macro_export] +macro_rules! outer_macro { + ($name:ident, $attr_struct_name:ident) => { + #[macro_export] + macro_rules! inner_macro { + ($bang_macro:ident, $attr_macro:ident) => { + $bang_macro!($name); + #[$attr_macro] struct $attr_struct_name {} + } + } + } +} + +outer_macro!(FirstStruct, FirstAttrStruct); diff --git a/src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs b/src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs new file mode 100644 index 000000000..ea5ff4665 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs @@ -0,0 +1,25 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; +use proc_macro::{TokenStream, quote}; + +#[proc_macro_attribute] +pub fn first_attr(_: TokenStream, input: TokenStream) -> TokenStream { + let recollected: TokenStream = input.into_iter().collect(); + println!("First recollected: {:#?}", recollected); + quote! { + #[second_attr] + $recollected + } +} + +#[proc_macro_attribute] +pub fn second_attr(_: TokenStream, input: TokenStream) -> TokenStream { + let recollected: TokenStream = input.into_iter().collect(); + println!("Second recollected: {:#?}", recollected); + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/not-joint.rs b/src/test/ui/proc-macro/auxiliary/not-joint.rs new file mode 100644 index 000000000..e6c09f762 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/not-joint.rs @@ -0,0 +1,30 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn tokens(input: TokenStream) -> TokenStream { + assert_nothing_joint(input); + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn nothing(_: TokenStream, input: TokenStream) -> TokenStream { + assert_nothing_joint(input); + TokenStream::new() +} + +fn assert_nothing_joint(s: TokenStream) { + for tt in s { + match tt { + TokenTree::Group(g) => assert_nothing_joint(g.stream()), + TokenTree::Punct(p) => assert_eq!(p.spacing(), Spacing::Alone), + _ => {} + } + } +} diff --git a/src/test/ui/proc-macro/auxiliary/parent-source-spans.rs b/src/test/ui/proc-macro/auxiliary/parent-source-spans.rs new file mode 100644 index 000000000..594f10883 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/parent-source-spans.rs @@ -0,0 +1,43 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_diagnostic, proc_macro_span)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span}; + +fn lit_span(tt: TokenTree) -> (Span, String) { + match tt { + TokenTree::Literal(..) | + TokenTree::Group(..) => (tt.span(), tt.to_string().trim().into()), + _ => panic!("expected a literal in token tree, got: {:?}", tt) + } +} + +#[proc_macro] +pub fn parent_source_spans(input: TokenStream) -> TokenStream { + let mut tokens = input.into_iter(); + let (sp1, str1) = lit_span(tokens.next().expect("first string")); + let _ = tokens.next(); + let (sp2, str2) = lit_span(tokens.next().expect("second string")); + + sp1.error(format!("first final: {}", str1)).emit(); + sp2.error(format!("second final: {}", str2)).emit(); + + if let (Some(p1), Some(p2)) = (sp1.parent(), sp2.parent()) { + p1.error(format!("first parent: {}", str1)).emit(); + p2.error(format!("second parent: {}", str2)).emit(); + + if let (Some(gp1), Some(gp2)) = (p1.parent(), p2.parent()) { + gp1.error(format!("first grandparent: {}", str1)).emit(); + gp2.error(format!("second grandparent: {}", str2)).emit(); + } + } + + sp1.source().error(format!("first source: {}", str1)).emit(); + sp2.source().error(format!("second source: {}", str2)).emit(); + + "ok".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs b/src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs new file mode 100644 index 000000000..fc15bb9c5 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, Ident, Span}; + +#[proc_macro] +pub fn panic_in_libproc_macro(_: TokenStream) -> TokenStream { + Ident::new("", Span::call_site()); + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/raw-ident.rs b/src/test/ui/proc-macro/auxiliary/raw-ident.rs new file mode 100644 index 000000000..9daee21aa --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/raw-ident.rs @@ -0,0 +1,35 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, TokenTree, Ident, Punct, Spacing, Span}; + +#[proc_macro] +pub fn make_struct(input: TokenStream) -> TokenStream { + match input.into_iter().next().unwrap() { + TokenTree::Ident(ident) => { + vec![ + TokenTree::Ident(Ident::new("struct", Span::call_site())), + TokenTree::Ident(Ident::new_raw(&ident.to_string(), Span::call_site())), + TokenTree::Punct(Punct::new(';', Spacing::Alone)) + ].into_iter().collect() + } + _ => panic!() + } +} + +#[proc_macro] +pub fn make_bad_struct(input: TokenStream) -> TokenStream { + match input.into_iter().next().unwrap() { + TokenTree::Ident(ident) => { + vec![ + TokenTree::Ident(Ident::new_raw("struct", Span::call_site())), + TokenTree::Ident(Ident::new(&ident.to_string(), Span::call_site())), + TokenTree::Punct(Punct::new(';', Spacing::Alone)) + ].into_iter().collect() + } + _ => panic!() + } +} diff --git a/src/test/ui/proc-macro/auxiliary/recollect.rs b/src/test/ui/proc-macro/auxiliary/recollect.rs new file mode 100644 index 000000000..d4494a5af --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/recollect.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn recollect(tokens: TokenStream) -> TokenStream { + tokens.into_iter().collect() +} diff --git a/src/test/ui/proc-macro/auxiliary/resolved-located-at.rs b/src/test/ui/proc-macro/auxiliary/resolved-located-at.rs new file mode 100644 index 000000000..db660824f --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/resolved-located-at.rs @@ -0,0 +1,31 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_def_site)] +#![feature(proc_macro_diagnostic)] +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn resolve_located_at(input: TokenStream) -> TokenStream { + match &*input.into_iter().collect::<Vec<_>>() { + [a, b, ..] => { + // The error is reported at input `a`. + let mut diag = Diagnostic::new(Level::Error, "expected error"); + diag.set_spans(Span::def_site().located_at(a.span())); + diag.emit(); + + // Resolves to `struct S;` at def site, but the error is reported at input `b`. + let s = TokenTree::Ident(Ident::new("S", b.span().resolved_at(Span::def_site()))); + quote!({ + struct S; + + $s + }) + } + _ => panic!("unexpected input"), + } +} diff --git a/src/test/ui/proc-macro/auxiliary/span-api-tests.rs b/src/test/ui/proc-macro/auxiliary/span-api-tests.rs new file mode 100644 index 000000000..ad1e770a4 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/span-api-tests.rs @@ -0,0 +1,45 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_span)] + +extern crate proc_macro; + +use proc_macro::*; + +// Re-emits the input tokens by parsing them from strings +#[proc_macro] +pub fn reemit(input: TokenStream) -> TokenStream { + input.to_string().parse().unwrap() +} + +#[proc_macro] +pub fn assert_fake_source_file(input: TokenStream) -> TokenStream { + for tk in input { + let source_file = tk.span().source_file(); + assert!(!source_file.is_real(), "Source file is real: {:?}", source_file); + } + + "".parse().unwrap() +} + +#[proc_macro] +pub fn assert_source_file(input: TokenStream) -> TokenStream { + for tk in input { + let source_file = tk.span().source_file(); + assert!(source_file.is_real(), "Source file is not real: {:?}", source_file); + } + + "".parse().unwrap() +} + +#[proc_macro] +pub fn macro_stringify(input: TokenStream) -> TokenStream { + let mut tokens = input.into_iter(); + let first_span = tokens.next().expect("first token").span(); + let last_span = tokens.last().map(|x| x.span()).unwrap_or(first_span); + let span = first_span.join(last_span).expect("joined span"); + let src = span.source_text().expect("source_text"); + TokenTree::Literal(Literal::string(&src)).into() +} diff --git a/src/test/ui/proc-macro/auxiliary/span-from-proc-macro.rs b/src/test/ui/proc-macro/auxiliary/span-from-proc-macro.rs new file mode 100644 index 000000000..49292acfe --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/span-from-proc-macro.rs @@ -0,0 +1,49 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![feature(proc_macro_internals)] // FIXME - this shouldn't be necessary +#![crate_type = "proc-macro"] + +extern crate proc_macro; +extern crate custom_quote; + +use proc_macro::{quote, TokenStream}; + +macro_rules! expand_to_quote { + () => { + quote! { + let bang_error: bool = 25; + } + } +} + +#[proc_macro] +pub fn error_from_bang(_input: TokenStream) -> TokenStream { + expand_to_quote!() +} + +#[proc_macro] +pub fn other_error_from_bang(_input: TokenStream) -> TokenStream { + custom_quote::custom_quote! { + my_ident + } +} + +#[proc_macro_attribute] +pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream { + quote! { + struct AttributeError { + field: MissingType + } + } +} + +#[proc_macro_derive(ErrorFromDerive)] +pub fn error_from_derive(_input: TokenStream) -> TokenStream { + quote! { + enum DeriveError { + Variant(OtherMissingType) + } + } +} diff --git a/src/test/ui/proc-macro/auxiliary/span-test-macros.rs b/src/test/ui/proc-macro/auxiliary/span-test-macros.rs new file mode 100644 index 000000000..9a78f0a89 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/span-test-macros.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! reemit_legacy { + ($($tok:tt)*) => ($($tok)*) +} + +#[macro_export] +macro_rules! say_hello_extern { + ($macname:ident) => ( $macname! { "Hello, world!" }) +} diff --git a/src/test/ui/proc-macro/auxiliary/subspan.rs b/src/test/ui/proc-macro/auxiliary/subspan.rs new file mode 100644 index 000000000..f92adc040 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/subspan.rs @@ -0,0 +1,38 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + if let Some(TokenTree::Literal(lit)) = input.into_iter().next() { + let mut spans = vec![]; + let string = lit.to_string(); + for hi in string.matches("hi") { + let index = hi.as_ptr() as usize - string.as_ptr() as usize; + let subspan = lit.subspan(index..(index + hi.len())).unwrap(); + spans.push(subspan); + } + + if !spans.is_empty() { + Err(Span::call_site().error("found 'hi's").span_note(spans, "here")) + } else { + Ok(()) + } + } else { + Err(Span::call_site().error("invalid input: expected string literal")) + } +} + +#[proc_macro] +pub fn subspan(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + } + + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/test-macros.rs b/src/test/ui/proc-macro/auxiliary/test-macros.rs new file mode 100644 index 000000000..7a46aee46 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/test-macros.rs @@ -0,0 +1,180 @@ +// force-host +// no-prefer-dynamic + +// Proc macros commonly used by tests. +// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros. + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, TokenTree}; + +// Macro that return empty token stream. + +#[proc_macro] +pub fn empty(_: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_derive(Empty, attributes(empty_helper))] +pub fn empty_derive(_: TokenStream) -> TokenStream { + TokenStream::new() +} + +// Macro that panics. + +#[proc_macro] +pub fn panic_bang(_: TokenStream) -> TokenStream { + panic!("panic-bang"); +} + +#[proc_macro_attribute] +pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream { + panic!("panic-attr"); +} + +#[proc_macro_derive(Panic, attributes(panic_helper))] +pub fn panic_derive(_: TokenStream) -> TokenStream { + panic!("panic-derive"); +} + +// Macros that return the input stream. + +#[proc_macro] +pub fn identity(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(Identity, attributes(identity_helper))] +pub fn identity_derive(input: TokenStream) -> TokenStream { + input +} + +// Macros that iterate and re-collect the input stream. + +#[proc_macro] +pub fn recollect(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_derive(Recollect, attributes(recollect_helper))] +pub fn recollect_derive(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +// Macros that print their input in the original and re-collected forms (if they differ). + +fn print_helper(input: TokenStream, kind: &str) -> TokenStream { + print_helper_ext(input, kind, true) +} + +fn deep_recollect(input: TokenStream) -> TokenStream { + input.into_iter().map(|tree| { + match tree { + TokenTree::Group(group) => { + let inner = deep_recollect(group.stream()); + let mut new_group = TokenTree::Group( + proc_macro::Group::new(group.delimiter(), inner) + ); + new_group.set_span(group.span()); + new_group + } + _ => tree, + } + }).collect() +} + +fn print_helper_ext(input: TokenStream, kind: &str, debug: bool) -> TokenStream { + let input_display = format!("{}", input); + let input_debug = format!("{:#?}", input); + let recollected = input.clone().into_iter().collect(); + let recollected_display = format!("{}", recollected); + let recollected_debug = format!("{:#?}", recollected); + + let deep_recollected = deep_recollect(input); + let deep_recollected_display = format!("{}", deep_recollected); + let deep_recollected_debug = format!("{:#?}", deep_recollected); + + + + println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display); + if recollected_display != input_display { + println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display); + } + + if deep_recollected_display != recollected_display { + println!("PRINT-{} DEEP-RE-COLLECTED (DISPLAY): {}", kind, deep_recollected_display); + } + + if debug { + println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug); + if recollected_debug != input_debug { + println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug); + } + if deep_recollected_debug != recollected_debug { + println!("PRINT-{} DEEP-RE-COLLETED (DEBUG): {}", kind, deep_recollected_debug); + } + } + recollected +} + +#[proc_macro] +pub fn print_bang(input: TokenStream) -> TokenStream { + print_helper(input, "BANG") +} + +#[proc_macro] +pub fn print_bang_consume(input: TokenStream) -> TokenStream { + print_helper(input, "BANG"); + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn print_attr(args: TokenStream, input: TokenStream) -> TokenStream { + let debug = match &args.into_iter().collect::<Vec<_>>()[..] { + [TokenTree::Ident(ident)] if ident.to_string() == "nodebug" => false, + _ => true, + }; + print_helper_ext(input, "ATTR", debug) +} + +#[proc_macro_attribute] +pub fn print_attr_args(args: TokenStream, input: TokenStream) -> TokenStream { + print_helper(args, "ATTR_ARGS"); + input +} + +#[proc_macro_attribute] +pub fn print_target_and_args(args: TokenStream, input: TokenStream) -> TokenStream { + print_helper(args, "ATTR_ARGS"); + print_helper(input.clone(), "ATTR"); + input +} + +#[proc_macro_attribute] +pub fn print_target_and_args_consume(args: TokenStream, input: TokenStream) -> TokenStream { + print_helper(args, "ATTR_ARGS"); + print_helper(input.clone(), "ATTR"); + TokenStream::new() +} + +#[proc_macro_derive(Print, attributes(print_helper))] +pub fn print_derive(input: TokenStream) -> TokenStream { + print_helper(input, "DERIVE"); + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/three-equals.rs b/src/test/ui/proc-macro/auxiliary/three-equals.rs new file mode 100644 index 000000000..e740e86e5 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/three-equals.rs @@ -0,0 +1,49 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + let mut count = 0; + let mut last_span = Span::def_site(); + for tree in input { + let span = tree.span(); + if count >= 3 { + return Err(span.error(format!("expected EOF, found `{}`.", tree)) + .span_note(last_span, "last good input was here") + .help("input must be: `===`")) + } + + if let TokenTree::Punct(ref tt) = tree { + if tt.as_char() == '=' { + count += 1; + last_span = span; + continue + } + } + return Err(span.error(format!("expected `=`, found `{}`.", tree))); + } + + if count < 3 { + return Err(Span::def_site() + .error(format!("found {} equal signs, need exactly 3", count)) + .help("input must be: `===`")) + } + + Ok(()) +} + +#[proc_macro] +pub fn three_equals(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + return TokenStream::new(); + } + + "3".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/weird-hygiene.rs b/src/test/ui/proc-macro/auxiliary/weird-hygiene.rs new file mode 100644 index 000000000..338e436df --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/weird-hygiene.rs @@ -0,0 +1,48 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Group}; + +fn find_my_ident(tokens: TokenStream) -> Option<TokenStream> { + for token in tokens { + if let TokenTree::Ident(ident) = &token { + if ident.to_string() == "hidden_ident" { + return Some(vec![token].into_iter().collect()) + } + } else if let TokenTree::Group(g) = token { + if let Some(stream) = find_my_ident(g.stream()) { + return Some(stream) + } + } + } + return None; +} + + +#[proc_macro_derive(WeirdDerive)] +pub fn weird_derive(item: TokenStream) -> TokenStream { + let my_ident = find_my_ident(item).expect("Missing 'my_ident'!"); + let tokens: TokenStream = "call_it!();".parse().unwrap(); + let final_call = tokens.into_iter().map(|tree| { + if let TokenTree::Group(g) = tree { + return Group::new(g.delimiter(), my_ident.clone()).into() + } else { + return tree + } + }).collect(); + final_call +} + +#[proc_macro] +pub fn recollect(item: TokenStream) -> TokenStream { + item.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn recollect_attr(_attr: TokenStream, mut item: TokenStream) -> TokenStream { + item.into_iter().collect() +} diff --git a/src/test/ui/proc-macro/bang-macro.rs b/src/test/ui/proc-macro/bang-macro.rs new file mode 100644 index 000000000..928107913 --- /dev/null +++ b/src/test/ui/proc-macro/bang-macro.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:bang-macro.rs + +extern crate bang_macro; +use bang_macro::rewrite; + +fn main() { + assert_eq!(rewrite!("Hello, world!"), "NOT Hello, world!"); +} diff --git a/src/test/ui/proc-macro/break-token-spans.rs b/src/test/ui/proc-macro/break-token-spans.rs new file mode 100644 index 000000000..59dc3b504 --- /dev/null +++ b/src/test/ui/proc-macro/break-token-spans.rs @@ -0,0 +1,16 @@ +// aux-build:test-macros.rs +// Regression test for issues #68489 and #70987 +// Tests that we properly break tokens in `probably_equal_for_proc_macro` +// See #72306 +// +// Note that the weird spacing in this example is critical +// for testing the issue. + +extern crate test_macros; + +#[test_macros::recollect_attr] +fn repro() { + f :: < Vec < _ > > ( ) ; //~ ERROR cannot find + let a: Option<Option<u8>>= true; //~ ERROR mismatched +} +fn main() {} diff --git a/src/test/ui/proc-macro/break-token-spans.stderr b/src/test/ui/proc-macro/break-token-spans.stderr new file mode 100644 index 000000000..0a0322b8a --- /dev/null +++ b/src/test/ui/proc-macro/break-token-spans.stderr @@ -0,0 +1,21 @@ +error[E0425]: cannot find function `f` in this scope + --> $DIR/break-token-spans.rs:13:5 + | +LL | f :: < Vec < _ > > ( ) ; + | ^ not found in this scope + +error[E0308]: mismatched types + --> $DIR/break-token-spans.rs:14:32 + | +LL | let a: Option<Option<u8>>= true; + | ------------------ ^^^^ expected enum `Option`, found `bool` + | | + | expected due to this + | + = note: expected enum `Option<Option<u8>>` + found type `bool` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/call-deprecated.rs b/src/test/ui/proc-macro/call-deprecated.rs new file mode 100644 index 000000000..b92cc2363 --- /dev/null +++ b/src/test/ui/proc-macro/call-deprecated.rs @@ -0,0 +1,34 @@ +// check-pass +// aux-build:call-deprecated.rs + +extern crate call_deprecated; + +// These first two `#[allow(deprecated)]` attributes +// do nothing, since the AST nodes for `First` and `Second` +// haven't been been assigned a `NodeId`. +// See #63221 for a discussion about how we should +// handle the interaction of 'inert' attributes and +// proc-macro attributes. + +#[allow(deprecated)] +#[call_deprecated::attr] //~ WARN use of deprecated macro +struct First; + +#[allow(deprecated)] +#[call_deprecated::attr_remove] //~ WARN use of deprecated macro +struct Second; + +#[allow(deprecated)] +mod bar { + #[allow(deprecated)] + #[call_deprecated::attr] + struct Third; + + #[allow(deprecated)] + #[call_deprecated::attr_remove] + struct Fourth; +} + + +fn main() { +} diff --git a/src/test/ui/proc-macro/call-deprecated.stderr b/src/test/ui/proc-macro/call-deprecated.stderr new file mode 100644 index 000000000..3506f9a16 --- /dev/null +++ b/src/test/ui/proc-macro/call-deprecated.stderr @@ -0,0 +1,16 @@ +warning: use of deprecated macro `call_deprecated::attr`: test + --> $DIR/call-deprecated.rs:14:3 + | +LL | #[call_deprecated::attr] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated macro `call_deprecated::attr_remove`: test + --> $DIR/call-deprecated.rs:18:3 + | +LL | #[call_deprecated::attr_remove] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/src/test/ui/proc-macro/call-site.rs b/src/test/ui/proc-macro/call-site.rs new file mode 100644 index 000000000..12c77250c --- /dev/null +++ b/src/test/ui/proc-macro/call-site.rs @@ -0,0 +1,10 @@ +// check-pass +// aux-build:call-site.rs + +extern crate call_site; + +fn main() { + let x1 = 10; + call_site::check!(let x2 = x1;); + let x6 = x5; +} diff --git a/src/test/ui/proc-macro/capture-macro-rules-invoke.rs b/src/test/ui/proc-macro/capture-macro-rules-invoke.rs new file mode 100644 index 000000000..de008a370 --- /dev/null +++ b/src/test/ui/proc-macro/capture-macro-rules-invoke.rs @@ -0,0 +1,57 @@ +// aux-build:test-macros.rs +// check-pass +// compile-flags: -Z span-debug + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; +use test_macros::{print_bang, print_bang_consume}; + +macro_rules! test_matchers { + ($expr:expr, $block:block, $stmt:stmt, $ty:ty, $ident:ident, $lifetime:lifetime, + $meta:meta, $path:path, $vis:vis, $tt:tt, $lit:literal) => { + print_bang_consume!($expr, $block, $stmt, $ty, $ident, + $lifetime, $meta, $path, $vis, $tt, $lit) + } +} + +macro_rules! use_expr { + ($expr:expr) => { + print_bang!($expr) + } +} + +macro_rules! use_pat { + ($pat:pat) => { + print_bang!($pat) + } +} + +#[allow(dead_code)] +struct Foo; +impl Foo { + #[allow(dead_code)] + fn use_self(self) { + drop(use_expr!(self)); + test_matchers!( + 1 + 1, + { "a" }, + let a = 1, + String, + my_name, + 'a, + my_val = 30, + std::option::Option, + pub(in some::path), + [ a b c ], + -30 + ); + } + + fn with_pat(use_pat!((a, b)): (u32, u32)) { + let _ = (a, b); + } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout new file mode 100644 index 000000000..4de8746a1 --- /dev/null +++ b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout @@ -0,0 +1,324 @@ +PRINT-BANG INPUT (DISPLAY): self +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "self", + span: $DIR/capture-macro-rules-invoke.rs:36:24: 36:28 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:21:21: 21:26 (#4), + }, +] +PRINT-BANG INPUT (DISPLAY): 1 + 1, { "a" }, let a = 1;, String, my_name, 'a, my_val = 30, +std::option::Option, pub(in some::path) , [a b c], -30 +PRINT-BANG RE-COLLECTED (DISPLAY): 1 + 1, { "a" }, let a = 1, String, my_name, 'a, my_val = 30, +std :: option :: Option, pub(in some :: path), [a b c], - 30 +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:38:13: 38:14 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:38:15: 38:16 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:38:17: 38:18 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:14:29: 14:34 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:34: 14:35 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "a", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:39:15: 39:18 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:39:13: 39:20 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:14:36: 14:42 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:42: 14:43 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "let", + span: $DIR/capture-macro-rules-invoke.rs:40:13: 40:16 (#0), + }, + Ident { + ident: "a", + span: $DIR/capture-macro-rules-invoke.rs:40:17: 40:18 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:40:19: 40:20 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:40:21: 40:22 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:14:44: 14:49 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:49: 14:50 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "String", + span: $DIR/capture-macro-rules-invoke.rs:41:13: 41:19 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:14:51: 14:54 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:54: 14:55 (#8), + }, + Ident { + ident: "my_name", + span: $DIR/capture-macro-rules-invoke.rs:42:13: 42:20 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:62: 14:63 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Punct { + ch: '\'', + spacing: Joint, + span: $DIR/capture-macro-rules-invoke.rs:43:13: 43:15 (#0), + }, + Ident { + ident: "a", + span: $DIR/capture-macro-rules-invoke.rs:43:13: 43:15 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:29: 15:38 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:38: 15:39 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "my_val", + span: $DIR/capture-macro-rules-invoke.rs:44:13: 44:19 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:44:20: 44:21 (#0), + }, + Literal { + kind: Integer, + symbol: "30", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:44:22: 44:24 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:40: 15:45 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:45: 15:46 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "std", + span: $DIR/capture-macro-rules-invoke.rs:45:13: 45:16 (#0), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/capture-macro-rules-invoke.rs:45:16: 45:18 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:45:16: 45:18 (#0), + }, + Ident { + ident: "option", + span: $DIR/capture-macro-rules-invoke.rs:45:18: 45:24 (#0), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/capture-macro-rules-invoke.rs:45:24: 45:26 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:45:24: 45:26 (#0), + }, + Ident { + ident: "Option", + span: $DIR/capture-macro-rules-invoke.rs:45:26: 45:32 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:47: 15:52 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:52: 15:53 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "pub", + span: $DIR/capture-macro-rules-invoke.rs:46:13: 46:16 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "in", + span: $DIR/capture-macro-rules-invoke.rs:46:17: 46:19 (#0), + }, + Ident { + ident: "some", + span: $DIR/capture-macro-rules-invoke.rs:46:20: 46:24 (#0), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/capture-macro-rules-invoke.rs:46:24: 46:26 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:46:24: 46:26 (#0), + }, + Ident { + ident: "path", + span: $DIR/capture-macro-rules-invoke.rs:46:26: 46:30 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:46:16: 46:31 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:54: 15:58 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:58: 15:59 (#8), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/capture-macro-rules-invoke.rs:47:15: 47:16 (#0), + }, + Ident { + ident: "b", + span: $DIR/capture-macro-rules-invoke.rs:47:17: 47:18 (#0), + }, + Ident { + ident: "c", + span: $DIR/capture-macro-rules-invoke.rs:47:19: 47:20 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:47:13: 47:22 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:63: 15:64 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Punct { + ch: '-', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:48:13: 48:14 (#0), + }, + Literal { + kind: Integer, + symbol: "30", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:48:14: 48:16 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:65: 15:69 (#8), + }, +] +PRINT-BANG INPUT (DISPLAY): (a, b) +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/capture-macro-rules-invoke.rs:52:27: 52:28 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:52:28: 52:29 (#0), + }, + Ident { + ident: "b", + span: $DIR/capture-macro-rules-invoke.rs:52:30: 52:31 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:52:26: 52:32 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:27:21: 27:25 (#12), + }, +] diff --git a/src/test/ui/proc-macro/capture-unglued-token.rs b/src/test/ui/proc-macro/capture-unglued-token.rs new file mode 100644 index 000000000..727b77977 --- /dev/null +++ b/src/test/ui/proc-macro/capture-unglued-token.rs @@ -0,0 +1,20 @@ +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// check-pass + +// Tests that we properly handle parsing a nonterminal +// where we have two consecutive angle brackets (one inside +// the nonterminal, and one outside) + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; +extern crate test_macros; + +macro_rules! trailing_angle { + (Option<$field:ty>) => { + test_macros::print_bang_consume!($field); + } +} + +trailing_angle!(Option<Vec<u8>>); +fn main() {} diff --git a/src/test/ui/proc-macro/capture-unglued-token.stdout b/src/test/ui/proc-macro/capture-unglued-token.stdout new file mode 100644 index 000000000..7e6b54033 --- /dev/null +++ b/src/test/ui/proc-macro/capture-unglued-token.stdout @@ -0,0 +1,28 @@ +PRINT-BANG INPUT (DISPLAY): Vec<u8> +PRINT-BANG RE-COLLECTED (DISPLAY): Vec < u8 > +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "Vec", + span: $DIR/capture-unglued-token.rs:19:24: 19:27 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/capture-unglued-token.rs:19:27: 19:28 (#0), + }, + Ident { + ident: "u8", + span: $DIR/capture-unglued-token.rs:19:28: 19:30 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/capture-unglued-token.rs:19:30: 19:31 (#0), + }, + ], + span: $DIR/capture-unglued-token.rs:15:42: 15:48 (#4), + }, +] diff --git a/src/test/ui/proc-macro/cfg-eval-fail.rs b/src/test/ui/proc-macro/cfg-eval-fail.rs new file mode 100644 index 000000000..a259aa2e6 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval-fail.rs @@ -0,0 +1,7 @@ +#![feature(cfg_eval)] +#![feature(stmt_expr_attributes)] + +fn main() { + let _ = #[cfg_eval] #[cfg(FALSE)] 0; + //~^ ERROR removing an expression is not supported in this position +} diff --git a/src/test/ui/proc-macro/cfg-eval-fail.stderr b/src/test/ui/proc-macro/cfg-eval-fail.stderr new file mode 100644 index 000000000..df8b6d5f3 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval-fail.stderr @@ -0,0 +1,8 @@ +error: removing an expression is not supported in this position + --> $DIR/cfg-eval-fail.rs:5:25 + | +LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0; + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/cfg-eval-inner.rs b/src/test/ui/proc-macro/cfg-eval-inner.rs new file mode 100644 index 000000000..5fd3ca0d1 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval-inner.rs @@ -0,0 +1,39 @@ +// compile-flags: -Z span-debug +// aux-build:test-macros.rs +// check-pass + +#![feature(cfg_eval)] +#![feature(custom_inner_attributes)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +struct Foo<T>(T); + +impl Foo<[u8; { + #![cfg_attr(not(FALSE), rustc_dummy(cursed_inner))] + #![allow(unused)] + struct Inner { + field: [u8; { + #![cfg_attr(not(FALSE), rustc_dummy(another_cursed_inner))] + 1 + }] + } + + 0 +}]> { + #![cfg_eval] + #![print_attr] + #![cfg_attr(not(FALSE), rustc_dummy(evaluated_attr))] + + fn bar() { + #[cfg(FALSE)] let a = 1; + } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/cfg-eval-inner.stdout b/src/test/ui/proc-macro/cfg-eval-inner.stdout new file mode 100644 index 000000000..9d25def58 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval-inner.stdout @@ -0,0 +1,247 @@ +PRINT-ATTR INPUT (DISPLAY): impl Foo < +[u8 ; +{ + #! [rustc_dummy(cursed_inner)] #! [allow(unused)] struct Inner + { field : [u8 ; { #! [rustc_dummy(another_cursed_inner)] 1 }] } 0 +}] > { #! [rustc_dummy(evaluated_attr)] fn bar() {} } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/cfg-eval-inner.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/cfg-eval-inner.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/cfg-eval-inner.rs:18:11: 18:13 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:18:13: 18:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:19:6: 19:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval-inner.rs:19:29: 19:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "cursed_inner", + span: $DIR/cfg-eval-inner.rs:19:41: 19:53 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:19:40: 19:54 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/cfg-eval-inner.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/cfg-eval-inner.rs:20:8: 20:13 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "unused", + span: $DIR/cfg-eval-inner.rs:20:14: 20:20 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:20:13: 20:21 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:20:7: 20:22 (#0), + }, + Ident { + ident: "struct", + span: $DIR/cfg-eval-inner.rs:21:5: 21:11 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/cfg-eval-inner.rs:21:12: 21:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/cfg-eval-inner.rs:22:9: 22:14 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:22:14: 22:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/cfg-eval-inner.rs:22:17: 22:19 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:22:19: 22:20 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:23:13: 23:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:23:14: 23:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval-inner.rs:23:37: 23:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "another_cursed_inner", + span: $DIR/cfg-eval-inner.rs:23:49: 23:69 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:23:48: 23:70 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:23:13: 23:14 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/cfg-eval-inner.rs:24:13: 24:14 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:22:21: 25:10 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:22:16: 25:11 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:21:18: 26:6 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/cfg-eval-inner.rs:28:5: 28:6 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:18:15: 29:2 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:18:10: 29:3 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:29:3: 29:4 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:32:5: 32:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:32:6: 32:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval-inner.rs:32:29: 32:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "evaluated_attr", + span: $DIR/cfg-eval-inner.rs:32:41: 32:55 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:32:40: 32:56 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:32:5: 32:6 (#0), + }, + Ident { + ident: "fn", + span: $DIR/cfg-eval-inner.rs:34:5: 34:7 (#0), + }, + Ident { + ident: "bar", + span: $DIR/cfg-eval-inner.rs:34:8: 34:11 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/cfg-eval-inner.rs:34:11: 34:13 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/cfg-eval-inner.rs:34:14: 36:6 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:29:5: 37:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/cfg-eval.rs b/src/test/ui/proc-macro/cfg-eval.rs new file mode 100644 index 000000000..fa6d015e4 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval.rs @@ -0,0 +1,37 @@ +// check-pass +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![feature(cfg_eval)] +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[cfg_eval] +#[print_attr] +struct S1 { + #[cfg(FALSE)] + field_false: u8, + #[cfg(all(/*true*/))] + #[cfg_attr(FALSE, unknown_attr)] + #[cfg_attr(all(/*true*/), allow())] + field_true: u8, +} + +#[cfg_eval] +#[cfg(FALSE)] +struct S2 {} + +fn main() { + // Subtle - we need a trailing comma after the '1' - otherwise, `#[cfg_eval]` will + // turn this into `(#[cfg(all())] 1)`, which is a parenthesized expression, not a tuple + // expression. `#[cfg]` is not supported inside parenthesized expressions, so this will + // produce an error when attribute collection runs. + let _ = #[cfg_eval] #[print_attr] #[cfg_attr(not(FALSE), rustc_dummy)] + (#[cfg(FALSE)] 0, #[cfg(all(/*true*/))] 1,); +} diff --git a/src/test/ui/proc-macro/cfg-eval.stdout b/src/test/ui/proc-macro/cfg-eval.stdout new file mode 100644 index 000000000..6732caf08 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval.stdout @@ -0,0 +1,150 @@ +PRINT-ATTR INPUT (DISPLAY): struct S1 { #[cfg(all())] #[allow()] field_true : u8, } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/cfg-eval.rs:17:1: 17:7 (#0), + }, + Ident { + ident: "S1", + span: $DIR/cfg-eval.rs:17:8: 17:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval.rs:20:5: 20:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/cfg-eval.rs:20:7: 20:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "all", + span: $DIR/cfg-eval.rs:20:11: 20:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/cfg-eval.rs:20:14: 20:24 (#0), + }, + ], + span: $DIR/cfg-eval.rs:20:10: 20:25 (#0), + }, + ], + span: $DIR/cfg-eval.rs:20:6: 20:26 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval.rs:22:5: 22:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/cfg-eval.rs:22:31: 22:36 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/cfg-eval.rs:22:36: 22:38 (#0), + }, + ], + span: $DIR/cfg-eval.rs:22:5: 22:6 (#0), + }, + Ident { + ident: "field_true", + span: $DIR/cfg-eval.rs:23:5: 23:15 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/cfg-eval.rs:23:15: 23:16 (#0), + }, + Ident { + ident: "u8", + span: $DIR/cfg-eval.rs:23:17: 23:19 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/cfg-eval.rs:23:19: 23:20 (#0), + }, + ], + span: $DIR/cfg-eval.rs:17:11: 24:2 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] (#[cfg(all())] 1,) +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval.rs:35:39: 35:40 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval.rs:35:62: 35:73 (#0), + }, + ], + span: $DIR/cfg-eval.rs:35:39: 35:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval.rs:36:23: 36:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/cfg-eval.rs:36:25: 36:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "all", + span: $DIR/cfg-eval.rs:36:29: 36:32 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/cfg-eval.rs:36:32: 36:42 (#0), + }, + ], + span: $DIR/cfg-eval.rs:36:28: 36:43 (#0), + }, + ], + span: $DIR/cfg-eval.rs:36:24: 36:44 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/cfg-eval.rs:36:45: 36:46 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/cfg-eval.rs:36:46: 36:47 (#0), + }, + ], + span: $DIR/cfg-eval.rs:36:5: 36:48 (#0), + }, +] diff --git a/src/test/ui/proc-macro/count_compound_ops.rs b/src/test/ui/proc-macro/count_compound_ops.rs new file mode 100644 index 000000000..2cb871844 --- /dev/null +++ b/src/test/ui/proc-macro/count_compound_ops.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:count_compound_ops.rs + +extern crate count_compound_ops; +use count_compound_ops::count_compound_ops; + +fn main() { + assert_eq!(count_compound_ops!(foo<=>bar <<<! -baz ++), 4); +} diff --git a/src/test/ui/proc-macro/crate-attrs-multiple.rs b/src/test/ui/proc-macro/crate-attrs-multiple.rs new file mode 100644 index 000000000..29a0eca41 --- /dev/null +++ b/src/test/ui/proc-macro/crate-attrs-multiple.rs @@ -0,0 +1,14 @@ +// Multiple custom crate-level attributes, both inert and active. + +// check-pass +// aux-crate:test_macros=test-macros.rs + +#![feature(custom_inner_attributes)] +#![feature(prelude_import)] + +#![test_macros::identity_attr] +#![rustfmt::skip] +#![test_macros::identity_attr] +#![rustfmt::skip] + +fn main() {} diff --git a/src/test/ui/proc-macro/crate-var.rs b/src/test/ui/proc-macro/crate-var.rs new file mode 100644 index 000000000..c0518e4b0 --- /dev/null +++ b/src/test/ui/proc-macro/crate-var.rs @@ -0,0 +1,61 @@ +// run-pass +// aux-build:double.rs +// aux-build:external-crate-var.rs + +#![allow(unused)] + +#[macro_use] +extern crate double; +#[macro_use] +extern crate external_crate_var; + +struct Foo; + +trait Trait { + const CONST: u32; + type Assoc; +} + +impl Trait for Foo { + const CONST: u32 = 0; + type Assoc = Foo; +} + +macro_rules! local { () => { + // derive_Double outputs secondary copies of each definition + // to test what the proc_macro sees. + mod bar { + #[derive(Double)] + struct Bar($crate::Foo); + } + + mod qself { + #[derive(Double)] + struct QSelf(<::Foo as $crate::Trait>::Assoc); + } + + mod qself_recurse { + #[derive(Double)] + struct QSelfRecurse(<<$crate::Foo as $crate::Trait>::Assoc as $crate::Trait>::Assoc); + } + + mod qself_in_const { + #[derive(Double)] + #[repr(u32)] + enum QSelfInConst { + Variant = <::Foo as $crate::Trait>::CONST, + } + } +} } + +mod local { + local!(); +} + +// and now repeat the above tests, using a macro defined in another crate + +mod external { + external!{} +} + +fn main() {} diff --git a/src/test/ui/proc-macro/crt-static.rs b/src/test/ui/proc-macro/crt-static.rs new file mode 100644 index 000000000..8c1a9dc80 --- /dev/null +++ b/src/test/ui/proc-macro/crt-static.rs @@ -0,0 +1,24 @@ +// Test proc-macro crate can be built without additional RUSTFLAGS +// on musl target +// override -Ctarget-feature=-crt-static from compiletest +// compile-flags: --crate-type proc-macro -Ctarget-feature= +// ignore-wasm32 +// ignore-sgx no support for proc-macro crate type +// build-pass +#![crate_type = "proc-macro"] + +// FIXME: This don't work when crate-type is specified by attribute +// `#![crate_type = "proc-macro"]`, not by `--crate-type=proc-macro` +// command line flag. This is beacuse the list of `cfg` symbols is generated +// before attributes are parsed. See rustc_interface::util::add_configuration +#[cfg(target_feature = "crt-static")] +compile_error!("crt-static is enabled"); + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui/proc-macro/custom-attr-only-one-derive.rs b/src/test/ui/proc-macro/custom-attr-only-one-derive.rs new file mode 100644 index 000000000..2cd5b4873 --- /dev/null +++ b/src/test/ui/proc-macro/custom-attr-only-one-derive.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:custom-attr-only-one-derive.rs + +#![feature(rust_2018_preview)] + +#[macro_use] +extern crate custom_attr_only_one_derive; + +#[derive(Bar, Foo)] +#[custom = "test"] +pub enum A { + B, + C, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs b/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs new file mode 100644 index 000000000..56ad0612f --- /dev/null +++ b/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![crate_name = "macro_dump_debug"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn dump_debug(tokens: TokenStream) -> TokenStream { + eprintln!("{:?}", tokens); + eprintln!("{:#?}", tokens); + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs b/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs new file mode 100644 index 000000000..fd34eb974 --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs @@ -0,0 +1,41 @@ +// run-pass +// aux-build:macro-dump-debug.rs +// compile-flags: -Z span-debug + +extern crate macro_dump_debug; +use macro_dump_debug::dump_debug; + +dump_debug! { + ident // ident + r#ident // raw ident + , // alone punct + ==> // joint punct + () // empty group + [_] // nonempty group + + // unsuffixed literals + 0 + 1.0 + "S" + b"B" + r"R" + r##"R"## + br"BR" + br##"BR"## + 'C' + b'B' + + // suffixed literals + 0q + 1.0q + "S"q + b"B"q + r"R"q + r##"R"##q + br"BR"q + br##"BR"##q + 'C'q + b'B'q +} + +fn main() {} diff --git a/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr new file mode 100644 index 000000000..2c05bdbc4 --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr @@ -0,0 +1,166 @@ +TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0) }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0) }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0) }], span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0) }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0) }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0) }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0) }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0) }] +TokenStream [ + Ident { + ident: "ident", + span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0), + }, + Ident { + ident: "r#ident", + span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "_", + span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0), + }, + ], + span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0), + }, + Literal { + kind: Str, + symbol: "S", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0), + }, + Literal { + kind: Char, + symbol: "C", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0), + }, + Literal { + kind: Str, + symbol: "S", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0), + }, + Literal { + kind: Char, + symbol: "C", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0), + }, +] diff --git a/src/test/ui/proc-macro/debug/dump-debug.rs b/src/test/ui/proc-macro/debug/dump-debug.rs new file mode 100644 index 000000000..0ed36b690 --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug.rs @@ -0,0 +1,40 @@ +// run-pass +// aux-build:macro-dump-debug.rs + +extern crate macro_dump_debug; +use macro_dump_debug::dump_debug; + +dump_debug! { + ident // ident + r#ident // raw ident + , // alone punct + ==> // joint punct + () // empty group + [_] // nonempty group + + // unsuffixed literals + 0 + 1.0 + "S" + b"B" + r"R" + r##"R"## + br"BR" + br##"BR"## + 'C' + b'B' + + // suffixed literals + 0q + 1.0q + "S"q + b"B"q + r"R"q + r##"R"##q + br"BR"q + br##"BR"##q + 'C'q + b'B'q +} + +fn main() {} diff --git a/src/test/ui/proc-macro/debug/dump-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug.stderr new file mode 100644 index 000000000..0aedefd4e --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug.stderr @@ -0,0 +1,166 @@ +TokenStream [Ident { ident: "ident", span: #0 bytes(130..135) }, Ident { ident: "r#ident", span: #0 bytes(151..158) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(176..177) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(205..206) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(230..232) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(258..259) }], span: #0 bytes(257..260) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(315..316) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(321..324) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(329..332) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(337..341) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(346..350) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(355..363) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(368..374) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(379..389) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(394..397) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(402..406) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(437..439) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(444..448) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(453..457) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(462..467) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(472..477) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(482..491) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(496..503) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(508..519) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(524..528) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(533..538) }] +TokenStream [ + Ident { + ident: "ident", + span: #0 bytes(130..135), + }, + Ident { + ident: "r#ident", + span: #0 bytes(151..158), + }, + Punct { + ch: ',', + spacing: Alone, + span: #0 bytes(176..177), + }, + Punct { + ch: '=', + spacing: Joint, + span: #0 bytes(203..205), + }, + Punct { + ch: '=', + spacing: Joint, + span: #0 bytes(203..205), + }, + Punct { + ch: '>', + spacing: Alone, + span: #0 bytes(205..206), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: #0 bytes(230..232), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "_", + span: #0 bytes(258..259), + }, + ], + span: #0 bytes(257..260), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(315..316), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: None, + span: #0 bytes(321..324), + }, + Literal { + kind: Str, + symbol: "S", + suffix: None, + span: #0 bytes(329..332), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: None, + span: #0 bytes(337..341), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: None, + span: #0 bytes(346..350), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: None, + span: #0 bytes(355..363), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: None, + span: #0 bytes(368..374), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: None, + span: #0 bytes(379..389), + }, + Literal { + kind: Char, + symbol: "C", + suffix: None, + span: #0 bytes(394..397), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: None, + span: #0 bytes(402..406), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: Some("q"), + span: #0 bytes(437..439), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: Some("q"), + span: #0 bytes(444..448), + }, + Literal { + kind: Str, + symbol: "S", + suffix: Some("q"), + span: #0 bytes(453..457), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: Some("q"), + span: #0 bytes(462..467), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: Some("q"), + span: #0 bytes(472..477), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: Some("q"), + span: #0 bytes(482..491), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: Some("q"), + span: #0 bytes(496..503), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: Some("q"), + span: #0 bytes(508..519), + }, + Literal { + kind: Char, + symbol: "C", + suffix: Some("q"), + span: #0 bytes(524..528), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: Some("q"), + span: #0 bytes(533..538), + }, +] diff --git a/src/test/ui/proc-macro/define-two.rs b/src/test/ui/proc-macro/define-two.rs new file mode 100644 index 000000000..b2184eae3 --- /dev/null +++ b/src/test/ui/proc-macro/define-two.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(A)] +pub fn foo(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(A)] //~ ERROR the name `A` is defined multiple times +pub fn bar(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui/proc-macro/define-two.stderr b/src/test/ui/proc-macro/define-two.stderr new file mode 100644 index 000000000..bf1bd8427 --- /dev/null +++ b/src/test/ui/proc-macro/define-two.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `A` is defined multiple times + --> $DIR/define-two.rs:15:21 + | +LL | #[proc_macro_derive(A)] + | - previous definition of the macro `A` here +... +LL | #[proc_macro_derive(A)] + | ^ `A` redefined here + | + = note: `A` must be defined only once in the macro namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/derive-attr-cfg.rs b/src/test/ui/proc-macro/derive-attr-cfg.rs new file mode 100644 index 000000000..394774628 --- /dev/null +++ b/src/test/ui/proc-macro/derive-attr-cfg.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(dead_code)] +// aux-build:derive-attr-cfg.rs + +extern crate derive_attr_cfg; +use derive_attr_cfg::Foo; + +#[derive(Foo)] +#[foo] +struct S { + #[cfg(any())] + x: i32 +} + +fn main() { +} diff --git a/src/test/ui/proc-macro/derive-b.rs b/src/test/ui/proc-macro/derive-b.rs new file mode 100644 index 000000000..a026c2bd7 --- /dev/null +++ b/src/test/ui/proc-macro/derive-b.rs @@ -0,0 +1,19 @@ +// run-pass +// aux-build:derive-b-rpass.rs + +extern crate derive_b_rpass as derive_b; + +#[derive(Debug, PartialEq, derive_b::B, Eq, Copy, Clone)] +#[cfg_attr(all(), B[arbitrary tokens])] +struct B { + #[C] + a: u64 +} + +fn main() { + B { a: 3 }; + assert_eq!(B { a: 3 }, B { a: 3 }); + let b = B { a: 3 }; + let _d = b; + let _e = b; +} diff --git a/src/test/ui/proc-macro/derive-bad.rs b/src/test/ui/proc-macro/derive-bad.rs new file mode 100644 index 000000000..cb5188b5f --- /dev/null +++ b/src/test/ui/proc-macro/derive-bad.rs @@ -0,0 +1,11 @@ +// aux-build:derive-bad.rs + +#[macro_use] +extern crate derive_bad; + +#[derive(A)] +//~^ ERROR proc-macro derive produced unparseable tokens +//~| ERROR expected `:`, found `}` +struct A; //~ ERROR the name `A` is defined multiple times + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-bad.stderr b/src/test/ui/proc-macro/derive-bad.stderr new file mode 100644 index 000000000..ae48141fb --- /dev/null +++ b/src/test/ui/proc-macro/derive-bad.stderr @@ -0,0 +1,28 @@ +error: expected `:`, found `}` + --> $DIR/derive-bad.rs:6:10 + | +LL | #[derive(A)] + | ^ expected `:` + | + = note: this error originates in the derive macro `A` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: proc-macro derive produced unparseable tokens + --> $DIR/derive-bad.rs:6:10 + | +LL | #[derive(A)] + | ^ + +error[E0428]: the name `A` is defined multiple times + --> $DIR/derive-bad.rs:9:1 + | +LL | #[derive(A)] + | - previous definition of the type `A` here +... +LL | struct A; + | ^^^^^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this module + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/derive-expand-order.rs b/src/test/ui/proc-macro/derive-expand-order.rs new file mode 100644 index 000000000..0cf1ceb91 --- /dev/null +++ b/src/test/ui/proc-macro/derive-expand-order.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:multiple-derives.rs + +extern crate multiple_derives; + +use multiple_derives::*; + +#[derive(First)] +#[derive(Second)] +#[derive(Third, Fourth)] +#[derive(Fifth)] +pub struct Foo {} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-expand-order.stdout b/src/test/ui/proc-macro/derive-expand-order.stdout new file mode 100644 index 000000000..dffbbf149 --- /dev/null +++ b/src/test/ui/proc-macro/derive-expand-order.stdout @@ -0,0 +1,5 @@ +Derive First: #[derive(Second)] #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo {} +Derive Second: #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo {} +Derive Third: #[derive(Fifth)] pub struct Foo {} +Derive Fourth: #[derive(Fifth)] pub struct Foo {} +Derive Fifth: pub struct Foo {} diff --git a/src/test/ui/proc-macro/derive-helper-configured.rs b/src/test/ui/proc-macro/derive-helper-configured.rs new file mode 100644 index 000000000..243cf685e --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-configured.rs @@ -0,0 +1,18 @@ +// Derive helpers are resolved successfully inside `cfg_attr`. + +// check-pass +// compile-flats:--cfg TRUE +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[cfg_attr(TRUE, empty_helper)] +#[derive(Empty)] +#[cfg_attr(TRUE, empty_helper)] +struct S { + #[cfg_attr(TRUE, empty_helper)] + field: u8, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-legacy-limits.rs b/src/test/ui/proc-macro/derive-helper-legacy-limits.rs new file mode 100644 index 000000000..ca904900d --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-legacy-limits.rs @@ -0,0 +1,21 @@ +// Support for legacy derive helpers is limited and heuristic-based +// (that's exactly the reason why they are deprecated). + +// edition:2018 +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +use derive as my_derive; + +#[my_derive(Empty)] +#[empty_helper] // OK +struct S1; + +// Legacy helper detection doesn't see through `derive` renaming. +#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope +#[my_derive(Empty)] +struct S2; + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-legacy-limits.stderr b/src/test/ui/proc-macro/derive-helper-legacy-limits.stderr new file mode 100644 index 000000000..186f38a00 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-legacy-limits.stderr @@ -0,0 +1,8 @@ +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-legacy-limits.rs:17:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/derive-helper-legacy-spurious.rs b/src/test/ui/proc-macro/derive-helper-legacy-spurious.rs new file mode 100644 index 000000000..4a7e48eed --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-legacy-spurious.rs @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs + +#![dummy] //~ ERROR cannot find attribute `dummy` in this scope + +#[macro_use] +extern crate test_macros; + +#[derive(Empty)] //~ ERROR cannot determine resolution for the attribute macro `derive` +#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope +struct Foo {} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-legacy-spurious.stderr b/src/test/ui/proc-macro/derive-helper-legacy-spurious.stderr new file mode 100644 index 000000000..fd1ed8a3d --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-legacy-spurious.stderr @@ -0,0 +1,22 @@ +error: cannot find attribute `dummy` in this scope + --> $DIR/derive-helper-legacy-spurious.rs:3:4 + | +LL | #![dummy] + | ^^^^^ + +error: cannot determine resolution for the attribute macro `derive` + --> $DIR/derive-helper-legacy-spurious.rs:8:3 + | +LL | #[derive(Empty)] + | ^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-legacy-spurious.rs:9:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/proc-macro/derive-helper-shadowed.rs b/src/test/ui/proc-macro/derive-helper-shadowed.rs new file mode 100644 index 000000000..e299454e0 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-shadowed.rs @@ -0,0 +1,16 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs +// aux-build:derive-helper-shadowed-2.rs + +#[macro_use] +extern crate test_macros; +#[macro_use(empty_helper)] +extern crate derive_helper_shadowed_2; + +macro_rules! empty_helper { () => () } + +#[derive(Empty)] +#[empty_helper] // OK +struct S; + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-shadowing-2.rs b/src/test/ui/proc-macro/derive-helper-shadowing-2.rs new file mode 100644 index 000000000..5204d72b9 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-shadowing-2.rs @@ -0,0 +1,16 @@ +// If a derive macro introduces a helper attribute with the same name as that macro, +// then make sure that it's usable without ambiguities. + +// check-pass +// aux-build:derive-helper-shadowing-2.rs + +#[macro_use] +extern crate derive_helper_shadowing_2; + +#[derive(same_name)] +struct S { + #[same_name] // OK, no ambiguity, derive helpers have highest priority + field: u8, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs new file mode 100644 index 000000000..80d982d25 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs @@ -0,0 +1,56 @@ +// edition:2018 +// aux-build:test-macros.rs +// aux-build:derive-helper-shadowing.rs + +#[macro_use] +extern crate test_macros; +#[macro_use] +extern crate derive_helper_shadowing; + +use test_macros::empty_attr as empty_helper; + +macro_rules! gen_helper_use { + () => { + #[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope + struct W; + } +} + +#[empty_helper] //~ ERROR `empty_helper` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[derive(Empty)] +struct S { + #[empty_helper] // OK, no ambiguity, derive helpers have highest priority + field: [u8; { + use empty_helper; //~ ERROR `empty_helper` is ambiguous + + #[empty_helper] // OK, no ambiguity, derive helpers have highest priority + struct U; + + mod inner { + // OK, no ambiguity, the non-helper attribute is not in scope here, only the helper. + #[empty_helper] + struct V; + + gen_helper_use!(); + + #[derive(GenHelperUse)] //~ ERROR cannot find attribute `empty_helper` in this scope + struct Owo; + + use empty_helper as renamed; + #[renamed] //~ ERROR cannot use a derive helper attribute through an import + struct Wow; + } + + 0 + }] +} + +// OK, no ambiguity, only the non-helper attribute is in scope. +#[empty_helper] +struct Z; + +fn main() { + let s = S { field: [] }; +} diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr new file mode 100644 index 000000000..d8287eb73 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -0,0 +1,89 @@ +error: cannot use a derive helper attribute through an import + --> $DIR/derive-helper-shadowing.rs:42:15 + | +LL | #[renamed] + | ^^^^^^^ + | +note: the derive helper attribute imported here + --> $DIR/derive-helper-shadowing.rs:41:17 + | +LL | use empty_helper as renamed; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-shadowing.rs:38:22 + | +LL | #[derive(GenHelperUse)] + | ^^^^^^^^^^^^ + | + = note: consider importing this attribute macro: + empty_helper + = note: this error originates in the derive macro `GenHelperUse` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-shadowing.rs:14:11 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ +... +LL | gen_helper_use!(); + | ----------------- in this macro invocation + | + = note: consider importing this attribute macro: + crate::empty_helper + = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `empty_helper` is ambiguous + --> $DIR/derive-helper-shadowing.rs:26:13 + | +LL | use empty_helper; + | ^^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/derive-helper-shadowing.rs:22:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/derive-helper-shadowing.rs:10:5 + | +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously + +error[E0659]: `empty_helper` is ambiguous + --> $DIR/derive-helper-shadowing.rs:19:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/derive-helper-shadowing.rs:22:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/derive-helper-shadowing.rs:10:5 + | +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously + +warning: derive helper attribute is used before it is introduced + --> $DIR/derive-helper-shadowing.rs:19:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ +... +LL | #[derive(Empty)] + | ----- the attribute is introduced here + | + = note: `#[warn(legacy_derive_helpers)]` on by default + = 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 #79202 <https://github.com/rust-lang/rust/issues/79202> + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/derive-helper-vs-legacy.rs b/src/test/ui/proc-macro/derive-helper-vs-legacy.rs new file mode 100644 index 000000000..98836bcb8 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-vs-legacy.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive(Empty)] +#[empty_helper] // OK, this is both derive helper and legacy derive helper +#[derive(Empty)] +struct S; + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-in-mod.rs b/src/test/ui/proc-macro/derive-in-mod.rs new file mode 100644 index 000000000..8b5d4e9d0 --- /dev/null +++ b/src/test/ui/proc-macro/derive-in-mod.rs @@ -0,0 +1,13 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +extern crate test_macros; + +mod inner { + use test_macros::Empty; + + #[derive(Empty)] + struct S; +} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-multiple-with-packed.rs b/src/test/ui/proc-macro/derive-multiple-with-packed.rs new file mode 100644 index 000000000..23578aa0e --- /dev/null +++ b/src/test/ui/proc-macro/derive-multiple-with-packed.rs @@ -0,0 +1,11 @@ +// check-pass + +#[derive(Clone, Copy)] +#[derive(Debug)] // OK, even if `Copy` is in the different `#[derive]` +#[derive(PartialEq)] // OK too +#[repr(packed)] +struct CacheRecordHeader { + field: u64, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-same-struct.rs b/src/test/ui/proc-macro/derive-same-struct.rs new file mode 100644 index 000000000..528b0f22a --- /dev/null +++ b/src/test/ui/proc-macro/derive-same-struct.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(path_statements)] +#![allow(dead_code)] +// aux-build:derive-same-struct.rs + +#[macro_use] +extern crate derive_same_struct; + +#[derive(AToB)] +struct A; + +fn main() { + C; +} diff --git a/src/test/ui/proc-macro/derive-same-struct.stdout b/src/test/ui/proc-macro/derive-same-struct.stdout new file mode 100644 index 000000000..7478d9741 --- /dev/null +++ b/src/test/ui/proc-macro/derive-same-struct.stdout @@ -0,0 +1 @@ +input1: "struct A ;" diff --git a/src/test/ui/proc-macro/derive-still-gated.rs b/src/test/ui/proc-macro/derive-still-gated.rs new file mode 100644 index 000000000..3f8d6f071 --- /dev/null +++ b/src/test/ui/proc-macro/derive-still-gated.rs @@ -0,0 +1,9 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive_Empty] //~ ERROR cannot find attribute `derive_Empty` in this scope +struct A; + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr new file mode 100644 index 000000000..99289fdfe --- /dev/null +++ b/src/test/ui/proc-macro/derive-still-gated.stderr @@ -0,0 +1,8 @@ +error: cannot find attribute `derive_Empty` in this scope + --> $DIR/derive-still-gated.rs:6:3 + | +LL | #[derive_Empty] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/derive-test.rs b/src/test/ui/proc-macro/derive-test.rs new file mode 100644 index 000000000..b81e38432 --- /dev/null +++ b/src/test/ui/proc-macro/derive-test.rs @@ -0,0 +1,22 @@ +// run-pass +// no-prefer-dynamic +// compile-flags: --test + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +// ``` +// assert!(true); +// ``` +#[proc_macro_derive(Foo)] +pub fn derive_foo(_input: TokenStream) -> TokenStream { + "".parse().unwrap() +} + +#[test] +pub fn test_derive() { + assert!(true); +} diff --git a/src/test/ui/proc-macro/derive-two-attrs.rs b/src/test/ui/proc-macro/derive-two-attrs.rs new file mode 100644 index 000000000..08225b8e3 --- /dev/null +++ b/src/test/ui/proc-macro/derive-two-attrs.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(dead_code)] +// aux-build:derive-two-attrs.rs + +extern crate derive_two_attrs as foo; + +use foo::A; + +#[derive(A)] +#[b] +#[b] +struct B; + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-union.rs b/src/test/ui/proc-macro/derive-union.rs new file mode 100644 index 000000000..e83eee093 --- /dev/null +++ b/src/test/ui/proc-macro/derive-union.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(unused_variables)] +// aux-build:derive-union.rs + +#[macro_use] +extern crate derive_union; + +#[repr(C)] +#[derive(UnionTest)] +union Test { + a: u8, +} + +fn main() { + let t = Test { a: 0 }; +} diff --git a/src/test/ui/proc-macro/disappearing-resolution.rs b/src/test/ui/proc-macro/disappearing-resolution.rs new file mode 100644 index 000000000..50f04b1ea --- /dev/null +++ b/src/test/ui/proc-macro/disappearing-resolution.rs @@ -0,0 +1,22 @@ +// Regression test for issue #64803 (initial attribute resolution can disappear later). + +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +mod m { + use test_macros::Empty; +} +use m::Empty; //~ ERROR derive macro import `Empty` is private + +// To resolve `empty_helper` we need to resolve `Empty`. +// During initial resolution `use m::Empty` introduces no entries, so we proceed to `macro_use`, +// successfully resolve `Empty` from there, and then resolve `empty_helper` as its helper. +// During validation `use m::Empty` introduces a `Res::Err` stub, so `Empty` resolves to it, +// and `empty_helper` can no longer be resolved. +#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope +#[derive(Empty)] +struct S; + +fn main() {} diff --git a/src/test/ui/proc-macro/disappearing-resolution.stderr b/src/test/ui/proc-macro/disappearing-resolution.stderr new file mode 100644 index 000000000..5b969549a --- /dev/null +++ b/src/test/ui/proc-macro/disappearing-resolution.stderr @@ -0,0 +1,26 @@ +error: cannot find attribute `empty_helper` in this scope + --> $DIR/disappearing-resolution.rs:18:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ + +error[E0603]: derive macro import `Empty` is private + --> $DIR/disappearing-resolution.rs:11:8 + | +LL | use m::Empty; + | ^^^^^ private derive macro import + | +note: the derive macro import `Empty` is defined here... + --> $DIR/disappearing-resolution.rs:9:9 + | +LL | use test_macros::Empty; + | ^^^^^^^^^^^^^^^^^^ +note: ...and refers to the derive macro `Empty` which is defined here + --> $DIR/auxiliary/test-macros.rs:25:1 + | +LL | pub fn empty_derive(_: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/proc-macro/doc-comment-preserved.rs b/src/test/ui/proc-macro/doc-comment-preserved.rs new file mode 100644 index 000000000..ed8ca99bd --- /dev/null +++ b/src/test/ui/proc-macro/doc-comment-preserved.rs @@ -0,0 +1,24 @@ +// check-pass +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +print_bang! { + +/** +******* +* DOC * +* DOC * +* DOC * +******* +*/ +pub struct S; + +} + +fn main() {} diff --git a/src/test/ui/proc-macro/doc-comment-preserved.stdout b/src/test/ui/proc-macro/doc-comment-preserved.stdout new file mode 100644 index 000000000..f4160d7da --- /dev/null +++ b/src/test/ui/proc-macro/doc-comment-preserved.stdout @@ -0,0 +1,54 @@ +PRINT-BANG INPUT (DISPLAY): /** +******* +* DOC * +* DOC * +* DOC * +******* +*/ + pub struct S ; +PRINT-BANG RE-COLLECTED (DISPLAY): #[doc = "\n*******\n* DOC *\n* DOC *\n* DOC *\n*******\n"] pub struct S ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "doc", + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + Literal { + kind: Str, + symbol: "\n*******\n* DOC *\n* DOC *\n* DOC *\n*******\n", + suffix: None, + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + ], + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + Ident { + ident: "pub", + span: $DIR/doc-comment-preserved.rs:20:1: 20:4 (#0), + }, + Ident { + ident: "struct", + span: $DIR/doc-comment-preserved.rs:20:5: 20:11 (#0), + }, + Ident { + ident: "S", + span: $DIR/doc-comment-preserved.rs:20:12: 20:13 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/doc-comment-preserved.rs:20:13: 20:14 (#0), + }, +] diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.rs b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs new file mode 100644 index 000000000..27bfa099f --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs @@ -0,0 +1,27 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +type S = u8; + +macro_rules! m { + () => { + print_bang! { + struct M($crate::S); + } + + #[print_attr] + struct A($crate::S); + }; +} + +m!(); + +fn main() {} diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout new file mode 100644 index 000000000..c0c9ed72c --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -0,0 +1,80 @@ +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate-issue-57089.rs:17:13: 17:19 (#4), + }, + Ident { + ident: "M", + span: $DIR/dollar-crate-issue-57089.rs:17:20: 17:21 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate-issue-57089.rs:17:22: 17:28 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate-issue-57089.rs:17:28: 17:30 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate-issue-57089.rs:17:28: 17:30 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate-issue-57089.rs:17:30: 17:31 (#4), + }, + ], + span: $DIR/dollar-crate-issue-57089.rs:17:21: 17:32 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate-issue-57089.rs:17:32: 17:33 (#4), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate-issue-57089.rs:21:9: 21:15 (#4), + }, + Ident { + ident: "A", + span: $DIR/dollar-crate-issue-57089.rs:21:16: 21:17 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate-issue-57089.rs:21:18: 21:24 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate-issue-57089.rs:21:24: 21:26 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate-issue-57089.rs:21:24: 21:26 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate-issue-57089.rs:21:26: 21:27 (#4), + }, + ], + span: $DIR/dollar-crate-issue-57089.rs:21:17: 21:28 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate-issue-57089.rs:21:28: 21:29 (#4), + }, +] diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.rs b/src/test/ui/proc-macro/dollar-crate-issue-62325.rs new file mode 100644 index 000000000..d828fb9fd --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.rs @@ -0,0 +1,26 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs +// aux-build:dollar-crate-external.rs + + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; +extern crate dollar_crate_external; + +type S = u8; + +macro_rules! m { () => { + #[print_attr] + struct A(identity!($crate::S)); +}} + +m!(); + +dollar_crate_external::issue_62325!(); + +fn main() {} diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout new file mode 100644 index 000000000..e6148a687 --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -0,0 +1,110 @@ +PRINT-ATTR INPUT (DISPLAY): struct A(identity! ($crate :: S)) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate-issue-62325.rs:19:5: 19:11 (#4), + }, + Ident { + ident: "A", + span: $DIR/dollar-crate-issue-62325.rs:19:12: 19:13 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "identity", + span: $DIR/dollar-crate-issue-62325.rs:19:14: 19:22 (#4), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/dollar-crate-issue-62325.rs:19:22: 19:23 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate-issue-62325.rs:19:24: 19:30 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate-issue-62325.rs:19:30: 19:32 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate-issue-62325.rs:19:30: 19:32 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate-issue-62325.rs:19:32: 19:33 (#4), + }, + ], + span: $DIR/dollar-crate-issue-62325.rs:19:23: 19:34 (#4), + }, + ], + span: $DIR/dollar-crate-issue-62325.rs:19:13: 19:35 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate-issue-62325.rs:19:35: 19:36 (#4), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct B(identity! ($crate :: S)) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/dollar-crate-external.rs:21:5: 21:11 (#12), + }, + Ident { + ident: "B", + span: $DIR/auxiliary/dollar-crate-external.rs:21:12: 21:13 (#12), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "identity", + span: $DIR/auxiliary/dollar-crate-external.rs:21:14: 21:22 (#12), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:21:22: 21:23 (#12), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/auxiliary/dollar-crate-external.rs:21:24: 21:30 (#12), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/auxiliary/dollar-crate-external.rs:21:30: 21:32 (#12), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:21:30: 21:32 (#12), + }, + Ident { + ident: "S", + span: $DIR/auxiliary/dollar-crate-external.rs:21:32: 21:33 (#12), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:21:23: 21:34 (#12), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:21:13: 21:35 (#12), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:21:35: 21:36 (#12), + }, +] diff --git a/src/test/ui/proc-macro/dollar-crate.rs b/src/test/ui/proc-macro/dollar-crate.rs new file mode 100644 index 000000000..ac27dfa1a --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate.rs @@ -0,0 +1,40 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs +// aux-build:dollar-crate-external.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; +extern crate dollar_crate_external; + +type S = u8; + +mod local { + macro_rules! local { + () => { + print_bang! { + struct M($crate::S); + } + + #[print_attr] + struct A($crate::S); + + #[derive(Print)] + struct D($crate::S); + }; + } + + local!(); +} + +mod external { + use crate::dollar_crate_external; + + dollar_crate_external::external!(); +} + +fn main() {} diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout new file mode 100644 index 000000000..d01fcb9d0 --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -0,0 +1,240 @@ +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate.rs:20:17: 20:23 (#4), + }, + Ident { + ident: "M", + span: $DIR/dollar-crate.rs:20:24: 20:25 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate.rs:20:26: 20:32 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate.rs:20:32: 20:34 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate.rs:20:32: 20:34 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate.rs:20:34: 20:35 (#4), + }, + ], + span: $DIR/dollar-crate.rs:20:25: 20:36 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate.rs:20:36: 20:37 (#4), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate.rs:24:13: 24:19 (#4), + }, + Ident { + ident: "A", + span: $DIR/dollar-crate.rs:24:20: 24:21 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate.rs:24:22: 24:28 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate.rs:24:28: 24:30 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate.rs:24:28: 24:30 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate.rs:24:30: 24:31 (#4), + }, + ], + span: $DIR/dollar-crate.rs:24:21: 24:32 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate.rs:24:32: 24:33 (#4), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ; +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate.rs:27:13: 27:19 (#4), + }, + Ident { + ident: "D", + span: $DIR/dollar-crate.rs:27:20: 27:21 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate.rs:27:22: 27:28 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate.rs:27:28: 27:30 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate.rs:27:28: 27:30 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate.rs:27:30: 27:31 (#4), + }, + ], + span: $DIR/dollar-crate.rs:27:21: 27:32 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate.rs:27:32: 27:33 (#4), + }, +] +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/dollar-crate-external.rs:7:13: 7:19 (#15), + }, + Ident { + ident: "M", + span: $DIR/auxiliary/dollar-crate-external.rs:7:20: 7:21 (#15), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/auxiliary/dollar-crate-external.rs:7:22: 7:28 (#15), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/auxiliary/dollar-crate-external.rs:7:28: 7:30 (#15), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:7:28: 7:30 (#15), + }, + Ident { + ident: "S", + span: $DIR/auxiliary/dollar-crate-external.rs:7:30: 7:31 (#15), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:7:21: 7:32 (#15), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:7:32: 7:33 (#15), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/dollar-crate-external.rs:11:9: 11:15 (#15), + }, + Ident { + ident: "A", + span: $DIR/auxiliary/dollar-crate-external.rs:11:16: 11:17 (#15), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/auxiliary/dollar-crate-external.rs:11:18: 11:24 (#15), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/auxiliary/dollar-crate-external.rs:11:24: 11:26 (#15), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:11:24: 11:26 (#15), + }, + Ident { + ident: "S", + span: $DIR/auxiliary/dollar-crate-external.rs:11:26: 11:27 (#15), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:11:17: 11:28 (#15), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:11:28: 11:29 (#15), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ; +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/dollar-crate-external.rs:14:9: 14:15 (#15), + }, + Ident { + ident: "D", + span: $DIR/auxiliary/dollar-crate-external.rs:14:16: 14:17 (#15), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/auxiliary/dollar-crate-external.rs:14:18: 14:24 (#15), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/auxiliary/dollar-crate-external.rs:14:24: 14:26 (#15), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:14:24: 14:26 (#15), + }, + Ident { + ident: "S", + span: $DIR/auxiliary/dollar-crate-external.rs:14:26: 14:27 (#15), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:14:17: 14:28 (#15), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:14:28: 14:29 (#15), + }, +] diff --git a/src/test/ui/proc-macro/edition-imports-2018.rs b/src/test/ui/proc-macro/edition-imports-2018.rs new file mode 100644 index 000000000..5a77cd4ef --- /dev/null +++ b/src/test/ui/proc-macro/edition-imports-2018.rs @@ -0,0 +1,24 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 +// aux-build:edition-imports-2015.rs + +#[macro_use] +extern crate edition_imports_2015; + +mod import { + pub struct Path; +} +mod absolute { + pub struct Path; +} + +mod check { + #[derive(Derive2015)] // OK + struct S; + + fn check() { + Path; + } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/empty-crate.rs b/src/test/ui/proc-macro/empty-crate.rs new file mode 100644 index 000000000..3e54c9fee --- /dev/null +++ b/src/test/ui/proc-macro/empty-crate.rs @@ -0,0 +1,9 @@ +// run-pass + +#![allow(unused_imports)] +// aux-build:empty-crate.rs + +#[macro_use] +extern crate empty_crate; + +fn main() {} diff --git a/src/test/ui/proc-macro/empty-where-clause.rs b/src/test/ui/proc-macro/empty-where-clause.rs new file mode 100644 index 000000000..719555c09 --- /dev/null +++ b/src/test/ui/proc-macro/empty-where-clause.rs @@ -0,0 +1,18 @@ +// aux-build:test-macros.rs + +extern crate test_macros; +use test_macros::recollect_attr; + +#[recollect_attr] +struct FieldStruct where { + field: MissingType1 //~ ERROR cannot find +} + +#[recollect_attr] +struct TupleStruct(MissingType2) where; //~ ERROR cannot find + +enum MyEnum where { + Variant(MissingType3) //~ ERROR cannot find +} + +fn main() {} diff --git a/src/test/ui/proc-macro/empty-where-clause.stderr b/src/test/ui/proc-macro/empty-where-clause.stderr new file mode 100644 index 000000000..192a2b30f --- /dev/null +++ b/src/test/ui/proc-macro/empty-where-clause.stderr @@ -0,0 +1,21 @@ +error[E0412]: cannot find type `MissingType1` in this scope + --> $DIR/empty-where-clause.rs:8:12 + | +LL | field: MissingType1 + | ^^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `MissingType2` in this scope + --> $DIR/empty-where-clause.rs:12:20 + | +LL | struct TupleStruct(MissingType2) where; + | ^^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `MissingType3` in this scope + --> $DIR/empty-where-clause.rs:15:13 + | +LL | Variant(MissingType3) + | ^^^^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/proc-macro/expand-expr.rs b/src/test/ui/proc-macro/expand-expr.rs new file mode 100644 index 000000000..d1146d970 --- /dev/null +++ b/src/test/ui/proc-macro/expand-expr.rs @@ -0,0 +1,121 @@ +// aux-build:expand-expr.rs + +extern crate expand_expr; + +use expand_expr::{ + check_expand_expr_file, echo_pm, expand_expr_fail, expand_expr_is, recursive_expand, +}; + +// Check builtin macros can be expanded. + +expand_expr_is!(11u32, line!()); +expand_expr_is!(24u32, column!()); + +expand_expr_is!("Hello, World!", concat!("Hello, ", "World", "!")); +expand_expr_is!("int10floats5.3booltrue", concat!("int", 10, "floats", 5.3, "bool", true)); +expand_expr_is!("Hello", concat!(r##"Hello"##)); + +expand_expr_is!("Included file contents\n", include_str!("auxiliary/included-file.txt")); +expand_expr_is!(b"Included file contents\n", include_bytes!("auxiliary/included-file.txt")); + +expand_expr_is!( + "contents: Included file contents\n", + concat!("contents: ", include_str!("auxiliary/included-file.txt")) +); + +// Correct value is checked for multiple sources. +check_expand_expr_file!(file!()); + +expand_expr_is!("hello", stringify!(hello)); +expand_expr_is!("10 + 20", stringify!(10 + 20)); + +macro_rules! echo_tts { + ($($t:tt)*) => { $($t)* }; //~ ERROR: expected expression, found `$` +} + +macro_rules! echo_lit { + ($l:literal) => { + $l + }; +} + +macro_rules! echo_expr { + ($e:expr) => { + $e + }; +} + +macro_rules! simple_lit { + ($l:literal) => { + expand_expr_is!($l, $l); + expand_expr_is!($l, echo_lit!($l)); + expand_expr_is!($l, echo_expr!($l)); + expand_expr_is!($l, echo_tts!($l)); + expand_expr_is!($l, echo_pm!($l)); + const _: () = { + macro_rules! mac { + () => { + $l + }; + } + expand_expr_is!($l, mac!()); + expand_expr_is!($l, echo_expr!(mac!())); + expand_expr_is!($l, echo_tts!(mac!())); + expand_expr_is!($l, echo_pm!(mac!())); + }; + }; +} + +simple_lit!("Hello, World"); +simple_lit!('c'); +simple_lit!(b'c'); +simple_lit!(10); +simple_lit!(10.0); +simple_lit!(10.0f64); +simple_lit!(-3.14159); +simple_lit!(-3.5e10); +simple_lit!(0xFEED); +simple_lit!(-0xFEED); +simple_lit!(0b0100); +simple_lit!(-0b0100); +simple_lit!("string"); +simple_lit!(r##"raw string"##); +simple_lit!(b"byte string"); +simple_lit!(br##"raw byte string"##); +simple_lit!(true); +simple_lit!(false); + +// Ensure char escapes aren't normalized by expansion +simple_lit!("\u{0}"); +simple_lit!("\0"); +simple_lit!("\x00"); +simple_lit!('\u{0}'); +simple_lit!('\0'); +simple_lit!('\x00'); +simple_lit!(b"\x00"); +simple_lit!(b"\0"); +simple_lit!(b'\x00'); +simple_lit!(b'\0'); + +// Extra tokens after the string literal aren't ignored +expand_expr_fail!("string"; hello); //~ ERROR: expected one of `.`, `?`, or an operator, found `;` + +// Invalid expressions produce errors in addition to returning `Err(())`. +expand_expr_fail!($); //~ ERROR: expected expression, found `$` +expand_expr_fail!(echo_tts!($)); +expand_expr_fail!(echo_pm!($)); //~ ERROR: expected expression, found `$` + +// We get errors reported and recover during macro expansion if the macro +// doesn't produce a valid expression. +expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores token `hello` and any following +expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores token `;` and any following + +// For now, fail if a non-literal expression is expanded. +expand_expr_fail!(arbitrary_expression() + "etc"); +expand_expr_fail!(echo_tts!(arbitrary_expression() + "etc")); +expand_expr_fail!(echo_expr!(arbitrary_expression() + "etc")); +expand_expr_fail!(echo_pm!(arbitrary_expression() + "etc")); + +const _: u32 = recursive_expand!(); //~ ERROR: recursion limit reached while expanding `recursive_expand!` + +fn main() {} diff --git a/src/test/ui/proc-macro/expand-expr.stderr b/src/test/ui/proc-macro/expand-expr.stderr new file mode 100644 index 000000000..8dc2d0cfc --- /dev/null +++ b/src/test/ui/proc-macro/expand-expr.stderr @@ -0,0 +1,55 @@ +error: expected one of `.`, `?`, or an operator, found `;` + --> $DIR/expand-expr.rs:101:27 + | +LL | expand_expr_fail!("string"; hello); + | ^ expected one of `.`, `?`, or an operator + +error: expected expression, found `$` + --> $DIR/expand-expr.rs:104:19 + | +LL | expand_expr_fail!($); + | ^ expected expression + +error: expected expression, found `$` + --> $DIR/expand-expr.rs:33:23 + | +LL | ($($t:tt)*) => { $($t)* }; + | ^^^^ expected expression + +error: expected expression, found `$` + --> $DIR/expand-expr.rs:106:28 + | +LL | expand_expr_fail!(echo_pm!($)); + | ^ expected expression + +error: macro expansion ignores token `hello` and any following + --> $DIR/expand-expr.rs:110:47 + | +LL | expand_expr_is!("string", echo_tts!("string"; hello)); + | --------------------^^^^^-- help: you might be missing a semicolon here: `;` + | | + | caused by the macro expansion here + | + = note: the usage of `echo_tts!` is likely invalid in expression context + +error: macro expansion ignores token `;` and any following + --> $DIR/expand-expr.rs:111:44 + | +LL | expand_expr_is!("string", echo_pm!("string"; hello)); + | -----------------^-------- help: you might be missing a semicolon here: `;` + | | + | caused by the macro expansion here + | + = note: the usage of `echo_pm!` is likely invalid in expression context + +error: recursion limit reached while expanding `recursive_expand!` + --> $DIR/expand-expr.rs:119:16 + | +LL | const _: u32 = recursive_expand!(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`expand_expr`) + = note: this error originates in the macro `recursive_expand` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/proc-macro/expand-to-derive.rs b/src/test/ui/proc-macro/expand-to-derive.rs new file mode 100644 index 000000000..ff2876e84 --- /dev/null +++ b/src/test/ui/proc-macro/expand-to-derive.rs @@ -0,0 +1,34 @@ +// check-pass +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs + +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! expand_to_derive { + ($item:item) => { + #[derive(Print)] + struct Foo { + #[cfg(FALSE)] removed: bool, + field: [bool; { + $item + 0 + }] + } + }; +} + +expand_to_derive! { + #[cfg_attr(not(FALSE), rustc_dummy)] + struct Inner { + #[cfg(FALSE)] removed_inner_field: bool, + other_inner_field: u8, + } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/expand-to-derive.stdout b/src/test/ui/proc-macro/expand-to-derive.stdout new file mode 100644 index 000000000..a6437982a --- /dev/null +++ b/src/test/ui/proc-macro/expand-to-derive.stdout @@ -0,0 +1,104 @@ +PRINT-DERIVE INPUT (DISPLAY): struct Foo +{ + field : + [bool ; { #[rustc_dummy] struct Inner { other_inner_field : u8, } 0 }] +} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/expand-to-derive.rs:16:9: 16:15 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/expand-to-derive.rs:16:16: 16:19 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/expand-to-derive.rs:18:13: 18:18 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/expand-to-derive.rs:18:18: 18:19 (#4), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "bool", + span: $DIR/expand-to-derive.rs:18:21: 18:25 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/expand-to-derive.rs:18:25: 18:26 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/expand-to-derive.rs:27:28: 27:39 (#0), + }, + ], + span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0), + }, + Ident { + ident: "struct", + span: $DIR/expand-to-derive.rs:28:5: 28:11 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/expand-to-derive.rs:28:12: 28:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "other_inner_field", + span: $DIR/expand-to-derive.rs:30:9: 30:26 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/expand-to-derive.rs:30:26: 30:27 (#0), + }, + Ident { + ident: "u8", + span: $DIR/expand-to-derive.rs:30:28: 30:30 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/expand-to-derive.rs:30:30: 30:31 (#0), + }, + ], + span: $DIR/expand-to-derive.rs:28:18: 31:6 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/expand-to-derive.rs:20:17: 20:18 (#4), + }, + ], + span: $DIR/expand-to-derive.rs:18:27: 21:14 (#4), + }, + ], + span: $DIR/expand-to-derive.rs:18:20: 21:15 (#4), + }, + ], + span: $DIR/expand-to-derive.rs:16:20: 22:10 (#4), + }, +] diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.rs b/src/test/ui/proc-macro/expand-to-unstable-2.rs new file mode 100644 index 000000000..4160e5418 --- /dev/null +++ b/src/test/ui/proc-macro/expand-to-unstable-2.rs @@ -0,0 +1,17 @@ +// aux-build:derive-unstable-2.rs + +#![feature(register_attr)] + +#![register_attr(rustc_foo)] + +#[macro_use] +extern crate derive_unstable_2; + +#[derive(Unstable)] +//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler + +struct A; + +fn main() { + foo(); +} diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.stderr b/src/test/ui/proc-macro/expand-to-unstable-2.stderr new file mode 100644 index 000000000..8b16ffb76 --- /dev/null +++ b/src/test/ui/proc-macro/expand-to-unstable-2.stderr @@ -0,0 +1,10 @@ +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler + --> $DIR/expand-to-unstable-2.rs:10:10 + | +LL | #[derive(Unstable)] + | ^^^^^^^^ + | + = note: this error originates in the derive macro `Unstable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/expand-to-unstable.rs b/src/test/ui/proc-macro/expand-to-unstable.rs new file mode 100644 index 000000000..0825c1a8e --- /dev/null +++ b/src/test/ui/proc-macro/expand-to-unstable.rs @@ -0,0 +1,14 @@ +// aux-build:derive-unstable.rs + +#![allow(warnings)] + +#[macro_use] +extern crate derive_unstable; + +#[derive(Unstable)] +//~^ ERROR: use of unstable library feature +struct A; + +fn main() { + unsafe { foo(); } +} diff --git a/src/test/ui/proc-macro/expand-to-unstable.stderr b/src/test/ui/proc-macro/expand-to-unstable.stderr new file mode 100644 index 000000000..b27dcd7e6 --- /dev/null +++ b/src/test/ui/proc-macro/expand-to-unstable.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library + --> $DIR/expand-to-unstable.rs:8:10 + | +LL | #[derive(Unstable)] + | ^^^^^^^^ + | + = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable + = note: this error originates in the derive macro `Unstable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/expand-with-a-macro.rs b/src/test/ui/proc-macro/expand-with-a-macro.rs new file mode 100644 index 000000000..21a4547d1 --- /dev/null +++ b/src/test/ui/proc-macro/expand-with-a-macro.rs @@ -0,0 +1,21 @@ +// run-pass +// needs-unwind +// aux-build:expand-with-a-macro.rs + +// ignore-wasm32-bare compiled with panic=abort by default + +#![deny(warnings)] + +#[macro_use] +extern crate expand_with_a_macro; + +use std::panic; + +#[derive(A)] +struct A; + +fn main() { + assert!(panic::catch_unwind(|| { + A.a(); + }).is_err()); +} diff --git a/src/test/ui/proc-macro/export-macro.rs b/src/test/ui/proc-macro/export-macro.rs new file mode 100644 index 000000000..ad69fe5ee --- /dev/null +++ b/src/test/ui/proc-macro/export-macro.rs @@ -0,0 +1,11 @@ +// error-pattern: cannot export macro_rules! macros from a `proc-macro` crate + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +#[macro_export] +macro_rules! foo { + ($e:expr) => ($e) +} diff --git a/src/test/ui/proc-macro/export-macro.stderr b/src/test/ui/proc-macro/export-macro.stderr new file mode 100644 index 000000000..36a6a9bb3 --- /dev/null +++ b/src/test/ui/proc-macro/export-macro.stderr @@ -0,0 +1,8 @@ +error: cannot export macro_rules! macros from a `proc-macro` crate type currently + --> $DIR/export-macro.rs:9:1 + | +LL | macro_rules! foo { + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/exports.rs b/src/test/ui/proc-macro/exports.rs new file mode 100644 index 000000000..a40c15908 --- /dev/null +++ b/src/test/ui/proc-macro/exports.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![allow(warnings)] + +pub fn a() {} //~ ERROR: cannot export any items +pub struct B; //~ ERROR: cannot export any items +pub enum C {} //~ ERROR: cannot export any items +pub mod d {} //~ ERROR: cannot export any items + +mod e {} +struct F; +enum G {} +fn h() {} diff --git a/src/test/ui/proc-macro/exports.stderr b/src/test/ui/proc-macro/exports.stderr new file mode 100644 index 000000000..7b23d08f2 --- /dev/null +++ b/src/test/ui/proc-macro/exports.stderr @@ -0,0 +1,26 @@ +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/exports.rs:7:1 + | +LL | pub fn a() {} + | ^^^^^^^^^^ + +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/exports.rs:8:1 + | +LL | pub struct B; + | ^^^^^^^^^^^^^ + +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/exports.rs:9:1 + | +LL | pub enum C {} + | ^^^^^^^^^^ + +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/exports.rs:10:1 + | +LL | pub mod d {} + | ^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs new file mode 100644 index 000000000..d4067a335 --- /dev/null +++ b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs @@ -0,0 +1,37 @@ +// check-pass +// aux-build:test-macros.rs + +#![feature(decl_macro)] +#![feature(stmt_expr_attributes)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro mac { + (expr $expr:expr) => { + #[derive(Print)] + enum E { + V = { let _ = $expr; 0 }, + } + }, + (stmt $stmt:stmt) => { + #[derive(Print)] + enum E { + V = { let _ = { $stmt }; 0 }, + } + }, +} + +const PATH: u8 = 2; + +fn main() { + mac!(expr #[allow(warnings)] 0); + mac!(stmt 0); + mac!(stmt {}); + mac!(stmt PATH); + mac!(stmt 0 + 1); + mac!(stmt PATH + 1); +} diff --git a/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout new file mode 100644 index 000000000..686d53e88 --- /dev/null +++ b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout @@ -0,0 +1,540 @@ +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0 ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = #[allow(warnings)] #[allow(warnings)] 0 ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #4 bytes(299..303), + }, + Ident { + ident: "E", + span: #4 bytes(304..305), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #4 bytes(320..321), + }, + Punct { + ch: '=', + spacing: Alone, + span: #4 bytes(322..323), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #4 bytes(326..329), + }, + Ident { + ident: "_", + span: #4 bytes(330..331), + }, + Punct { + ch: '=', + spacing: Alone, + span: #4 bytes(332..333), + }, + Group { + delimiter: None, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: #0 bytes(541..542), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: #0 bytes(543..548), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: #0 bytes(549..557), + }, + ], + span: #0 bytes(548..558), + }, + ], + span: #0 bytes(542..559), + }, + Punct { + ch: '#', + spacing: Alone, + span: #0 bytes(541..542), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: #0 bytes(543..548), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: #0 bytes(549..557), + }, + ], + span: #0 bytes(548..558), + }, + ], + span: #0 bytes(542..559), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(560..561), + }, + ], + span: #4 bytes(334..339), + }, + Punct { + ch: ';', + spacing: Alone, + span: #4 bytes(339..340), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #4 bytes(341..342), + }, + ], + span: #4 bytes(324..344), + }, + Punct { + ch: ',', + spacing: Alone, + span: #4 bytes(344..345), + }, + ], + span: #4 bytes(306..355), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0; } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #8 bytes(423..427), + }, + Ident { + ident: "E", + span: #8 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #8 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #8 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #8 bytes(450..453), + }, + Ident { + ident: "_", + span: #8 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #8 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(578..579), + }, + ], + span: #8 bytes(460..465), + }, + ], + span: #8 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #8 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #8 bytes(469..470), + }, + ], + span: #8 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #8 bytes(472..473), + }, + ], + span: #8 bytes(430..483), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { {} } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #12 bytes(423..427), + }, + Ident { + ident: "E", + span: #12 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #12 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #12 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #12 bytes(450..453), + }, + Ident { + ident: "_", + span: #12 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #12 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: Brace, + stream: TokenStream [], + span: #0 bytes(596..598), + }, + ], + span: #12 bytes(460..465), + }, + ], + span: #12 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #12 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #12 bytes(469..470), + }, + ], + span: #12 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #12 bytes(472..473), + }, + ], + span: #12 bytes(430..483), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH; } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #16 bytes(423..427), + }, + Ident { + ident: "E", + span: #16 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #16 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #16 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #16 bytes(450..453), + }, + Ident { + ident: "_", + span: #16 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #16 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "PATH", + span: #0 bytes(615..619), + }, + ], + span: #16 bytes(460..465), + }, + ], + span: #16 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #16 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #16 bytes(469..470), + }, + ], + span: #16 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #16 bytes(472..473), + }, + ], + span: #16 bytes(430..483), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1; } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 + 1 } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #20 bytes(423..427), + }, + Ident { + ident: "E", + span: #20 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #20 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #20 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #20 bytes(450..453), + }, + Ident { + ident: "_", + span: #20 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #20 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(636..637), + }, + Punct { + ch: '+', + spacing: Alone, + span: #0 bytes(638..639), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: #0 bytes(640..641), + }, + ], + span: #20 bytes(460..465), + }, + ], + span: #20 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #20 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #20 bytes(469..470), + }, + ], + span: #20 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #20 bytes(472..473), + }, + ], + span: #20 bytes(430..483), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1; } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH + 1 } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #24 bytes(423..427), + }, + Ident { + ident: "E", + span: #24 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #24 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #24 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #24 bytes(450..453), + }, + Ident { + ident: "_", + span: #24 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #24 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "PATH", + span: #0 bytes(658..662), + }, + Punct { + ch: '+', + spacing: Alone, + span: #0 bytes(663..664), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: #0 bytes(665..666), + }, + ], + span: #24 bytes(460..465), + }, + ], + span: #24 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #24 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #24 bytes(469..470), + }, + ], + span: #24 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #24 bytes(472..473), + }, + ], + span: #24 bytes(430..483), + }, +] diff --git a/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs b/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs new file mode 100644 index 000000000..a6e64e1b1 --- /dev/null +++ b/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs @@ -0,0 +1,7 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +extern crate proc_macro; +use proc_macro::TokenStream; // OK + +fn main() {} diff --git a/src/test/ui/proc-macro/gen-lifetime-token.rs b/src/test/ui/proc-macro/gen-lifetime-token.rs new file mode 100644 index 000000000..588bd2b76 --- /dev/null +++ b/src/test/ui/proc-macro/gen-lifetime-token.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:gen-lifetime-token.rs + +extern crate gen_lifetime_token as bar; + +bar::bar!(); + +fn main() { + let x: &'static i32 = FOO; + assert_eq!(*x, 1); +} diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs new file mode 100644 index 000000000..195bda82e --- /dev/null +++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs @@ -0,0 +1,23 @@ +// `macro_rules` items produced by transparent macros have correct hygiene in basic cases. +// Local variables and labels are hygienic, items are not hygienic. +// `$crate` refers to the crate that defines `macro_rules` and not the outer transparent macro. + +// aux-build:gen-macro-rules-hygiene.rs + +#[macro_use] +extern crate gen_macro_rules_hygiene; + +struct ItemUse; + +gen_macro_rules!(); +//~^ ERROR use of undeclared label `'label_use` +//~| ERROR cannot find value `local_use` in this scope + +fn main() { + 'label_use: loop { + let local_use = 1; + generated!(); + ItemDef; // OK + local_def; //~ ERROR cannot find value `local_def` in this scope + } +} diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr new file mode 100644 index 000000000..6060f872f --- /dev/null +++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr @@ -0,0 +1,32 @@ +error[E0426]: use of undeclared label `'label_use` + --> $DIR/gen-macro-rules-hygiene.rs:12:1 + | +LL | gen_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` +... +LL | generated!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `local_use` in this scope + --> $DIR/gen-macro-rules-hygiene.rs:12:1 + | +LL | gen_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^ not found in this scope +... +LL | generated!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `local_def` in this scope + --> $DIR/gen-macro-rules-hygiene.rs:21:9 + | +LL | local_def; + | ^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0426. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/proc-macro/gen-macro-rules.rs b/src/test/ui/proc-macro/gen-macro-rules.rs new file mode 100644 index 000000000..13ad27f93 --- /dev/null +++ b/src/test/ui/proc-macro/gen-macro-rules.rs @@ -0,0 +1,13 @@ +// Derive macros can generate `macro_rules` items, regression test for issue #63651. + +// check-pass +// aux-build:gen-macro-rules.rs + +extern crate gen_macro_rules as repro; + +#[derive(repro::repro)] +pub struct S; + +m!(); // OK + +fn main() {} diff --git a/src/test/ui/proc-macro/generate-dollar-ident.rs b/src/test/ui/proc-macro/generate-dollar-ident.rs new file mode 100644 index 000000000..b838be9fb --- /dev/null +++ b/src/test/ui/proc-macro/generate-dollar-ident.rs @@ -0,0 +1,18 @@ +// Proc macros can generate token sequence `$ IDENT` +// without it being recognized as an unknown macro variable. + +// check-pass +// aux-build:generate-dollar-ident.rs + +extern crate generate_dollar_ident; +use generate_dollar_ident::*; + +macro_rules! black_hole { + ($($tt:tt)*) => {}; +} + +black_hole!($var); + +dollar_ident!(black_hole); + +fn main() {} diff --git a/src/test/ui/proc-macro/generate-mod.rs b/src/test/ui/proc-macro/generate-mod.rs new file mode 100644 index 000000000..471f317ed --- /dev/null +++ b/src/test/ui/proc-macro/generate-mod.rs @@ -0,0 +1,33 @@ +// Modules generated by transparent proc macros still acts as barriers for names (issue #50504). + +// aux-build:generate-mod.rs + +extern crate generate_mod; + +struct FromOutside; + +generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `Outer` in this scope + +#[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `OuterAttr` in this scope +struct S; + +#[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `OuterDerive` in this scope + //~| WARN this was previously accepted + //~| WARN this was previously accepted +struct Z; + +fn inner_block() { + #[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `OuterDerive` in this scope + //~| WARN this was previously accepted + //~| WARN this was previously accepted + struct InnerZ; +} + +#[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed +struct W; + +fn main() {} diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr new file mode 100644 index 000000000..f1a167e37 --- /dev/null +++ b/src/test/ui/proc-macro/generate-mod.stderr @@ -0,0 +1,164 @@ +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:9:1 + | +LL | generate_mod::check!(); + | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: consider importing this struct: + FromOutside + = note: this error originates in the macro `generate_mod::check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `Outer` in this scope + --> $DIR/generate-mod.rs:9:1 + | +LL | generate_mod::check!(); + | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: consider importing this struct: + Outer + = note: this error originates in the macro `generate_mod::check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:12:1 + | +LL | #[generate_mod::check_attr] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: consider importing this struct: + FromOutside + = note: this error originates in the attribute macro `generate_mod::check_attr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `OuterAttr` in this scope + --> $DIR/generate-mod.rs:12:1 + | +LL | #[generate_mod::check_attr] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: consider importing this struct: + OuterAttr + = note: this error originates in the attribute macro `generate_mod::check_attr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0412`. +Future incompatibility report: Future breakage diagnostic: +error: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +error: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +error: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +error: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | +note: the lint level is defined here + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `OuterDeriveLint` in this scope + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | +note: the lint level is defined here + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = 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 #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs new file mode 100644 index 000000000..40c42d82f --- /dev/null +++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs @@ -0,0 +1,13 @@ +// aux-build:test-macros.rs + +#[macro_use(Empty)] +extern crate test_macros; +use test_macros::empty_attr as empty_helper; + +#[empty_helper] //~ ERROR `empty_helper` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[derive(Empty)] +struct S; + +fn main() {} diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr new file mode 100644 index 000000000..45b014c4b --- /dev/null +++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr @@ -0,0 +1,35 @@ +error[E0659]: `empty_helper` is ambiguous + --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/helper-attr-blocked-by-import-ambig.rs:10:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/helper-attr-blocked-by-import-ambig.rs:5:5 + | +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously + +warning: derive helper attribute is used before it is introduced + --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ +... +LL | #[derive(Empty)] + | ----- the attribute is introduced here + | + = note: `#[warn(legacy_derive_helpers)]` on by default + = 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 #79202 <https://github.com/rust-lang/rust/issues/79202> + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs b/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs new file mode 100644 index 000000000..2e20a3de6 --- /dev/null +++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs @@ -0,0 +1,28 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +#[macro_use(Empty)] +extern crate test_macros; + +use self::one::*; +use self::two::*; + +mod empty_helper {} + +mod one { + use empty_helper; + + #[derive(Empty)] + #[empty_helper] + struct One; +} + +mod two { + use empty_helper; + + #[derive(Empty)] + #[empty_helper] + struct Two; +} + +fn main() {} diff --git a/src/test/ui/proc-macro/hygiene_example.rs b/src/test/ui/proc-macro/hygiene_example.rs new file mode 100644 index 000000000..346ed1207 --- /dev/null +++ b/src/test/ui/proc-macro/hygiene_example.rs @@ -0,0 +1,16 @@ +// check-pass +// aux-build:hygiene_example_codegen.rs +// aux-build:hygiene_example.rs + +extern crate hygiene_example; +use hygiene_example::hello; + +fn main() { + mod hygiene_example {} // no conflict with `extern crate hygiene_example;` from the proc macro + macro_rules! format { () => {} } // does not interfere with `format!` from the proc macro + macro_rules! hello_helper { () => {} } // similarly does not intefere with the proc macro + + let string = "world"; // no conflict with `string` from the proc macro + hello!(string); + hello!(string); +} diff --git a/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs new file mode 100644 index 000000000..4efd9e952 --- /dev/null +++ b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs @@ -0,0 +1,15 @@ +extern crate proc_macro; + +#[proc_macro_derive(Foo)] +//~^ ERROR: only usable with crates of the `proc-macro` crate type +pub fn foo(a: proc_macro::TokenStream) -> proc_macro::TokenStream { + a +} + +// Issue #37590 +#[proc_macro_derive(Foo)] +//~^ ERROR: the `#[proc_macro_derive]` attribute may only be used on bare functions +pub struct Foo { +} + +fn main() {} diff --git a/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr new file mode 100644 index 000000000..c0930ab71 --- /dev/null +++ b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr @@ -0,0 +1,14 @@ +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/illegal-proc-macro-derive-use.rs:3:1 + | +LL | #[proc_macro_derive(Foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/illegal-proc-macro-derive-use.rs:10:1 + | +LL | #[proc_macro_derive(Foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/proc-macro/import.rs b/src/test/ui/proc-macro/import.rs new file mode 100644 index 000000000..d1b1ff350 --- /dev/null +++ b/src/test/ui/proc-macro/import.rs @@ -0,0 +1,8 @@ +// aux-build:test-macros.rs + +extern crate test_macros; + +use test_macros::empty_derive; +//~^ ERROR: unresolved import `test_macros::empty_derive` + +fn main() {} diff --git a/src/test/ui/proc-macro/import.stderr b/src/test/ui/proc-macro/import.stderr new file mode 100644 index 000000000..aae621193 --- /dev/null +++ b/src/test/ui/proc-macro/import.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `test_macros::empty_derive` + --> $DIR/import.rs:5:5 + | +LL | use test_macros::empty_derive; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ no `empty_derive` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/proc-macro/inert-attribute-order.rs b/src/test/ui/proc-macro/inert-attribute-order.rs new file mode 100644 index 000000000..f80796756 --- /dev/null +++ b/src/test/ui/proc-macro/inert-attribute-order.rs @@ -0,0 +1,23 @@ +// Order of inert attributes, both built-in and custom is preserved during expansion. + +// check-pass +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +/// 1 +#[rustfmt::attr2] +#[doc = "3"] +#[print_attr(nodebug)] +#[doc = "4"] +#[rustfmt::attr5] +/// 6 +#[print_attr(nodebug)] +struct S; + +fn main() {} diff --git a/src/test/ui/proc-macro/inert-attribute-order.stdout b/src/test/ui/proc-macro/inert-attribute-order.stdout new file mode 100644 index 000000000..cc2155459 --- /dev/null +++ b/src/test/ui/proc-macro/inert-attribute-order.stdout @@ -0,0 +1,7 @@ +PRINT-ATTR INPUT (DISPLAY): /// 1 +#[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] #[rustfmt :: attr5] /// 6 +#[print_attr(nodebug)] struct S ; +PRINT-ATTR RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] +#[rustfmt :: attr5] #[doc = " 6"] #[print_attr(nodebug)] struct S ; +PRINT-ATTR INPUT (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] +#[rustfmt :: attr5] #[doc = " 6"] struct S ; diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.rs b/src/test/ui/proc-macro/inner-attr-non-inline-mod.rs new file mode 100644 index 000000000..30c2666df --- /dev/null +++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z span-debug +// error-pattern:custom inner attributes are unstable +// error-pattern:inner macro attributes are unstable +// error-pattern:this was previously accepted +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[deny(unused_attributes)] +mod module_with_attrs; +//~^ ERROR non-inline modules in proc macro input are unstable +//~| ERROR custom inner attributes are unstable + +fn main() {} diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr new file mode 100644 index 000000000..4286896df --- /dev/null +++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr @@ -0,0 +1,40 @@ +error[E0658]: inner macro attributes are unstable + --> $DIR/module_with_attrs.rs:4:4 + | +LL | #![print_attr] + | ^^^^^^^^^^ + | + = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/inner-attr-non-inline-mod.rs:14:1 + | +LL | mod module_with_attrs; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom inner attributes are unstable + --> $DIR/inner-attr-non-inline-mod.rs:14:1 + | +LL | mod module_with_attrs; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + +error: custom inner attributes are unstable + --> $DIR/module_with_attrs.rs:3:4 + | +LL | #![rustfmt::skip] + | ^^^^^^^^^^^^^ + | + = note: `#[deny(soft_unstable)]` on by default + = 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 #64266 <https://github.com/rust-lang/rust/issues/64266> + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout new file mode 100644 index 000000000..6261d82e2 --- /dev/null +++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout @@ -0,0 +1,76 @@ +PRINT-ATTR INPUT (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #! [rustfmt :: skip] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "deny", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "unused_attributes", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + ], + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + ], + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Ident { + ident: "mod", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Ident { + ident: "module_with_attrs", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustfmt", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Ident { + ident: "skip", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + ], + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + ], + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, +] diff --git a/src/test/ui/proc-macro/inner-attrs.rs b/src/test/ui/proc-macro/inner-attrs.rs new file mode 100644 index 000000000..2e3c704da --- /dev/null +++ b/src/test/ui/proc-macro/inner-attrs.rs @@ -0,0 +1,86 @@ +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs +// edition:2018 + +#![feature(custom_inner_attributes)] +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[print_target_and_args(first)] +#[print_target_and_args(second)] +fn foo() { + #![print_target_and_args(third)] + #![print_target_and_args(fourth)] +} + +#[print_target_and_args(mod_first)] +#[print_target_and_args(mod_second)] +mod inline_mod { + #![print_target_and_args(mod_third)] + #![print_target_and_args(mod_fourth)] +} + +struct MyStruct { + field: bool +} + +#[derive(Print)] +struct MyDerivePrint { + field: [u8; { + match true { + _ => { + #![cfg_attr(not(FALSE), rustc_dummy(third))] + true + } + }; + 0 + }] +} + +fn bar() { + #[print_target_and_args(tuple_attrs)] ( + 3, 4, { + #![cfg_attr(not(FALSE), rustc_dummy(innermost))] + 5 + } + ); + + #[print_target_and_args(tuple_attrs)] ( + 3, 4, { + #![cfg_attr(not(FALSE), rustc_dummy(innermost))] + 5 + } + ); + + for _ in &[true] { + #![print_attr] //~ ERROR expected non-macro inner attribute + } + + let _ = { + #![print_attr] //~ ERROR expected non-macro inner attribute + }; + + let _ = async { + #![print_attr] //~ ERROR expected non-macro inner attribute + }; + + { + #![print_attr] //~ ERROR expected non-macro inner attribute + }; +} + + +extern { + fn weird_extern() { + #![print_target_and_args_consume(tenth)] + } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/inner-attrs.stderr b/src/test/ui/proc-macro/inner-attrs.stderr new file mode 100644 index 000000000..4da8751ef --- /dev/null +++ b/src/test/ui/proc-macro/inner-attrs.stderr @@ -0,0 +1,26 @@ +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:63:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:67:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:71:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:75:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/proc-macro/inner-attrs.stdout b/src/test/ui/proc-macro/inner-attrs.stdout new file mode 100644 index 000000000..eaa8882d6 --- /dev/null +++ b/src/test/ui/proc-macro/inner-attrs.stdout @@ -0,0 +1,956 @@ +PRINT-ATTR_ARGS INPUT (DISPLAY): first +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "first", + span: $DIR/inner-attrs.rs:16:25: 16:30 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second)] fn foo() +{ #! [print_target_and_args(third)] #! [print_target_and_args(fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:17:1: 17:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:17:3: 17:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second", + span: $DIR/inner-attrs.rs:17:25: 17:31 (#0), + }, + ], + span: $DIR/inner-attrs.rs:17:24: 17:32 (#0), + }, + ], + span: $DIR/inner-attrs.rs:17:2: 17:33 (#0), + }, + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:18:1: 18:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/inner-attrs.rs:18:4: 18:7 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:18:7: 18:9 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:19:6: 19:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:19:8: 19:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:19:30: 19:35 (#0), + }, + ], + span: $DIR/inner-attrs.rs:19:29: 19:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:19:7: 19:37 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/inner-attrs.rs:20:30: 20:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:29: 20:37 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:7: 20:38 (#0), + }, + ], + span: $DIR/inner-attrs.rs:18:10: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): second +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "second", + span: $DIR/inner-attrs.rs:17:25: 17:31 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): fn foo() +{ #! [print_target_and_args(third)] #! [print_target_and_args(fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:18:1: 18:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/inner-attrs.rs:18:4: 18:7 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:18:7: 18:9 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:19:6: 19:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:19:8: 19:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:19:30: 19:35 (#0), + }, + ], + span: $DIR/inner-attrs.rs:19:29: 19:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:19:7: 19:37 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/inner-attrs.rs:20:30: 20:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:29: 20:37 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:7: 20:38 (#0), + }, + ], + span: $DIR/inner-attrs.rs:18:10: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): third +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:19:30: 19:35 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): fn foo() { #! [print_target_and_args(fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:18:1: 18:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/inner-attrs.rs:18:4: 18:7 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:18:7: 18:9 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/inner-attrs.rs:20:30: 20:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:29: 20:37 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:7: 20:38 (#0), + }, + ], + span: $DIR/inner-attrs.rs:18:10: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): fourth +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "fourth", + span: $DIR/inner-attrs.rs:20:30: 20:36 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): fn foo() {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:18:1: 18:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/inner-attrs.rs:18:4: 18:7 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:18:7: 18:9 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:18:10: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_first +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_first", + span: $DIR/inner-attrs.rs:23:25: 23:34 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(mod_second)] mod inline_mod +{ + #! [print_target_and_args(mod_third)] #! + [print_target_and_args(mod_fourth)] +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:24:1: 24:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:24:3: 24:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_second", + span: $DIR/inner-attrs.rs:24:25: 24:35 (#0), + }, + ], + span: $DIR/inner-attrs.rs:24:24: 24:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:24:2: 24:37 (#0), + }, + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:25:1: 25:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:25:5: 25:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:26:5: 26:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:26:6: 26:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:26:8: 26:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:26:30: 26:39 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:29: 26:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:7: 26:41 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:27:5: 27:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:27:6: 27:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:27:8: 27:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:27:30: 27:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:29: 27:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:7: 27:42 (#0), + }, + ], + span: $DIR/inner-attrs.rs:25:16: 28:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_second +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_second", + span: $DIR/inner-attrs.rs:24:25: 24:35 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): mod inline_mod +{ + #! [print_target_and_args(mod_third)] #! + [print_target_and_args(mod_fourth)] +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:25:1: 25:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:25:5: 25:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:26:5: 26:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:26:6: 26:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:26:8: 26:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:26:30: 26:39 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:29: 26:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:7: 26:41 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:27:5: 27:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:27:6: 27:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:27:8: 27:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:27:30: 27:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:29: 27:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:7: 27:42 (#0), + }, + ], + span: $DIR/inner-attrs.rs:25:16: 28:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_third +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:26:30: 26:39 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): mod inline_mod { #! [print_target_and_args(mod_fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:25:1: 25:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:25:5: 25:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:27:5: 27:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:27:6: 27:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:27:8: 27:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:27:30: 27:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:29: 27:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:7: 27:42 (#0), + }, + ], + span: $DIR/inner-attrs.rs:25:16: 28:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_fourth +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:27:30: 27:40 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): mod inline_mod {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:25:1: 25:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:25:5: 25:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:25:16: 28:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct MyDerivePrint +{ + field : + [u8 ; { match true { _ => { #! [rustc_dummy(third)] true } } ; 0 }] +} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/inner-attrs.rs:35:1: 35:7 (#0), + }, + Ident { + ident: "MyDerivePrint", + span: $DIR/inner-attrs.rs:35:8: 35:21 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/inner-attrs.rs:36:5: 36:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/inner-attrs.rs:36:10: 36:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/inner-attrs.rs:36:13: 36:15 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:36:15: 36:16 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "match", + span: $DIR/inner-attrs.rs:37:9: 37:14 (#0), + }, + Ident { + ident: "true", + span: $DIR/inner-attrs.rs:37:15: 37:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "_", + span: $DIR/inner-attrs.rs:38:13: 38:14 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/inner-attrs.rs:38:15: 38:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/inner-attrs.rs:38:15: 38:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:39:17: 39:18 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:39:18: 39:19 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:39:41: 39:52 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:39:53: 39:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:39:52: 39:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:39:17: 39:18 (#0), + }, + Ident { + ident: "true", + span: $DIR/inner-attrs.rs:40:17: 40:21 (#0), + }, + ], + span: $DIR/inner-attrs.rs:38:18: 41:14 (#0), + }, + ], + span: $DIR/inner-attrs.rs:37:20: 42:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:42:10: 42:11 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/inner-attrs.rs:43:9: 43:10 (#0), + }, + ], + span: $DIR/inner-attrs.rs:36:17: 44:6 (#0), + }, + ], + span: $DIR/inner-attrs.rs:36:12: 44:7 (#0), + }, + ], + span: $DIR/inner-attrs.rs:35:22: 45:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "tuple_attrs", + span: $DIR/inner-attrs.rs:48:29: 48:40 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "3", + suffix: None, + span: $DIR/inner-attrs.rs:49:9: 49:10 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:49:10: 49:11 (#0), + }, + Literal { + kind: Integer, + symbol: "4", + suffix: None, + span: $DIR/inner-attrs.rs:49:12: 49:13 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:49:13: 49:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:50:13: 50:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:50:14: 50:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/inner-attrs.rs:50:16: 50:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/inner-attrs.rs:50:25: 50:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/inner-attrs.rs:50:29: 50:34 (#0), + }, + ], + span: $DIR/inner-attrs.rs:50:28: 50:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:50:35: 50:36 (#0), + }, + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:50:37: 50:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "innermost", + span: $DIR/inner-attrs.rs:50:49: 50:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:50:48: 50:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:50:24: 50:60 (#0), + }, + ], + span: $DIR/inner-attrs.rs:50:15: 50:61 (#0), + }, + Literal { + kind: Integer, + symbol: "5", + suffix: None, + span: $DIR/inner-attrs.rs:51:13: 51:14 (#0), + }, + ], + span: $DIR/inner-attrs.rs:49:15: 52:10 (#0), + }, + ], + span: $DIR/inner-attrs.rs:48:43: 53:6 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:53:6: 53:7 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "tuple_attrs", + span: $DIR/inner-attrs.rs:55:29: 55:40 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "3", + suffix: None, + span: $DIR/inner-attrs.rs:56:9: 56:10 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:56:10: 56:11 (#0), + }, + Literal { + kind: Integer, + symbol: "4", + suffix: None, + span: $DIR/inner-attrs.rs:56:12: 56:13 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:56:13: 56:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:57:13: 57:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:57:14: 57:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/inner-attrs.rs:57:16: 57:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/inner-attrs.rs:57:25: 57:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/inner-attrs.rs:57:29: 57:34 (#0), + }, + ], + span: $DIR/inner-attrs.rs:57:28: 57:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:57:35: 57:36 (#0), + }, + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:57:37: 57:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "innermost", + span: $DIR/inner-attrs.rs:57:49: 57:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:57:48: 57:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:57:24: 57:60 (#0), + }, + ], + span: $DIR/inner-attrs.rs:57:15: 57:61 (#0), + }, + Literal { + kind: Integer, + symbol: "5", + suffix: None, + span: $DIR/inner-attrs.rs:58:13: 58:14 (#0), + }, + ], + span: $DIR/inner-attrs.rs:56:15: 59:10 (#0), + }, + ], + span: $DIR/inner-attrs.rs:55:43: 60:6 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:60:6: 60:7 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): tenth +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "tenth", + span: $DIR/inner-attrs.rs:82:42: 82:47 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): fn weird_extern() {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:81:5: 81:7 (#0), + }, + Ident { + ident: "weird_extern", + span: $DIR/inner-attrs.rs:81:8: 81:20 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:81:20: 81:22 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:81:23: 83:6 (#0), + }, +] diff --git a/src/test/ui/proc-macro/input-interpolated.rs b/src/test/ui/proc-macro/input-interpolated.rs new file mode 100644 index 000000000..5e49e330c --- /dev/null +++ b/src/test/ui/proc-macro/input-interpolated.rs @@ -0,0 +1,29 @@ +// Check what token streams proc macros see when interpolated tokens are passed to them as input. + +// check-pass +// edition:2018 +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! pass_ident { + ($i:ident) => { + fn f() { + print_bang!($i); + } + + #[print_attr] + const $i: u8 = 0; + + #[derive(Print)] + struct $i {} + }; +} + +pass_ident!(A); + +fn main() {} diff --git a/src/test/ui/proc-macro/input-interpolated.stdout b/src/test/ui/proc-macro/input-interpolated.stdout new file mode 100644 index 000000000..34566c780 --- /dev/null +++ b/src/test/ui/proc-macro/input-interpolated.stdout @@ -0,0 +1,59 @@ +PRINT-BANG INPUT (DISPLAY): A +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "A", + span: #0 bytes(503..504), + }, +] +PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0 ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "const", + span: #4 bytes(416..421), + }, + Ident { + ident: "A", + span: #0 bytes(503..504), + }, + Punct { + ch: ':', + spacing: Alone, + span: #4 bytes(424..425), + }, + Ident { + ident: "u8", + span: #4 bytes(426..428), + }, + Punct { + ch: '=', + spacing: Alone, + span: #4 bytes(429..430), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #4 bytes(431..432), + }, + Punct { + ch: ';', + spacing: Alone, + span: #4 bytes(432..433), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct A {} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: #4 bytes(468..474), + }, + Ident { + ident: "A", + span: #0 bytes(503..504), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: #4 bytes(478..480), + }, +] diff --git a/src/test/ui/proc-macro/invalid-attributes.rs b/src/test/ui/proc-macro/invalid-attributes.rs new file mode 100644 index 000000000..6bbe022c6 --- /dev/null +++ b/src/test/ui/proc-macro/invalid-attributes.rs @@ -0,0 +1,26 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro = "test"] //~ ERROR malformed `proc_macro` attribute +pub fn a(a: TokenStream) -> TokenStream { a } + +#[proc_macro()] //~ ERROR malformed `proc_macro` attribute +pub fn c(a: TokenStream) -> TokenStream { a } + +#[proc_macro(x)] //~ ERROR malformed `proc_macro` attribute +pub fn d(a: TokenStream) -> TokenStream { a } + +#[proc_macro_attribute = "test"] //~ ERROR malformed `proc_macro_attribute` attribute +pub fn e(_: TokenStream, a: TokenStream) -> TokenStream { a } + +#[proc_macro_attribute()] //~ ERROR malformed `proc_macro_attribute` attribute +pub fn g(_: TokenStream, a: TokenStream) -> TokenStream { a } + +#[proc_macro_attribute(x)] //~ ERROR malformed `proc_macro_attribute` attribute +pub fn h(_: TokenStream, a: TokenStream) -> TokenStream { a } diff --git a/src/test/ui/proc-macro/invalid-attributes.stderr b/src/test/ui/proc-macro/invalid-attributes.stderr new file mode 100644 index 000000000..fe411fa5e --- /dev/null +++ b/src/test/ui/proc-macro/invalid-attributes.stderr @@ -0,0 +1,38 @@ +error: malformed `proc_macro` attribute input + --> $DIR/invalid-attributes.rs:10:1 + | +LL | #[proc_macro = "test"] + | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]` + +error: malformed `proc_macro` attribute input + --> $DIR/invalid-attributes.rs:13:1 + | +LL | #[proc_macro()] + | ^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]` + +error: malformed `proc_macro` attribute input + --> $DIR/invalid-attributes.rs:16:1 + | +LL | #[proc_macro(x)] + | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]` + +error: malformed `proc_macro_attribute` attribute input + --> $DIR/invalid-attributes.rs:19:1 + | +LL | #[proc_macro_attribute = "test"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]` + +error: malformed `proc_macro_attribute` attribute input + --> $DIR/invalid-attributes.rs:22:1 + | +LL | #[proc_macro_attribute()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]` + +error: malformed `proc_macro_attribute` attribute input + --> $DIR/invalid-attributes.rs:25:1 + | +LL | #[proc_macro_attribute(x)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]` + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs new file mode 100644 index 000000000..814cd77cf --- /dev/null +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs @@ -0,0 +1,8 @@ +// aux-build:invalid-punct-ident.rs + +#[macro_use] +extern crate invalid_punct_ident; + +invalid_punct!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr new file mode 100644 index 000000000..7babe685b --- /dev/null +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr @@ -0,0 +1,10 @@ +error: proc macro panicked + --> $DIR/invalid-punct-ident-1.rs:6:1 + | +LL | invalid_punct!(); + | ^^^^^^^^^^^^^^^^ + | + = help: message: unsupported character `'`'` + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs new file mode 100644 index 000000000..a04dec707 --- /dev/null +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs @@ -0,0 +1,8 @@ +// aux-build:invalid-punct-ident.rs + +#[macro_use] +extern crate invalid_punct_ident; + +invalid_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr new file mode 100644 index 000000000..01b80768c --- /dev/null +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr @@ -0,0 +1,10 @@ +error: proc macro panicked + --> $DIR/invalid-punct-ident-2.rs:6:1 + | +LL | invalid_ident!(); + | ^^^^^^^^^^^^^^^^ + | + = help: message: `"*"` is not a valid identifier + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs new file mode 100644 index 000000000..f0e953608 --- /dev/null +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs @@ -0,0 +1,8 @@ +// aux-build:invalid-punct-ident.rs + +#[macro_use] +extern crate invalid_punct_ident; + +invalid_raw_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr new file mode 100644 index 000000000..899c38158 --- /dev/null +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr @@ -0,0 +1,10 @@ +error: proc macro panicked + --> $DIR/invalid-punct-ident-3.rs:6:1 + | +LL | invalid_raw_ident!(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: message: `self` cannot be a raw identifier + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.rs b/src/test/ui/proc-macro/invalid-punct-ident-4.rs new file mode 100644 index 000000000..59b347dac --- /dev/null +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.rs @@ -0,0 +1,12 @@ +// aux-build:invalid-punct-ident.rs + +#[macro_use] +extern crate invalid_punct_ident; + +lexer_failure!(); +//~^ ERROR proc macro panicked +//~| ERROR unexpected closing delimiter: `)` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr new file mode 100644 index 000000000..deb93b893 --- /dev/null +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr @@ -0,0 +1,25 @@ +error: unexpected closing delimiter: `)` + --> $DIR/invalid-punct-ident-4.rs:6:1 + | +LL | lexer_failure!(); + | ^^^^^^^^^^^^^^^^ unexpected closing delimiter + | + = note: this error originates in the macro `lexer_failure` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: proc macro panicked + --> $DIR/invalid-punct-ident-4.rs:6:1 + | +LL | lexer_failure!(); + | ^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/invalid-punct-ident-4.rs:11:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/is-available.rs b/src/test/ui/proc-macro/is-available.rs new file mode 100644 index 000000000..b32bb61b4 --- /dev/null +++ b/src/test/ui/proc-macro/is-available.rs @@ -0,0 +1,15 @@ +// run-pass + +extern crate proc_macro; + +// aux-build:is-available.rs +extern crate is_available; + +fn main() { + let a = proc_macro::is_available(); + let b = is_available::from_inside_proc_macro!(); + let c = proc_macro::is_available(); + assert!(!a); + assert!(b); + assert!(!c); +} diff --git a/src/test/ui/proc-macro/issue-36935.rs b/src/test/ui/proc-macro/issue-36935.rs new file mode 100644 index 000000000..5c43a564c --- /dev/null +++ b/src/test/ui/proc-macro/issue-36935.rs @@ -0,0 +1,13 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive(Identity, Panic)] //~ ERROR proc-macro derive panicked +struct Baz { + //~^ ERROR the name `Baz` is defined multiple times + a: i32, + b: i32, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-36935.stderr b/src/test/ui/proc-macro/issue-36935.stderr new file mode 100644 index 000000000..079e134c6 --- /dev/null +++ b/src/test/ui/proc-macro/issue-36935.stderr @@ -0,0 +1,22 @@ +error[E0428]: the name `Baz` is defined multiple times + --> $DIR/issue-36935.rs:7:1 + | +LL | struct Baz { + | ^^^^^^^^^^ + | | + | `Baz` redefined here + | previous definition of the type `Baz` here + | + = note: `Baz` must be defined only once in the type namespace of this module + +error: proc-macro derive panicked + --> $DIR/issue-36935.rs:6:20 + | +LL | #[derive(Identity, Panic)] + | ^^^^^ + | + = help: message: panic-derive + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/issue-37788.rs b/src/test/ui/proc-macro/issue-37788.rs new file mode 100644 index 000000000..73b1f0d58 --- /dev/null +++ b/src/test/ui/proc-macro/issue-37788.rs @@ -0,0 +1,9 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +fn main() { + // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE. + std::cell::Cell::new(0) //~ ERROR mismatched types +} diff --git a/src/test/ui/proc-macro/issue-37788.stderr b/src/test/ui/proc-macro/issue-37788.stderr new file mode 100644 index 000000000..345520d48 --- /dev/null +++ b/src/test/ui/proc-macro/issue-37788.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-37788.rs:8:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE. +LL | std::cell::Cell::new(0) + | ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found struct `Cell` + | + = note: expected unit type `()` + found struct `Cell<{integer}>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/issue-38586.rs b/src/test/ui/proc-macro/issue-38586.rs new file mode 100644 index 000000000..24e88ed93 --- /dev/null +++ b/src/test/ui/proc-macro/issue-38586.rs @@ -0,0 +1,9 @@ +// aux-build:issue-38586.rs + +#[macro_use] +extern crate issue_38586; + +#[derive(A)] //~ ERROR `foo` +struct A; + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-38586.stderr b/src/test/ui/proc-macro/issue-38586.stderr new file mode 100644 index 000000000..ddd0a0874 --- /dev/null +++ b/src/test/ui/proc-macro/issue-38586.stderr @@ -0,0 +1,11 @@ +error[E0425]: cannot find value `foo` in this scope + --> $DIR/issue-38586.rs:6:10 + | +LL | #[derive(A)] + | ^ not found in this scope + | + = note: this error originates in the derive macro `A` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/proc-macro/issue-39889.rs b/src/test/ui/proc-macro/issue-39889.rs new file mode 100644 index 000000000..69bfb4f3c --- /dev/null +++ b/src/test/ui/proc-macro/issue-39889.rs @@ -0,0 +1,12 @@ +// run-pass + +#![allow(dead_code, unused_macros)] +// aux-build:issue-39889.rs + +extern crate issue_39889; +use issue_39889::Issue39889; + +#[derive(Issue39889)] +struct S; + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-41211.rs b/src/test/ui/proc-macro/issue-41211.rs new file mode 100644 index 000000000..072a63baf --- /dev/null +++ b/src/test/ui/proc-macro/issue-41211.rs @@ -0,0 +1,16 @@ +// aux-build:test-macros.rs + +// FIXME: https://github.com/rust-lang/rust/issues/41430 +// This is a temporary regression test for the ICE reported in #41211 + +#![feature(custom_inner_attributes)] +#![feature(register_attr)] + +#![register_attr(identity_attr)] + +#![identity_attr] +//~^ ERROR `identity_attr` is ambiguous +extern crate test_macros; +use test_macros::identity_attr; + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-41211.stderr b/src/test/ui/proc-macro/issue-41211.stderr new file mode 100644 index 000000000..60cd36a9c --- /dev/null +++ b/src/test/ui/proc-macro/issue-41211.stderr @@ -0,0 +1,22 @@ +error[E0659]: `identity_attr` is ambiguous + --> $DIR/issue-41211.rs:11:4 + | +LL | #![identity_attr] + | ^^^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `identity_attr` could refer to the attribute macro imported here + --> $DIR/issue-41211.rs:14:5 + | +LL | use test_macros::identity_attr; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::identity_attr` to refer to this attribute macro unambiguously +note: `identity_attr` could also refer to the explicitly registered attribute defined here + --> $DIR/issue-41211.rs:9:18 + | +LL | #![register_attr(identity_attr)] + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/issue-42708.rs b/src/test/ui/proc-macro/issue-42708.rs new file mode 100644 index 000000000..e8f445aaa --- /dev/null +++ b/src/test/ui/proc-macro/issue-42708.rs @@ -0,0 +1,26 @@ +// run-pass +// aux-build:issue-42708.rs + +#![feature(decl_macro)] +#![allow(unused)] + +extern crate issue_42708; + +macro m() { + #[derive(issue_42708::Test)] + struct S { x: () } + + #[issue_42708::attr_test] + struct S2 { x: () } + + #[derive(Clone)] + struct S3 { x: () } + + fn g(s: S, s2: S2, s3: S3) { + (s.x, s2.x, s3.x); + } +} + +m!(); + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-50061.rs b/src/test/ui/proc-macro/issue-50061.rs new file mode 100644 index 000000000..01c6b80b4 --- /dev/null +++ b/src/test/ui/proc-macro/issue-50061.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(path_statements)] +// aux-build:issue-50061.rs + +#![feature(decl_macro)] + +extern crate issue_50061; + +macro inner(any_token $v: tt) { + $v +} + +macro outer($v: tt) { + inner!(any_token $v) +} + +#[issue_50061::check] +fn main() { + //! this doc comment forces roundtrip through a string + let checkit = 0; + outer!(checkit); +} diff --git a/src/test/ui/proc-macro/issue-50493.rs b/src/test/ui/proc-macro/issue-50493.rs new file mode 100644 index 000000000..ce0e0839f --- /dev/null +++ b/src/test/ui/proc-macro/issue-50493.rs @@ -0,0 +1,13 @@ +// aux-build:issue-50493.rs + +#[macro_use] +extern crate issue_50493; + +#[derive(Derive)] +struct Restricted { + pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules +} + +mod restricted {} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-50493.stderr b/src/test/ui/proc-macro/issue-50493.stderr new file mode 100644 index 000000000..23e103dbf --- /dev/null +++ b/src/test/ui/proc-macro/issue-50493.stderr @@ -0,0 +1,9 @@ +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/issue-50493.rs:8:12 + | +LL | pub(in restricted) field: usize, + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0742`. diff --git a/src/test/ui/proc-macro/issue-53481.rs b/src/test/ui/proc-macro/issue-53481.rs new file mode 100644 index 000000000..ae10a3baa --- /dev/null +++ b/src/test/ui/proc-macro/issue-53481.rs @@ -0,0 +1,22 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +mod m1 { + use m2::Empty; + + #[derive(Empty)] + struct A {} +} + +mod m2 { + pub type Empty = u8; + + #[derive(Empty)] + #[empty_helper] + struct B {} +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs new file mode 100644 index 000000000..a4161d4fc --- /dev/null +++ b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs @@ -0,0 +1,10 @@ +// Test that using a macro to replace the entire crate tree with a non-'mod' item errors out nicely. +// `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`. + +// edition:2018 +// aux-crate:issue_59191=issue-59191.rs +// error-pattern: requires `sized` lang_item + +#![feature(custom_inner_attributes)] +#![issue_59191::no_main] +#![issue_59191::no_main] diff --git a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr new file mode 100644 index 000000000..f7516c7d3 --- /dev/null +++ b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr @@ -0,0 +1,4 @@ +error: requires `sized` lang_item + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/issue-66286.rs b/src/test/ui/proc-macro/issue-66286.rs new file mode 100644 index 000000000..2a67aeab4 --- /dev/null +++ b/src/test/ui/proc-macro/issue-66286.rs @@ -0,0 +1,13 @@ +// aux-build:issue-66286.rs + +// Regression test for #66286. + +extern crate issue_66286; + +#[issue_66286::vec_ice] +pub extern fn foo(_: Vec(u32)) -> u32 { + //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait + 0 +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-66286.stderr b/src/test/ui/proc-macro/issue-66286.stderr new file mode 100644 index 000000000..fe2464b3b --- /dev/null +++ b/src/test/ui/proc-macro/issue-66286.stderr @@ -0,0 +1,14 @@ +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-66286.rs:8:22 + | +LL | pub extern fn foo(_: Vec(u32)) -> u32 { + | ^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | pub extern fn foo(_: Vec<u32>) -> u32 { + | ~ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0214`. diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs new file mode 100644 index 000000000..0c1c51c01 --- /dev/null +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs @@ -0,0 +1,19 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive(Print)] +enum ProceduralMasqueradeDummyType { +//~^ ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously + Input +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr new file mode 100644 index 000000000..be4239089 --- /dev/null +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr @@ -0,0 +1,91 @@ +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(proc_macro_back_compat)]` on by default + = 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + +error: aborting due to 4 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(proc_macro_back_compat)]` on by default + = 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + +Future breakage diagnostic: +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(proc_macro_back_compat)]` on by default + = 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + +Future breakage diagnostic: +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(proc_macro_back_compat)]` on by default + = 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + +Future breakage diagnostic: +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(proc_macro_back_compat)]` on by default + = 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout new file mode 100644 index 000000000..50334589d --- /dev/null +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout @@ -0,0 +1,22 @@ +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #0 bytes(86..90), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: #0 bytes(91..120), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: #0 bytes(315..320), + }, + ], + span: #0 bytes(121..322), + }, +] diff --git a/src/test/ui/proc-macro/issue-75734-pp-paren.rs b/src/test/ui/proc-macro/issue-75734-pp-paren.rs new file mode 100644 index 000000000..faa93787d --- /dev/null +++ b/src/test/ui/proc-macro/issue-75734-pp-paren.rs @@ -0,0 +1,26 @@ +// Regression test for issue #75734 +// Ensures that we don't lose tokens when pretty-printing would +// normally insert extra parentheses. + +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! mul_2 { + ($val:expr) => { + print_bang!($val * 2); + }; +} + + +#[print_attr] +fn main() { + &|_: u8| {}; + mul_2!(1 + 1); +} diff --git a/src/test/ui/proc-macro/issue-75734-pp-paren.stdout b/src/test/ui/proc-macro/issue-75734-pp-paren.stdout new file mode 100644 index 000000000..0fda6654f --- /dev/null +++ b/src/test/ui/proc-macro/issue-75734-pp-paren.stdout @@ -0,0 +1,134 @@ +PRINT-ATTR INPUT (DISPLAY): fn main() { & | _ : u8 | {} ; mul_2! (1 + 1) ; } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/issue-75734-pp-paren.rs:23:1: 23:3 (#0), + }, + Ident { + ident: "main", + span: $DIR/issue-75734-pp-paren.rs:23:4: 23:8 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75734-pp-paren.rs:23:8: 23:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '&', + spacing: Joint, + span: $DIR/issue-75734-pp-paren.rs:24:5: 24:6 (#0), + }, + Punct { + ch: '|', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:24:6: 24:7 (#0), + }, + Ident { + ident: "_", + span: $DIR/issue-75734-pp-paren.rs:24:7: 24:8 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:24:8: 24:9 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75734-pp-paren.rs:24:10: 24:12 (#0), + }, + Punct { + ch: '|', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:24:12: 24:13 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75734-pp-paren.rs:24:14: 24:16 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:24:16: 24:17 (#0), + }, + Ident { + ident: "mul_2", + span: $DIR/issue-75734-pp-paren.rs:25:5: 25:10 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:25:10: 25:11 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:25:12: 25:13 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:25:14: 25:15 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:25:16: 25:17 (#0), + }, + ], + span: $DIR/issue-75734-pp-paren.rs:25:11: 25:18 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:25:18: 25:19 (#0), + }, + ], + span: $DIR/issue-75734-pp-paren.rs:23:11: 26:2 (#0), + }, +] +PRINT-BANG INPUT (DISPLAY): 1 + 1 * 2 +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:25:12: 25:13 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:25:14: 25:15 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:25:16: 25:17 (#0), + }, + ], + span: $DIR/issue-75734-pp-paren.rs:17:21: 17:25 (#7), + }, + Punct { + ch: '*', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:17:26: 17:27 (#7), + }, + Literal { + kind: Integer, + symbol: "2", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:17:28: 17:29 (#7), + }, +] diff --git a/src/test/ui/proc-macro/issue-75801.rs b/src/test/ui/proc-macro/issue-75801.rs new file mode 100644 index 000000000..b07cde0fa --- /dev/null +++ b/src/test/ui/proc-macro/issue-75801.rs @@ -0,0 +1,19 @@ +// aux-build: issue-75801.rs + +// Regression test for #75801. + +#[macro_use] +extern crate issue_75801; + +macro_rules! foo { + ($arg:expr) => { + #[foo] + fn bar() { + let _bar: u32 = $arg; + } + }; +} + +foo!("baz"); //~ ERROR: mismatched types [E0308] + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-75801.stderr b/src/test/ui/proc-macro/issue-75801.stderr new file mode 100644 index 000000000..ee0a9bd77 --- /dev/null +++ b/src/test/ui/proc-macro/issue-75801.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-75801.rs:17:6 + | +LL | let _bar: u32 = $arg; + | --- expected due to this +... +LL | foo!("baz"); + | ^^^^^ expected `u32`, found `&str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.rs b/src/test/ui/proc-macro/issue-75930-derive-cfg.rs new file mode 100644 index 000000000..ef56e8e02 --- /dev/null +++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.rs @@ -0,0 +1,74 @@ +// check-pass +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs + +// Regression test for issue #75930 +// Tests that we cfg-strip all targets before invoking +// a derive macro +// We need '--error-format human' to stop compiletest from +// trying to interpret proc-macro output as JSON messages +// (a pretty-printed struct may cause a line to start with '{' ) +// FIXME: We currently lose spans here (see issue #43081) + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[print_helper(a)] //~ WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[cfg_attr(not(FALSE), allow(dead_code))] +#[print_attr] +#[derive(Print)] +#[print_helper(b)] +struct Foo<#[cfg(FALSE)] A, B> { + #[cfg(FALSE)] first: String, + #[cfg_attr(FALSE, deny(warnings))] second: bool, + third: [u8; { + #[cfg(FALSE)] struct Bar; + #[cfg(not(FALSE))] struct Inner; + #[cfg(FALSE)] let a = 25; + match true { + #[cfg(FALSE)] true => {}, + #[cfg_attr(not(FALSE), allow(warnings))] false => {}, + _ => {} + }; + + #[print_helper(should_be_removed)] + fn removed_fn() { + #![cfg(FALSE)] + } + + #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() { + #![cfg(not(FALSE))] + let my_val = true; + } + + enum TupleEnum { + Foo( + #[cfg(FALSE)] u8, + #[cfg(FALSE)] bool, + #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] String, u8 + ) + } + + struct TupleStruct( + #[cfg(FALSE)] String, + #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] bool, + u8 + ); + + fn plain_removed_fn() { + #![cfg_attr(not(FALSE), cfg(FALSE))] + } + + 0 + }], + #[print_helper(d)] + fourth: B +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr b/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr new file mode 100644 index 000000000..69d72b55c --- /dev/null +++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr @@ -0,0 +1,27 @@ +warning: derive helper attribute is used before it is introduced + --> $DIR/issue-75930-derive-cfg.rs:19:3 + | +LL | #[print_helper(a)] + | ^^^^^^^^^^^^ +... +LL | #[derive(Print)] + | ----- the attribute is introduced here + | + = note: `#[warn(legacy_derive_helpers)]` on by default + = 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 #79202 <https://github.com/rust-lang/rust/issues/79202> + +warning: derive helper attribute is used before it is introduced + --> $DIR/issue-75930-derive-cfg.rs:19:3 + | +LL | #[print_helper(a)] + | ^^^^^^^^^^^^ +... +LL | #[derive(Print)] + | ----- the attribute is introduced here + | + = 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 #79202 <https://github.com/rust-lang/rust/issues/79202> + +warning: 2 warnings emitted + diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout new file mode 100644 index 000000000..c81fa201c --- /dev/null +++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout @@ -0,0 +1,1904 @@ +PRINT-ATTR INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)] +struct Foo < #[cfg(FALSE)] A, B > +{ + #[cfg(FALSE)] first : String, #[cfg_attr(FALSE, deny(warnings))] second : + bool, third : + [u8 ; + { + #[cfg(FALSE)] struct Bar ; #[cfg(not(FALSE))] struct Inner ; + #[cfg(FALSE)] let a = 25 ; match true + { + #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] + false => {}, _ => {} + } ; #[print_helper(should_be_removed)] fn removed_fn() + { #! [cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() + { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum + { + Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] String, u8) + } struct + TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] bool, u8) ; fn plain_removed_fn() + { #! [cfg_attr(not(FALSE), cfg(FALSE))] } 0 + }], #[print_helper(d)] fourth : B +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/issue-75930-derive-cfg.rs:19:16: 19:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:15: 19:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:19 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:21:24: 21:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/issue-75930-derive-cfg.rs:21:30: 21:39 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:29: 21:40 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:23:1: 23:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "derive", + span: $DIR/issue-75930-derive-cfg.rs:23:3: 23:9 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "Print", + span: $DIR/issue-75930-derive-cfg.rs:23:10: 23:15 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:23:9: 23:16 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:23:2: 23:17 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:24:1: 24:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:24:3: 24:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "b", + span: $DIR/issue-75930-derive-cfg.rs:24:16: 24:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:2: 24:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:25:1: 25:7 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:25:8: 25:11 (#0), + }, + Punct { + ch: '<', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:12 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:12: 25:13 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:25:14: 25:17 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:25:18: 25:23 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:17: 25:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:13: 25:25 (#0), + }, + Ident { + ident: "A", + span: $DIR/issue-75930-derive-cfg.rs:25:26: 25:27 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:27: 25:28 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:25:29: 25:30 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:30: 25:31 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:26:5: 26:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:26:7: 26:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:26:11: 26:16 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:26:10: 26:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:26:6: 26:18 (#0), + }, + Ident { + ident: "first", + span: $DIR/issue-75930-derive-cfg.rs:26:19: 26:24 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:26:24: 26:25 (#0), + }, + Ident { + ident: "String", + span: $DIR/issue-75930-derive-cfg.rs:26:26: 26:32 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:26:32: 26:33 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:5: 27:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/issue-75930-derive-cfg.rs:27:7: 27:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:27:16: 27:21 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:21: 27:22 (#0), + }, + Ident { + ident: "deny", + span: $DIR/issue-75930-derive-cfg.rs:27:23: 27:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: $DIR/issue-75930-derive-cfg.rs:27:28: 27:36 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:27:27: 27:37 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:27:15: 27:38 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:27:6: 27:39 (#0), + }, + Ident { + ident: "second", + span: $DIR/issue-75930-derive-cfg.rs:27:40: 27:46 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:46: 27:47 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:27:48: 27:52 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:52: 27:53 (#0), + }, + Ident { + ident: "third", + span: $DIR/issue-75930-derive-cfg.rs:28:5: 28:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:10: 28:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:28:13: 28:15 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:16 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:9: 29:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:29:11: 29:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:29:15: 29:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:14: 29:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:10: 29:22 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:29:23: 29:29 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/issue-75930-derive-cfg.rs:29:30: 29:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:33: 29:34 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:30:9: 30:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:30:11: 30:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:30:19: 30:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:14: 30:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:10: 30:27 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:30:28: 30:34 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/issue-75930-derive-cfg.rs:30:35: 30:40 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:30:40: 30:41 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:31:9: 31:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:31:11: 31:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:31:15: 31:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:31:14: 31:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:31:10: 31:22 (#0), + }, + Ident { + ident: "let", + span: $DIR/issue-75930-derive-cfg.rs:31:23: 31:26 (#0), + }, + Ident { + ident: "a", + span: $DIR/issue-75930-derive-cfg.rs:31:27: 31:28 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:31:29: 31:30 (#0), + }, + Literal { + kind: Integer, + symbol: "25", + suffix: None, + span: $DIR/issue-75930-derive-cfg.rs:31:31: 31:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:31:33: 31:34 (#0), + }, + Ident { + ident: "match", + span: $DIR/issue-75930-derive-cfg.rs:32:9: 32:14 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:32:15: 32:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:33:13: 33:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:33:15: 33:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:33:19: 33:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:33:18: 33:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:33:14: 33:26 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:33:27: 33:31 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:33:32: 33:34 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:33:32: 33:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:33:35: 33:37 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:33:37: 33:38 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/issue-75930-derive-cfg.rs:34:15: 34:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:34:24: 34:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:34:28: 34:33 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:27: 34:34 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:34: 34:35 (#0), + }, + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:34:36: 34:41 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: $DIR/issue-75930-derive-cfg.rs:34:42: 34:50 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:41: 34:51 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:23: 34:52 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:14: 34:53 (#0), + }, + Ident { + ident: "false", + span: $DIR/issue-75930-derive-cfg.rs:34:54: 34:59 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:34:63: 34:65 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:65: 34:66 (#0), + }, + Ident { + ident: "_", + span: $DIR/issue-75930-derive-cfg.rs:35:13: 35:14 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:35:18: 35:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:32:20: 36:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:36:10: 36:11 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:38:9: 38:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:38:11: 38:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "should_be_removed", + span: $DIR/issue-75930-derive-cfg.rs:38:24: 38:41 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:23: 38:42 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:10: 38:43 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:39:9: 39:11 (#0), + }, + Ident { + ident: "removed_fn", + span: $DIR/issue-75930-derive-cfg.rs:39:12: 39:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:39:22: 39:24 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:40:13: 40:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:40:14: 40:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:40:16: 40:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:40:20: 40:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:40:19: 40:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:40:15: 40:27 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:39:25: 41:10 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:43:9: 43:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:43:11: 43:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "c", + span: $DIR/issue-75930-derive-cfg.rs:43:24: 43:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:23: 43:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:10: 43:27 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:43:28: 43:29 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:43:30: 43:33 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:43:34: 43:37 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:43:38: 43:43 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:37: 43:44 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:33: 43:45 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:29: 43:46 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:43:47: 43:49 (#0), + }, + Ident { + ident: "kept_fn", + span: $DIR/issue-75930-derive-cfg.rs:43:50: 43:57 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:43:57: 43:59 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:44:13: 44:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:44:14: 44:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:44:16: 44:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:44:20: 44:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:44:24: 44:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:23: 44:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:19: 44:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:15: 44:32 (#0), + }, + Ident { + ident: "let", + span: $DIR/issue-75930-derive-cfg.rs:45:13: 45:16 (#0), + }, + Ident { + ident: "my_val", + span: $DIR/issue-75930-derive-cfg.rs:45:17: 45:23 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:24: 45:25 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:45:26: 45:30 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:30: 45:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:60: 46:10 (#0), + }, + Ident { + ident: "enum", + span: $DIR/issue-75930-derive-cfg.rs:48:9: 48:13 (#0), + }, + Ident { + ident: "TupleEnum", + span: $DIR/issue-75930-derive-cfg.rs:48:14: 48:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:49:13: 49:16 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:50:17: 50:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:50:19: 50:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:50:23: 50:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:50:22: 50:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:50:18: 50:30 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:50:31: 50:33 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:50:33: 50:34 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:51:17: 51:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:51:19: 51:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:51:23: 51:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:51:22: 51:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:51:18: 51:30 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:51:31: 51:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:51:35: 51:36 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:52:17: 52:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:52:19: 52:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:52:23: 52:26 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:52:27: 52:32 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:26: 52:33 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:22: 52:34 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:18: 52:35 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:52:36: 52:39 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:52:39: 52:40 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:53:17: 53:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:53:19: 53:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:53:23: 53:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:53:22: 53:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:53:18: 53:30 (#0), + }, + Ident { + ident: "String", + span: $DIR/issue-75930-derive-cfg.rs:53:31: 53:37 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:53:37: 53:38 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:53:39: 53:41 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:49:16: 54:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:48:24: 55:10 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:57:9: 57:15 (#0), + }, + Ident { + ident: "TupleStruct", + span: $DIR/issue-75930-derive-cfg.rs:57:16: 57:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:58:13: 58:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:58:15: 58:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:58:19: 58:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:58:18: 58:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:58:14: 58:26 (#0), + }, + Ident { + ident: "String", + span: $DIR/issue-75930-derive-cfg.rs:58:27: 58:33 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:58:33: 58:34 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:59:13: 59:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:59:15: 59:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:59:19: 59:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:59:23: 59:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:22: 59:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:18: 59:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:14: 59:31 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:59:32: 59:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:59:35: 59:36 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:60:13: 60:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:60:15: 60:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:60:19: 60:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:60:18: 60:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:60:14: 60:26 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:60:27: 60:31 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:60:31: 60:32 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:61:13: 61:15 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:57:27: 62:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:62:10: 62:11 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:64:9: 64:11 (#0), + }, + Ident { + ident: "plain_removed_fn", + span: $DIR/issue-75930-derive-cfg.rs:64:12: 64:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:64:28: 64:30 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:65:13: 65:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:65:14: 65:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/issue-75930-derive-cfg.rs:65:16: 65:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:65:25: 65:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:65:29: 65:34 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:65:28: 65:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:65:35: 65:36 (#0), + }, + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:65:37: 65:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:65:41: 65:46 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:65:40: 65:47 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:65:24: 65:48 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:65:15: 65:49 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:64:31: 66:10 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/issue-75930-derive-cfg.rs:68:9: 68:10 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:17: 69:6 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:12: 69:7 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:69:7: 69:8 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:70:5: 70:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:70:7: 70:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "d", + span: $DIR/issue-75930-derive-cfg.rs:70:20: 70:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:70:19: 70:22 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:70:6: 70:23 (#0), + }, + Ident { + ident: "fourth", + span: $DIR/issue-75930-derive-cfg.rs:71:5: 71:11 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:71:11: 71:12 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:71:13: 71:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:32: 72:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_helper(b)] struct Foo < B > +{ + second : bool, third : + [u8 ; + { + #[cfg(not(FALSE))] struct Inner ; match true + { #[allow(warnings)] false => {}, _ => {} } ; #[print_helper(c)] + #[cfg(not(FALSE))] fn kept_fn() + { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum + { Foo(#[cfg(not(FALSE))] i32, u8) } struct + TupleStruct(#[cfg(not(FALSE))] i32, u8) ; 0 + }], #[print_helper(d)] fourth : B +} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/issue-75930-derive-cfg.rs:19:16: 19:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:15: 19:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:19 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:21:24: 21:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/issue-75930-derive-cfg.rs:21:30: 21:39 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:29: 21:40 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:24:1: 24:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:24:3: 24:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "b", + span: $DIR/issue-75930-derive-cfg.rs:24:16: 24:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:2: 24:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:25:1: 25:7 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:25:8: 25:11 (#0), + }, + Punct { + ch: '<', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:12 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:25:29: 25:30 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:30: 25:31 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "second", + span: $DIR/issue-75930-derive-cfg.rs:27:40: 27:46 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:46: 27:47 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:27:48: 27:52 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:52: 27:53 (#0), + }, + Ident { + ident: "third", + span: $DIR/issue-75930-derive-cfg.rs:28:5: 28:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:10: 28:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:28:13: 28:15 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:16 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:30:9: 30:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:30:11: 30:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:30:19: 30:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:14: 30:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:10: 30:27 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:30:28: 30:34 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/issue-75930-derive-cfg.rs:30:35: 30:40 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:30:40: 30:41 (#0), + }, + Ident { + ident: "match", + span: $DIR/issue-75930-derive-cfg.rs:32:9: 32:14 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:32:15: 32:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:34:36: 34:41 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: $DIR/issue-75930-derive-cfg.rs:34:42: 34:50 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:41: 34:51 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0), + }, + Ident { + ident: "false", + span: $DIR/issue-75930-derive-cfg.rs:34:54: 34:59 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:34:63: 34:65 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:65: 34:66 (#0), + }, + Ident { + ident: "_", + span: $DIR/issue-75930-derive-cfg.rs:35:13: 35:14 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:35:18: 35:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:32:20: 36:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:36:10: 36:11 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:43:9: 43:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:43:11: 43:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "c", + span: $DIR/issue-75930-derive-cfg.rs:43:24: 43:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:23: 43:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:10: 43:27 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:43:28: 43:29 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:43:30: 43:33 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:43:34: 43:37 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:43:38: 43:43 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:37: 43:44 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:33: 43:45 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:29: 43:46 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:43:47: 43:49 (#0), + }, + Ident { + ident: "kept_fn", + span: $DIR/issue-75930-derive-cfg.rs:43:50: 43:57 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:43:57: 43:59 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:44:13: 44:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:44:14: 44:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:44:16: 44:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:44:20: 44:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:44:24: 44:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:23: 44:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:19: 44:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:15: 44:32 (#0), + }, + Ident { + ident: "let", + span: $DIR/issue-75930-derive-cfg.rs:45:13: 45:16 (#0), + }, + Ident { + ident: "my_val", + span: $DIR/issue-75930-derive-cfg.rs:45:17: 45:23 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:24: 45:25 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:45:26: 45:30 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:30: 45:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:60: 46:10 (#0), + }, + Ident { + ident: "enum", + span: $DIR/issue-75930-derive-cfg.rs:48:9: 48:13 (#0), + }, + Ident { + ident: "TupleEnum", + span: $DIR/issue-75930-derive-cfg.rs:48:14: 48:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:49:13: 49:16 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:52:17: 52:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:52:19: 52:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:52:23: 52:26 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:52:27: 52:32 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:26: 52:33 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:22: 52:34 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:18: 52:35 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:52:36: 52:39 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:52:39: 52:40 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:53:39: 53:41 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:49:16: 54:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:48:24: 55:10 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:57:9: 57:15 (#0), + }, + Ident { + ident: "TupleStruct", + span: $DIR/issue-75930-derive-cfg.rs:57:16: 57:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:59:13: 59:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:59:15: 59:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:59:19: 59:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:59:23: 59:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:22: 59:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:18: 59:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:14: 59:31 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:59:32: 59:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:59:35: 59:36 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:61:13: 61:15 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:57:27: 62:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:62:10: 62:11 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/issue-75930-derive-cfg.rs:68:9: 68:10 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:17: 69:6 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:12: 69:7 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:69:7: 69:8 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:70:5: 70:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:70:7: 70:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "d", + span: $DIR/issue-75930-derive-cfg.rs:70:20: 70:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:70:19: 70:22 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:70:6: 70:23 (#0), + }, + Ident { + ident: "fourth", + span: $DIR/issue-75930-derive-cfg.rs:71:5: 71:11 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:71:11: 71:12 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:71:13: 71:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:32: 72:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs new file mode 100644 index 000000000..7d31de1d2 --- /dev/null +++ b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs @@ -0,0 +1,16 @@ +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// +// Regression test for issue #76182 +// Tests that we properly handle patterns with a leading vert + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; + +#[test_macros::print_attr] +fn main() { + match () { | () => () } +} diff --git a/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout new file mode 100644 index 000000000..5493f9c7b --- /dev/null +++ b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout @@ -0,0 +1,62 @@ +PRINT-ATTR INPUT (DISPLAY): fn main() { match() { | () => () } } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/issue-76182-leading-vert-pat.rs:14:1: 14:3 (#0), + }, + Ident { + ident: "main", + span: $DIR/issue-76182-leading-vert-pat.rs:14:4: 14:8 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-76182-leading-vert-pat.rs:14:8: 14:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "match", + span: $DIR/issue-76182-leading-vert-pat.rs:15:5: 15:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-76182-leading-vert-pat.rs:15:11: 15:13 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '|', + spacing: Alone, + span: $DIR/issue-76182-leading-vert-pat.rs:15:16: 15:17 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-76182-leading-vert-pat.rs:15:18: 15:20 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-76182-leading-vert-pat.rs:15:24: 15:26 (#0), + }, + ], + span: $DIR/issue-76182-leading-vert-pat.rs:15:14: 15:28 (#0), + }, + ], + span: $DIR/issue-76182-leading-vert-pat.rs:14:11: 16:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs new file mode 100644 index 000000000..98fa06b6e --- /dev/null +++ b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs @@ -0,0 +1,12 @@ +// aux-build:proc-macro-panic.rs +// edition:2018 + +// Regression test for issue #76270 +// Tests that we don't print an ICE message when a panic +// occurs in libproc-macro (when `-Z proc-macro-backtrace` is not specified) + +extern crate proc_macro_panic; + +proc_macro_panic::panic_in_libproc_macro!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr new file mode 100644 index 000000000..1dc0f16bf --- /dev/null +++ b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr @@ -0,0 +1,10 @@ +error: proc macro panicked + --> $DIR/issue-76270-panic-in-libproc-macro.rs:10:1 + | +LL | proc_macro_panic::panic_in_libproc_macro!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: message: `""` is not a valid identifier + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.rs b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.rs new file mode 100644 index 000000000..478809324 --- /dev/null +++ b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.rs @@ -0,0 +1,32 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] extern crate test_macros; + +macro_rules! foo {( + #[fake_attr] + $item:item +) => ( + $item +)} + +macro_rules! outer {($item:item) => ( + print_bang! { // Identity proc-macro + foo! { + #[fake_attr] + $item + } + } +)} +outer! { + mod bar { + //! Foo + } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout new file mode 100644 index 000000000..60a400a5d --- /dev/null +++ b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout @@ -0,0 +1,87 @@ +PRINT-BANG INPUT (DISPLAY): foo! { #[fake_attr] mod bar { + #![doc = r" Foo"] +} } +PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): foo! { #[fake_attr] mod bar { #! [doc = r" Foo"] } } +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "foo", + span: $DIR/issue-78675-captured-inner-attrs.rs:20:9: 20:12 (#4), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:20:12: 20:13 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:21:13: 21:14 (#4), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "fake_attr", + span: $DIR/issue-78675-captured-inner-attrs.rs:21:15: 21:24 (#4), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:21:14: 21:25 (#4), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "mod", + span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 27:8 (#0), + }, + Ident { + ident: "bar", + span: $DIR/issue-78675-captured-inner-attrs.rs:27:9: 27:12 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "doc", + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: " Foo", + suffix: None, + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:27:13: 29:6 (#0), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:20:14: 23:10 (#4), + }, +] diff --git a/src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs b/src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs new file mode 100644 index 000000000..b68f19c5d --- /dev/null +++ b/src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs @@ -0,0 +1,34 @@ +// check-pass +// aux-build:issue-79242.rs + +// Regression test for issue #79242 +// Tests that compilation time doesn't blow up for a proc-macro +// invocation with deeply nested nonterminals + +#![allow(unused)] + +extern crate issue_79242; + +macro_rules! declare_nats { + ($prev:ty) => {}; + ($prev:ty, $n:literal$(, $tail:literal)*) => { + + issue_79242::dummy! { + $prev + } + + declare_nats!(Option<$prev>$(, $tail)*); + }; + (0, $($n:literal),+) => { + pub struct N0; + declare_nats!(N0, $($n),+); + }; +} + +declare_nats! { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 +} + + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-79825.rs b/src/test/ui/proc-macro/issue-79825.rs new file mode 100644 index 000000000..f628469ce --- /dev/null +++ b/src/test/ui/proc-macro/issue-79825.rs @@ -0,0 +1,10 @@ +// check-pass +// aux-build:issue-79825.rs +#![feature(trait_alias)] + +extern crate issue_79825; + +#[issue_79825::assert_input] +trait Alias = Sized; + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.rs b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs new file mode 100644 index 000000000..86865af0b --- /dev/null +++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs @@ -0,0 +1,26 @@ +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! empty_stmt { + ($s:stmt) => { + print_bang!($s); + + // Currently, all attributes are ignored + // on an empty statement + #[print_attr] + #[rustc_dummy(first)] + #[rustc_dummy(second)] + $s + } +} + +fn main() { + empty_stmt!(;); +} diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout new file mode 100644 index 000000000..4b7ed8743 --- /dev/null +++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout @@ -0,0 +1,14 @@ +PRINT-BANG INPUT (DISPLAY): ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-80760-empty-stmt.rs:25:17: 25:18 (#0), + }, + ], + span: $DIR/issue-80760-empty-stmt.rs:13:21: 13:23 (#4), + }, +] diff --git a/src/test/ui/proc-macro/issue-81007-item-attrs.rs b/src/test/ui/proc-macro/issue-81007-item-attrs.rs new file mode 100644 index 000000000..ea27d54ee --- /dev/null +++ b/src/test/ui/proc-macro/issue-81007-item-attrs.rs @@ -0,0 +1,31 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] extern crate test_macros; + +macro_rules! capture_item { + ($item:item) => { + #[print_attr] + $item + } +} + +capture_item! { + /// A doc comment + struct Foo {} +} + +capture_item! { + #[rustc_dummy] + /// Another comment comment + struct Bar {} +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-81007-item-attrs.stdout b/src/test/ui/proc-macro/issue-81007-item-attrs.stdout new file mode 100644 index 000000000..3c001e995 --- /dev/null +++ b/src/test/ui/proc-macro/issue-81007-item-attrs.stdout @@ -0,0 +1,99 @@ +PRINT-ATTR INPUT (DISPLAY): #[doc = r" A doc comment"] struct Foo {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "doc", + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: " A doc comment", + suffix: None, + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + ], + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-81007-item-attrs.rs:22:5: 22:11 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/issue-81007-item-attrs.rs:22:12: 22:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-81007-item-attrs.rs:22:16: 22:18 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[doc = r" Another comment comment"] struct Bar {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:26:5: 26:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/issue-81007-item-attrs.rs:26:7: 26:18 (#0), + }, + ], + span: $DIR/issue-81007-item-attrs.rs:26:6: 26:19 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "doc", + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: " Another comment comment", + suffix: None, + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + ], + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-81007-item-attrs.rs:28:5: 28:11 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/issue-81007-item-attrs.rs:28:12: 28:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-81007-item-attrs.rs:28:16: 28:18 (#0), + }, +] diff --git a/src/test/ui/proc-macro/issue-81543-item-parse-err.rs b/src/test/ui/proc-macro/issue-81543-item-parse-err.rs new file mode 100644 index 000000000..027389556 --- /dev/null +++ b/src/test/ui/proc-macro/issue-81543-item-parse-err.rs @@ -0,0 +1,14 @@ +// aux-build:test-macros.rs + +// Regression test for issue #81543 +// Tests that we emit a properly spanned error +// when the output of a proc-macro cannot be parsed +// as the expected AST node kind + +extern crate test_macros; + +test_macros::identity! { + fn 32() {} //~ ERROR expected identifier +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-81543-item-parse-err.stderr b/src/test/ui/proc-macro/issue-81543-item-parse-err.stderr new file mode 100644 index 000000000..ca5241760 --- /dev/null +++ b/src/test/ui/proc-macro/issue-81543-item-parse-err.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `32` + --> $DIR/issue-81543-item-parse-err.rs:11:8 + | +LL | fn 32() {} + | ^^ expected identifier + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/issue-81555.rs b/src/test/ui/proc-macro/issue-81555.rs new file mode 100644 index 000000000..693f1f7dc --- /dev/null +++ b/src/test/ui/proc-macro/issue-81555.rs @@ -0,0 +1,15 @@ +// check-pass +// aux-build:test-macros.rs +#![feature(stmt_expr_attributes, proc_macro_hygiene)] + +extern crate test_macros; + +use test_macros::identity_attr; + +#[identity_attr] +fn main() { + let _x; + let y = (); + #[identity_attr] + _x = y; +} diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs new file mode 100644 index 000000000..25adc5d25 --- /dev/null +++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs @@ -0,0 +1,10 @@ +// Regression test for issue #83469 +// Ensures that we recover from `#[global_alloc]` on an invalid +// stmt without an ICE + +fn outer() { + #[global_allocator] + fn inner() {} //~ ERROR allocators must be statics +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr new file mode 100644 index 000000000..ec0e3c4c7 --- /dev/null +++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr @@ -0,0 +1,8 @@ +error: allocators must be statics + --> $DIR/issue-83469-global-alloc-invalid-stmt.rs:7:5 + | +LL | fn inner() {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/issue-83510.rs b/src/test/ui/proc-macro/issue-83510.rs new file mode 100644 index 000000000..2b1aec4df --- /dev/null +++ b/src/test/ui/proc-macro/issue-83510.rs @@ -0,0 +1,11 @@ +// aux-build: issue-83510.rs + +extern crate issue_83510; + +issue_83510::dance_like_you_want_to_ice!(); +//~^ ERROR: cannot find type `Foo` in this scope +//~| ERROR: expected trait, found struct `Box` +//~| ERROR: cannot find trait `Baz` in this scope +//~| ERROR: inherent associated types are unstable + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-83510.stderr b/src/test/ui/proc-macro/issue-83510.stderr new file mode 100644 index 000000000..e0628a317 --- /dev/null +++ b/src/test/ui/proc-macro/issue-83510.stderr @@ -0,0 +1,38 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0404]: expected trait, found struct `Box` + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait + | + = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0405]: cannot find trait `Baz` in this scope + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: inherent associated types are unstable + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0404, E0405, E0412, E0658. +For more information about an error, try `rustc --explain E0404`. diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed new file mode 100644 index 000000000..426a5fa72 --- /dev/null +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs +// run-rustfix + +#[macro_use] +extern crate test_macros; + +/// Inner doc comment +//~^ ERROR expected outer doc comment +#[derive(Empty)] +pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs new file mode 100644 index 000000000..31e3f3c85 --- /dev/null +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs +// run-rustfix + +#[macro_use] +extern crate test_macros; + +//! Inner doc comment +//~^ ERROR expected outer doc comment +#[derive(Empty)] +pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr new file mode 100644 index 000000000..a92f07522 --- /dev/null +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr @@ -0,0 +1,17 @@ +error[E0753]: expected outer doc comment + --> $DIR/issue-86781-bad-inner-doc.rs:7:1 + | +LL | //! Inner doc comment + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | pub struct Foo; + | --------------- the inner doc comment doesn't annotate this struct + | +help: to annotate the struct, change the doc comment from inner to outer style + | +LL | /// Inner doc comment + | ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0753`. diff --git a/src/test/ui/proc-macro/issue-91800.rs b/src/test/ui/proc-macro/issue-91800.rs new file mode 100644 index 000000000..0c1281de4 --- /dev/null +++ b/src/test/ui/proc-macro/issue-91800.rs @@ -0,0 +1,16 @@ +// aux-build: issue-91800-macro.rs + +#[macro_use] +extern crate issue_91800_macro; + +#[derive(MyTrait)] +//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon +//~| ERROR proc-macro derive produced unparseable tokens +#[attribute_macro] +//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon +struct MyStruct; + +fn_macro! {} +//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-91800.stderr b/src/test/ui/proc-macro/issue-91800.stderr new file mode 100644 index 000000000..9c356263a --- /dev/null +++ b/src/test/ui/proc-macro/issue-91800.stderr @@ -0,0 +1,56 @@ +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/issue-91800.rs:6:10 + | +LL | #[derive(MyTrait)] + | ^^^^^^^ + | + = note: this error originates in the derive macro `MyTrait` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: proc-macro derive produced unparseable tokens + --> $DIR/issue-91800.rs:6:10 + | +LL | #[derive(MyTrait)] + | ^^^^^^^ + +error: + --> $DIR/issue-91800.rs:6:10 + | +LL | #[derive(MyTrait)] + | ^^^^^^^ + | + = note: this error originates in the derive macro `MyTrait` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/issue-91800.rs:9:1 + | +LL | #[attribute_macro] + | ^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: + --> $DIR/issue-91800.rs:9:1 + | +LL | #[attribute_macro] + | ^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/issue-91800.rs:13:1 + | +LL | fn_macro! {} + | ^^^^^^^^^^^^ + | + = note: this error originates in the macro `fn_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: + --> $DIR/issue-91800.rs:13:1 + | +LL | fn_macro! {} + | ^^^^^^^^^^^^ + | + = note: this error originates in the macro `fn_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/proc-macro/item-error.rs b/src/test/ui/proc-macro/item-error.rs new file mode 100644 index 000000000..64c203e54 --- /dev/null +++ b/src/test/ui/proc-macro/item-error.rs @@ -0,0 +1,15 @@ +// aux-build:derive-b.rs + +#![allow(warnings)] + +#[macro_use] +extern crate derive_b; + +#[derive(B)] +struct A { + a: &u64 +//~^ ERROR: missing lifetime specifier +} + +fn main() { +} diff --git a/src/test/ui/proc-macro/item-error.stderr b/src/test/ui/proc-macro/item-error.stderr new file mode 100644 index 000000000..b544be6e9 --- /dev/null +++ b/src/test/ui/proc-macro/item-error.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/item-error.rs:10:8 + | +LL | a: &u64 + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ struct A<'a> { +LL ~ a: &'a u64 + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/proc-macro/keep-expr-tokens.rs b/src/test/ui/proc-macro/keep-expr-tokens.rs new file mode 100644 index 000000000..0bf889a85 --- /dev/null +++ b/src/test/ui/proc-macro/keep-expr-tokens.rs @@ -0,0 +1,24 @@ +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![feature(stmt_expr_attributes)] +#![feature(proc_macro_hygiene)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; + +use test_macros::recollect_attr; + +fn main() { + #[test_macros::recollect_attr] + for item in missing_fn() {} //~ ERROR cannot find + + (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad))); //~ ERROR cannot + + #[test_macros::print_attr] + #[rustc_dummy] + { 1 +1; } // Don't change the weird spacing of the '+' +} diff --git a/src/test/ui/proc-macro/keep-expr-tokens.stderr b/src/test/ui/proc-macro/keep-expr-tokens.stderr new file mode 100644 index 000000000..11052d11c --- /dev/null +++ b/src/test/ui/proc-macro/keep-expr-tokens.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find function `missing_fn` in this scope + --> $DIR/keep-expr-tokens.rs:17:17 + | +LL | for item in missing_fn() {} + | ^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `bad` in this scope + --> $DIR/keep-expr-tokens.rs:19:62 + | +LL | (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad))); + | ^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/proc-macro/keep-expr-tokens.stdout b/src/test/ui/proc-macro/keep-expr-tokens.stdout new file mode 100644 index 000000000..fcd72a0e0 --- /dev/null +++ b/src/test/ui/proc-macro/keep-expr-tokens.stdout @@ -0,0 +1,46 @@ +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] { 1 + 1 ; } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/keep-expr-tokens.rs:22:5: 22:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/keep-expr-tokens.rs:22:7: 22:18 (#0), + }, + ], + span: $DIR/keep-expr-tokens.rs:22:6: 22:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/keep-expr-tokens.rs:23:7: 23:8 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/keep-expr-tokens.rs:23:9: 23:10 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/keep-expr-tokens.rs:23:10: 23:11 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/keep-expr-tokens.rs:23:11: 23:12 (#0), + }, + ], + span: $DIR/keep-expr-tokens.rs:23:5: 23:14 (#0), + }, +] diff --git a/src/test/ui/proc-macro/lifetimes-rpass.rs b/src/test/ui/proc-macro/lifetimes-rpass.rs new file mode 100644 index 000000000..a1d33ddca --- /dev/null +++ b/src/test/ui/proc-macro/lifetimes-rpass.rs @@ -0,0 +1,26 @@ +// run-pass + +#![allow(unused_variables)] +// aux-build:lifetimes-rpass.rs + +extern crate lifetimes_rpass as lifetimes; +use lifetimes::*; + +lifetimes_bang! { + fn bang<'a>() -> &'a u8 { &0 } +} + +#[lifetimes_attr] +fn attr<'a>() -> &'a u8 { &1 } + +#[derive(Lifetimes)] +pub struct Lifetimes<'a> { + pub field: &'a u8, +} + +fn main() { + assert_eq!(bang::<'static>(), &0); + assert_eq!(attr::<'static>(), &1); + let l1 = Lifetimes { field: &0 }; + let l2 = m::Lifetimes { field: &1 }; +} diff --git a/src/test/ui/proc-macro/lifetimes.rs b/src/test/ui/proc-macro/lifetimes.rs new file mode 100644 index 000000000..560569671 --- /dev/null +++ b/src/test/ui/proc-macro/lifetimes.rs @@ -0,0 +1,9 @@ +// aux-build:lifetimes.rs + +extern crate lifetimes; + +use lifetimes::*; + +type A = single_quote_alone!(); //~ ERROR expected type, found `'` + +fn main() {} diff --git a/src/test/ui/proc-macro/lifetimes.stderr b/src/test/ui/proc-macro/lifetimes.stderr new file mode 100644 index 000000000..0c99809ed --- /dev/null +++ b/src/test/ui/proc-macro/lifetimes.stderr @@ -0,0 +1,13 @@ +error: expected type, found `'` + --> $DIR/lifetimes.rs:7:10 + | +LL | type A = single_quote_alone!(); + | ^^^^^^^^^^^^^^^^^^^^^ + | | + | expected type + | this macro call doesn't expand to a type + | + = note: this error originates in the macro `single_quote_alone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.rs b/src/test/ui/proc-macro/lints_in_proc_macros.rs new file mode 100644 index 000000000..377a1f25b --- /dev/null +++ b/src/test/ui/proc-macro/lints_in_proc_macros.rs @@ -0,0 +1,14 @@ +// aux-build:bang_proc_macro2.rs + +extern crate bang_proc_macro2; + +use bang_proc_macro2::bang_proc_macro2; + +fn main() { + let foobar = 42; + bang_proc_macro2!(); + //~^ ERROR cannot find value `foobar2` in this scope + //~| HELP a local variable with a similar name exists + //~| SUGGESTION foobar + println!("{}", x); +} diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.stderr b/src/test/ui/proc-macro/lints_in_proc_macros.stderr new file mode 100644 index 000000000..4dd8be7d9 --- /dev/null +++ b/src/test/ui/proc-macro/lints_in_proc_macros.stderr @@ -0,0 +1,11 @@ +error[E0425]: cannot find value `foobar2` in this scope + --> $DIR/lints_in_proc_macros.rs:9:5 + | +LL | bang_proc_macro2!(); + | ^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar` + | + = note: this error originates in the macro `bang_proc_macro2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/proc-macro/load-panic-backtrace.rs b/src/test/ui/proc-macro/load-panic-backtrace.rs new file mode 100644 index 000000000..cd6f70a55 --- /dev/null +++ b/src/test/ui/proc-macro/load-panic-backtrace.rs @@ -0,0 +1,14 @@ +// aux-build:test-macros.rs +// compile-flags: -Z proc-macro-backtrace +// rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "thread '.*' panicked " -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + +#[macro_use] +extern crate test_macros; + +#[derive(Panic)] +//~^ ERROR: proc-macro derive panicked +struct Foo; + +fn main() {} diff --git a/src/test/ui/proc-macro/load-panic-backtrace.stderr b/src/test/ui/proc-macro/load-panic-backtrace.stderr new file mode 100644 index 000000000..cef5786d1 --- /dev/null +++ b/src/test/ui/proc-macro/load-panic-backtrace.stderr @@ -0,0 +1,11 @@ +at 'panic-derive', $DIR/auxiliary/test-macros.rs:43:5 +error: proc-macro derive panicked + --> $DIR/load-panic-backtrace.rs:10:10 + | +LL | #[derive(Panic)] + | ^^^^^ + | + = help: message: panic-derive + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/load-panic.rs b/src/test/ui/proc-macro/load-panic.rs new file mode 100644 index 000000000..2e9a311d8 --- /dev/null +++ b/src/test/ui/proc-macro/load-panic.rs @@ -0,0 +1,10 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive(Panic)] +//~^ ERROR: proc-macro derive panicked +struct Foo; + +fn main() {} diff --git a/src/test/ui/proc-macro/load-panic.stderr b/src/test/ui/proc-macro/load-panic.stderr new file mode 100644 index 000000000..40cc4ee0e --- /dev/null +++ b/src/test/ui/proc-macro/load-panic.stderr @@ -0,0 +1,10 @@ +error: proc-macro derive panicked + --> $DIR/load-panic.rs:6:10 + | +LL | #[derive(Panic)] + | ^^^^^ + | + = help: message: panic-derive + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/load-two.rs b/src/test/ui/proc-macro/load-two.rs new file mode 100644 index 000000000..5ce0e6545 --- /dev/null +++ b/src/test/ui/proc-macro/load-two.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(path_statements)] +#![allow(dead_code)] +// aux-build:derive-atob.rs +// aux-build:derive-ctod.rs + +#[macro_use] +extern crate derive_atob; +#[macro_use] +extern crate derive_ctod; + +#[derive(Copy, Clone)] +#[derive(AToB)] +struct A; + +#[derive(CToD)] +struct C; + +fn main() { + B; + D; +} diff --git a/src/test/ui/proc-macro/macro-brackets.rs b/src/test/ui/proc-macro/macro-brackets.rs new file mode 100644 index 000000000..aa0046f45 --- /dev/null +++ b/src/test/ui/proc-macro/macro-brackets.rs @@ -0,0 +1,14 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +macro_rules! id { + ($($t:tt)*) => ($($t)*) +} + +#[identity_attr] +id![static X: u32 = 'a';]; //~ ERROR: mismatched types + + +fn main() {} diff --git a/src/test/ui/proc-macro/macro-brackets.stderr b/src/test/ui/proc-macro/macro-brackets.stderr new file mode 100644 index 000000000..d35163752 --- /dev/null +++ b/src/test/ui/proc-macro/macro-brackets.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/macro-brackets.rs:11:21 + | +LL | id![static X: u32 = 'a';]; + | ^^^ expected `u32`, found `char` + | +help: you can cast a `char` to a `u32`, since a `char` always occupies 4 bytes + | +LL | id![static X: u32 = 'a' as u32;]; + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/macro-crate-multi-decorator.rs b/src/test/ui/proc-macro/macro-crate-multi-decorator.rs new file mode 100644 index 000000000..ec57dec14 --- /dev/null +++ b/src/test/ui/proc-macro/macro-crate-multi-decorator.rs @@ -0,0 +1,41 @@ +// The duplicate macro will create a copy of the item with the given identifier. + +// check-pass +// aux-build:duplicate.rs + +#[macro_use] +extern crate duplicate; + +#[duplicate(MyCopy)] +struct MyStruct { + number: i32, +} + +trait TestTrait { + #[duplicate(TestType2)] + type TestType; + + #[duplicate(required_fn2)] + fn required_fn(&self); + + #[duplicate(provided_fn2)] + fn provided_fn(&self) {} +} + +impl TestTrait for MyStruct { + #[duplicate(TestType2)] + type TestType = f64; + + #[duplicate(required_fn2)] + fn required_fn(&self) {} +} + +fn main() { + let s = MyStruct { number: 42 }; + s.required_fn(); + s.required_fn2(); + s.provided_fn(); + s.provided_fn2(); + + let s = MyCopy { number: 42 }; +} diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs new file mode 100644 index 000000000..470b22b48 --- /dev/null +++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs @@ -0,0 +1,57 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn my_macro(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(MyTrait)] +pub fn my_macro_derive(input: TokenStream) -> TokenStream { + input +} + +fn check_bang1() { + my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it +} +fn check_bang2() { + my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr` in this scope + crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines + //~| ERROR expected macro, found attribute macro `crate::my_macro_attr` +} +fn check_bang3() { + MyTrait!(); //~ ERROR cannot find macro `MyTrait` in this scope + crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it + //~| ERROR expected macro, found derive macro `crate::MyTrait` +} + +#[my_macro] //~ ERROR cannot find attribute `my_macro` in this scope +#[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it + //~| ERROR expected attribute, found macro `crate::my_macro` +fn check_attr1() {} +#[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it +fn check_attr2() {} +#[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it + //~| ERROR expected attribute, found derive macro `MyTrait` +fn check_attr3() {} + +#[derive(my_macro)] //~ ERROR cannot find derive macro `my_macro` in this scope + //~| ERROR cannot find derive macro `my_macro` in this scope +#[derive(crate::my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines + //~| ERROR expected derive macro, found macro `crate::my_macro` +struct CheckDerive1; +#[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it + //~| ERROR expected derive macro, found attribute macro `my_macro_attr` +struct CheckDerive2; +#[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it +struct CheckDerive3; diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr new file mode 100644 index 000000000..633a6c6a0 --- /dev/null +++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr @@ -0,0 +1,132 @@ +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:25:5 + | +LL | my_macro!(); + | ^^^^^^^^ + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:29:5 + | +LL | crate::my_macro_attr!(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: expected macro, found attribute macro `crate::my_macro_attr` + --> $DIR/macro-namespace-reserved-2.rs:29:5 + | +LL | crate::my_macro_attr!(); + | ^^^^^^^^^^^^^^^^^^^^ not a macro + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:34:5 + | +LL | crate::MyTrait!(); + | ^^^^^^^^^^^^^^ + +error: expected macro, found derive macro `crate::MyTrait` + --> $DIR/macro-namespace-reserved-2.rs:34:5 + | +LL | crate::MyTrait!(); + | ^^^^^^^^^^^^^^ not a macro + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:42:3 + | +LL | #[my_macro_attr] + | ^^^^^^^^^^^^^ + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:44:3 + | +LL | #[MyTrait] + | ^^^^^^^ + +error: expected attribute, found derive macro `MyTrait` + --> $DIR/macro-namespace-reserved-2.rs:44:3 + | +LL | #[MyTrait] + | ^^^^^^^ not an attribute + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:53:10 + | +LL | #[derive(my_macro_attr)] + | ^^^^^^^^^^^^^ + +error: expected derive macro, found attribute macro `my_macro_attr` + --> $DIR/macro-namespace-reserved-2.rs:53:10 + | +LL | #[derive(my_macro_attr)] + | ^^^^^^^^^^^^^ not a derive macro + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:56:10 + | +LL | #[derive(MyTrait)] + | ^^^^^^^ + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:39:3 + | +LL | #[crate::my_macro] + | ^^^^^^^^^^^^^^^ + +error: expected attribute, found macro `crate::my_macro` + --> $DIR/macro-namespace-reserved-2.rs:39:3 + | +LL | #[crate::my_macro] + | ^^^^^^^^^^^^^^^ not an attribute + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:50:10 + | +LL | #[derive(crate::my_macro)] + | ^^^^^^^^^^^^^^^ + +error: expected derive macro, found macro `crate::my_macro` + --> $DIR/macro-namespace-reserved-2.rs:50:10 + | +LL | #[derive(crate::my_macro)] + | ^^^^^^^^^^^^^^^ not a derive macro + +error: cannot find macro `my_macro_attr` in this scope + --> $DIR/macro-namespace-reserved-2.rs:28:5 + | +LL | my_macro_attr!(); + | ^^^^^^^^^^^^^ + | + = note: `my_macro_attr` is in scope, but it is an attribute: `#[my_macro_attr]` + +error: cannot find macro `MyTrait` in this scope + --> $DIR/macro-namespace-reserved-2.rs:33:5 + | +LL | MyTrait!(); + | ^^^^^^^ + | + = note: `MyTrait` is in scope, but it is a derive macro: `#[derive(MyTrait)]` + +error: cannot find attribute `my_macro` in this scope + --> $DIR/macro-namespace-reserved-2.rs:38:3 + | +LL | #[my_macro] + | ^^^^^^^^ + | + = note: `my_macro` is in scope, but it is a function-like macro + +error: cannot find derive macro `my_macro` in this scope + --> $DIR/macro-namespace-reserved-2.rs:48:10 + | +LL | #[derive(my_macro)] + | ^^^^^^^^ + | + = note: `my_macro` is in scope, but it is a function-like macro + +error: cannot find derive macro `my_macro` in this scope + --> $DIR/macro-namespace-reserved-2.rs:48:10 + | +LL | #[derive(my_macro)] + | ^^^^^^^^ + | + = note: `my_macro` is in scope, but it is a function-like macro + +error: aborting due to 20 previous errors + diff --git a/src/test/ui/proc-macro/macro-namespace-reserved.rs b/src/test/ui/proc-macro/macro-namespace-reserved.rs new file mode 100644 index 000000000..60d379e41 --- /dev/null +++ b/src/test/ui/proc-macro/macro-namespace-reserved.rs @@ -0,0 +1,38 @@ +// force-host +// no-prefer-dynamic + +#![feature(decl_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn my_macro(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(MyTrait)] +pub fn my_macro_derive(input: TokenStream) -> TokenStream { + input +} + +macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times +macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times +macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times + +#[proc_macro_derive(SameName)] +pub fn foo(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro] +pub fn SameName(input: TokenStream) -> TokenStream { +//~^ ERROR the name `SameName` is defined multiple times + input +} diff --git a/src/test/ui/proc-macro/macro-namespace-reserved.stderr b/src/test/ui/proc-macro/macro-namespace-reserved.stderr new file mode 100644 index 000000000..f5d589c3a --- /dev/null +++ b/src/test/ui/proc-macro/macro-namespace-reserved.stderr @@ -0,0 +1,47 @@ +error[E0428]: the name `my_macro` is defined multiple times + --> $DIR/macro-namespace-reserved.rs:25:1 + | +LL | pub fn my_macro(input: TokenStream) -> TokenStream { + | -------------------------------------------------- previous definition of the macro `my_macro` here +... +LL | macro my_macro() {} + | ^^^^^^^^^^^^^^^^ `my_macro` redefined here + | + = note: `my_macro` must be defined only once in the macro namespace of this module + +error[E0428]: the name `my_macro_attr` is defined multiple times + --> $DIR/macro-namespace-reserved.rs:26:1 + | +LL | pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream { + | ----------------------------------------------------------------------- previous definition of the macro `my_macro_attr` here +... +LL | macro my_macro_attr() {} + | ^^^^^^^^^^^^^^^^^^^^^ `my_macro_attr` redefined here + | + = note: `my_macro_attr` must be defined only once in the macro namespace of this module + +error[E0428]: the name `MyTrait` is defined multiple times + --> $DIR/macro-namespace-reserved.rs:27:1 + | +LL | #[proc_macro_derive(MyTrait)] + | ------- previous definition of the macro `MyTrait` here +... +LL | macro MyTrait() {} + | ^^^^^^^^^^^^^^^ `MyTrait` redefined here + | + = note: `MyTrait` must be defined only once in the macro namespace of this module + +error[E0428]: the name `SameName` is defined multiple times + --> $DIR/macro-namespace-reserved.rs:35:1 + | +LL | #[proc_macro_derive(SameName)] + | -------- previous definition of the macro `SameName` here +... +LL | pub fn SameName(input: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SameName` redefined here + | + = note: `SameName` must be defined only once in the macro namespace of this module + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/macro-quote-cond.rs b/src/test/ui/proc-macro/macro-quote-cond.rs new file mode 100644 index 000000000..48307f4d9 --- /dev/null +++ b/src/test/ui/proc-macro/macro-quote-cond.rs @@ -0,0 +1,46 @@ +// run-pass +// aux-build:cond_plugin.rs + +#![allow(unused_parens)] + +extern crate cond_plugin; + +use cond_plugin::cond; + +fn fact(n : i64) -> i64 { + if n == 0 { + 1 + } else { + n * fact(n - 1) + } +} + +fn fact_cond(n : i64) -> i64 { + cond!( + ((n == 0) 1) + (else (n * fact_cond(n-1))) + ) +} + +fn fib(n : i64) -> i64 { + if n == 0 || n == 1 { + 1 + } else { + fib(n-1) + fib(n-2) + } +} + +fn fib_cond(n : i64) -> i64 { + cond!( + ((n == 0) 1) + ((n == 1) 1) + (else (fib_cond(n-1) + fib_cond(n-2))) + ) +} + +fn main() { + assert_eq!(fact(3), fact_cond(3)); + assert_eq!(fact(5), fact_cond(5)); + assert_eq!(fib(5), fib_cond(5)); + assert_eq!(fib(8), fib_cond(8)); +} diff --git a/src/test/ui/proc-macro/macro-rules-derive-cfg.rs b/src/test/ui/proc-macro/macro-rules-derive-cfg.rs new file mode 100644 index 000000000..a221b9578 --- /dev/null +++ b/src/test/ui/proc-macro/macro-rules-derive-cfg.rs @@ -0,0 +1,31 @@ +// check-pass +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! produce_it { + ($expr:expr) => { + #[derive(Print)] + struct Foo { + val: [bool; { + let a = #[cfg_attr(not(FALSE), rustc_dummy(first))] $expr; + 0 + }] + } + } +} + +produce_it!(#[cfg_attr(not(FALSE), rustc_dummy(second))] { + #![cfg_attr(not(FALSE), allow(unused))] + 30 +}); + +fn main() {} diff --git a/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout b/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout new file mode 100644 index 000000000..74641058e --- /dev/null +++ b/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout @@ -0,0 +1,171 @@ +PRINT-DERIVE INPUT (DISPLAY): struct Foo +{ + val : + [bool ; + { + let a = #[rustc_dummy(first)] #[rustc_dummy(second)] + { #! [allow(unused)] 30 } ; 0 + }] +} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/macro-rules-derive-cfg.rs:17:9: 17:15 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/macro-rules-derive-cfg.rs:17:16: 17:19 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "val", + span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:16 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:18:16: 18:17 (#4), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "bool", + span: $DIR/macro-rules-derive-cfg.rs:18:19: 18:23 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:18:23: 18:24 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: $DIR/macro-rules-derive-cfg.rs:19:17: 19:20 (#4), + }, + Ident { + ident: "a", + span: $DIR/macro-rules-derive-cfg.rs:19:21: 19:22 (#4), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:19:23: 19:24 (#4), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#4), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:19:48: 19:59 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "first", + span: $DIR/macro-rules-derive-cfg.rs:19:60: 19:65 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:19:59: 19:66 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#4), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:26:36: 26:47 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second", + span: $DIR/macro-rules-derive-cfg.rs:26:48: 26:54 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:26:47: 26:55 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:27:6: 27:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/macro-rules-derive-cfg.rs:27:29: 27:34 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "unused", + span: $DIR/macro-rules-derive-cfg.rs:27:35: 27:41 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:27:34: 27:42 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0), + }, + Literal { + kind: Integer, + symbol: "30", + suffix: None, + span: $DIR/macro-rules-derive-cfg.rs:28:5: 28:7 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:26:58: 29:2 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:19:74: 19:75 (#4), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/macro-rules-derive-cfg.rs:20:17: 20:18 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:18:25: 21:14 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:18:18: 21:15 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:17:20: 22:10 (#4), + }, +] diff --git a/src/test/ui/proc-macro/macro-rules-derive.rs b/src/test/ui/proc-macro/macro-rules-derive.rs new file mode 100644 index 000000000..e0c40bbc7 --- /dev/null +++ b/src/test/ui/proc-macro/macro-rules-derive.rs @@ -0,0 +1,19 @@ +// aux-build:first-second.rs + +extern crate first_second; +use first_second::*; + +macro_rules! produce_it { + ($name:ident) => { + #[first] + struct $name { + field: MissingType //~ ERROR cannot find type + } + } +} + +produce_it!(MyName); + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/proc-macro/macro-rules-derive.stderr b/src/test/ui/proc-macro/macro-rules-derive.stderr new file mode 100644 index 000000000..517cbabd5 --- /dev/null +++ b/src/test/ui/proc-macro/macro-rules-derive.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/macro-rules-derive.rs:10:20 + | +LL | field: MissingType + | ^^^^^^^^^^^ not found in this scope +... +LL | produce_it!(MyName); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `produce_it` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/proc-macro/macro-use-attr.rs b/src/test/ui/proc-macro/macro-use-attr.rs new file mode 100644 index 000000000..b101c09ed --- /dev/null +++ b/src/test/ui/proc-macro/macro-use-attr.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[identity_attr] +struct Foo; + +fn main() { + let _ = Foo; +} diff --git a/src/test/ui/proc-macro/macro-use-bang.rs b/src/test/ui/proc-macro/macro-use-bang.rs new file mode 100644 index 000000000..4a0bf0b2f --- /dev/null +++ b/src/test/ui/proc-macro/macro-use-bang.rs @@ -0,0 +1,9 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +fn main() { + identity!(println!("Hello, world!")); +} diff --git a/src/test/ui/proc-macro/macros-in-extern-derive.rs b/src/test/ui/proc-macro/macros-in-extern-derive.rs new file mode 100644 index 000000000..c8b26b005 --- /dev/null +++ b/src/test/ui/proc-macro/macros-in-extern-derive.rs @@ -0,0 +1,6 @@ +extern "C" { + #[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + fn f(); +} + +fn main() {} diff --git a/src/test/ui/proc-macro/macros-in-extern-derive.stderr b/src/test/ui/proc-macro/macros-in-extern-derive.stderr new file mode 100644 index 000000000..efd9ff225 --- /dev/null +++ b/src/test/ui/proc-macro/macros-in-extern-derive.stderr @@ -0,0 +1,11 @@ +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/macros-in-extern-derive.rs:2:5 + | +LL | #[derive(Copy)] + | ^^^^^^^^^^^^^^^ not applicable here +LL | fn f(); + | ------- not a `struct`, `enum` or `union` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0774`. diff --git a/src/test/ui/proc-macro/macros-in-extern.rs b/src/test/ui/proc-macro/macros-in-extern.rs new file mode 100644 index 000000000..57e2066d8 --- /dev/null +++ b/src/test/ui/proc-macro/macros-in-extern.rs @@ -0,0 +1,24 @@ +// run-pass +// aux-build:test-macros.rs +// ignore-wasm32 + +#[macro_use] +extern crate test_macros; + +fn main() { + assert_eq!(unsafe { rust_get_test_int() }, 1); + assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF); +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + #[empty_attr] + fn some_definitely_unknown_symbol_which_should_be_removed(); + + #[identity_attr] + fn rust_get_test_int() -> isize; + + identity!( + fn rust_dbg_extern_identity_u32(arg: u32) -> u32; + ); +} diff --git a/src/test/ui/proc-macro/macros-in-type.rs b/src/test/ui/proc-macro/macros-in-type.rs new file mode 100644 index 000000000..19ed58ece --- /dev/null +++ b/src/test/ui/proc-macro/macros-in-type.rs @@ -0,0 +1,11 @@ +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +const C: identity!(u8) = 10; + +fn main() { + let c: u8 = C; +} diff --git a/src/test/ui/proc-macro/meta-delim.rs b/src/test/ui/proc-macro/meta-delim.rs new file mode 100644 index 000000000..964291bc6 --- /dev/null +++ b/src/test/ui/proc-macro/meta-delim.rs @@ -0,0 +1,12 @@ +// aux-build:meta-delim.rs +// edition:2018 +// run-pass + +// Tests that we can properly deserialize a macro with strange delimiters +// See https://github.com/rust-lang/rust/pull/73569#issuecomment-650860457 + +extern crate meta_delim; + +fn main() { + assert_eq!("a bunch of idents", meta_delim::meta_delim!(a bunch of idents)); +} diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.rs b/src/test/ui/proc-macro/meta-macro-hygiene.rs new file mode 100644 index 000000000..62968ea54 --- /dev/null +++ b/src/test/ui/proc-macro/meta-macro-hygiene.rs @@ -0,0 +1,30 @@ +// aux-build:make-macro.rs +// aux-build:meta-macro.rs +// edition:2018 +// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no +// check-pass +// normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" +// +// We don't care about symbol ids, so we set them all to 0 +// in the stdout + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate meta_macro; + +macro_rules! produce_it { + () => { + // `print_def_site!` will respan the `$crate` identifier + // with `Span::def_site()`. This should cause it to resolve + // relative to `meta_macro`, *not* `make_macro` (despite + // the fact that that `print_def_site` is produced by + // a `macro_rules!` macro in `make_macro`). + meta_macro::print_def_site!($crate::dummy!()); + } +} + +fn main() { + produce_it!(); +} diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout new file mode 100644 index 000000000..5d04fe1e3 --- /dev/null +++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout @@ -0,0 +1,69 @@ +Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) +Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:24:37: 24:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:24:45: 24:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:50: 24:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:24:51: 24:53 (#4) }] +Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }] +#![feature /* 0#0 */(prelude_import)] +// aux-build:make-macro.rs +// aux-build:meta-macro.rs +// edition:2018 +// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no +// check-pass +// normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" +// +// We don't care about symbol ids, so we set them all to 0 +// in the stdout + +#![no_std /* 0#0 */] +#[prelude_import /* 0#1 */] +use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*; +#[macro_use /* 0#1 */] +extern crate core /* 0#1 */; +#[macro_use /* 0#1 */] +extern crate compiler_builtins /* 0#1 */; +// Don't load unnecessary hygiene information from std +extern crate std /* 0#0 */; + +extern crate meta_macro /* 0#0 */; + +macro_rules! produce_it + /* + 0#0 + */ { + () => + { + meta_macro :: print_def_site! ($crate :: dummy! ()) ; + // `print_def_site!` will respan the `$crate` identifier + // with `Span::def_site()`. This should cause it to resolve + // relative to `meta_macro`, *not* `make_macro` (despite + // the fact that that `print_def_site` is produced by + // a `macro_rules!` macro in `make_macro`). + } +} + +fn main /* 0#0 */() { ; } + +/* +Expansions: +crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) +crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it") +crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") +crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) + +SyntaxContexts: +#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) +#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) +#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque) +#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#6: parent: #4, outer_mark: (crate0::{{expn3}}, Transparent) +#7: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent) +#8: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) +#9: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent) +#10: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) +*/ diff --git a/src/test/ui/proc-macro/meta-macro.rs b/src/test/ui/proc-macro/meta-macro.rs new file mode 100644 index 000000000..dbac90382 --- /dev/null +++ b/src/test/ui/proc-macro/meta-macro.rs @@ -0,0 +1,14 @@ +// aux-build:make-macro.rs +// aux-build:meta-macro.rs +// edition:2018 +// compile-flags: -Z span-debug +// run-pass + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate meta_macro; + +fn main() { + meta_macro::print_def_site!(); +} diff --git a/src/test/ui/proc-macro/meta-macro.stdout b/src/test/ui/proc-macro/meta-macro.stdout new file mode 100644 index 000000000..662682d40 --- /dev/null +++ b/src/test/ui/proc-macro/meta-macro.stdout @@ -0,0 +1,3 @@ +Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) +Input: TokenStream [] +Respanned: TokenStream [] diff --git a/src/test/ui/proc-macro/mixed-site-span.rs b/src/test/ui/proc-macro/mixed-site-span.rs new file mode 100644 index 000000000..008384656 --- /dev/null +++ b/src/test/ui/proc-macro/mixed-site-span.rs @@ -0,0 +1,24 @@ +// Proc macros using `mixed_site` spans exhibit usual properties of `macro_rules` hygiene. + +// aux-build:mixed-site-span.rs + +#[macro_use] +extern crate mixed_site_span; + +struct ItemUse; + +fn main() { + 'label_use: loop { + let local_use = 1; + proc_macro_rules!(); + //~^ ERROR use of undeclared label `'label_use` + //~| ERROR cannot find value `local_use` in this scope + ItemDef; // OK + local_def; //~ ERROR cannot find value `local_def` in this scope + } +} + +macro_rules! pass_dollar_crate { + () => (proc_macro_rules!($crate);) //~ ERROR cannot find type `ItemUse` in crate `$crate` +} +pass_dollar_crate!(); diff --git a/src/test/ui/proc-macro/mixed-site-span.stderr b/src/test/ui/proc-macro/mixed-site-span.stderr new file mode 100644 index 000000000..eab4317de --- /dev/null +++ b/src/test/ui/proc-macro/mixed-site-span.stderr @@ -0,0 +1,34 @@ +error[E0426]: use of undeclared label `'label_use` + --> $DIR/mixed-site-span.rs:13:9 + | +LL | proc_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` + | + = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `local_use` in this scope + --> $DIR/mixed-site-span.rs:13:9 + | +LL | proc_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `local_def` in this scope + --> $DIR/mixed-site-span.rs:17:9 + | +LL | local_def; + | ^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `ItemUse` in crate `$crate` + --> $DIR/mixed-site-span.rs:24:1 + | +LL | pass_dollar_crate!(); + | ^^^^^^^^^^^^^^^^^^^^ not found in `$crate` + | + = note: this error originates in the macro `proc_macro_rules` which comes from the expansion of the macro `pass_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0412, E0425, E0426. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/proc-macro/modify-ast.rs b/src/test/ui/proc-macro/modify-ast.rs new file mode 100644 index 000000000..ea9bf837c --- /dev/null +++ b/src/test/ui/proc-macro/modify-ast.rs @@ -0,0 +1,26 @@ +// run-pass +// aux-build:modify-ast.rs + +extern crate modify_ast; + +use modify_ast::*; + +#[derive(Foo)] +pub struct MyStructc { + #[cfg_attr(my_cfg, foo)] + _a: i32, +} + +macro_rules! a { + ($i:item) => ($i) +} + +a! { + #[assert1] + pub fn foo() {} +} + +fn main() { + let _a = MyStructc { _a: 0 }; + foo(); +} diff --git a/src/test/ui/proc-macro/module.rs b/src/test/ui/proc-macro/module.rs new file mode 100644 index 000000000..5777ed899 --- /dev/null +++ b/src/test/ui/proc-macro/module.rs @@ -0,0 +1 @@ +// ignore-test diff --git a/src/test/ui/proc-macro/module_with_attrs.rs b/src/test/ui/proc-macro/module_with_attrs.rs new file mode 100644 index 000000000..63e66a62a --- /dev/null +++ b/src/test/ui/proc-macro/module_with_attrs.rs @@ -0,0 +1,4 @@ +// ignore-test + +#![rustfmt::skip] +#![print_attr] diff --git a/src/test/ui/proc-macro/multispan.rs b/src/test/ui/proc-macro/multispan.rs new file mode 100644 index 000000000..e9e0349f2 --- /dev/null +++ b/src/test/ui/proc-macro/multispan.rs @@ -0,0 +1,25 @@ +// aux-build:multispan.rs + +extern crate multispan; + +use multispan::hello; + +fn main() { + // This one emits no error. + hello!(); + + // Exactly one 'hi'. + hello!(hi); //~ ERROR hello to you, too! + + // Now two, back to back. + hello!(hi hi); //~ ERROR hello to you, too! + + // Now three, back to back. + hello!(hi hi hi); //~ ERROR hello to you, too! + + // Now several, with spacing. + hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too! + hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too! + hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too! + hello!(hi good hi and good bye); //~ ERROR hello to you, too! +} diff --git a/src/test/ui/proc-macro/multispan.stderr b/src/test/ui/proc-macro/multispan.stderr new file mode 100644 index 000000000..0aea02bbd --- /dev/null +++ b/src/test/ui/proc-macro/multispan.stderr @@ -0,0 +1,93 @@ +error: hello to you, too! + --> $DIR/multispan.rs:12:5 + | +LL | hello!(hi); + | ^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:12:12 + | +LL | hello!(hi); + | ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:15:5 + | +LL | hello!(hi hi); + | ^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:15:12 + | +LL | hello!(hi hi); + | ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:18:5 + | +LL | hello!(hi hi hi); + | ^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:18:12 + | +LL | hello!(hi hi hi); + | ^^ ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:21:5 + | +LL | hello!(hi hey hi yo hi beep beep hi hi); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:21:12 + | +LL | hello!(hi hey hi yo hi beep beep hi hi); + | ^^ ^^ ^^ ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:22:5 + | +LL | hello!(hi there, hi how are you? hi... hi.); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:22:12 + | +LL | hello!(hi there, hi how are you? hi... hi.); + | ^^ ^^ ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:23:5 + | +LL | hello!(whoah. hi di hi di ho); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:23:19 + | +LL | hello!(whoah. hi di hi di ho); + | ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:24:5 + | +LL | hello!(hi good hi and good bye); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:24:12 + | +LL | hello!(hi good hi and good bye); + | ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/proc-macro/negative-token.rs b/src/test/ui/proc-macro/negative-token.rs new file mode 100644 index 000000000..2ed3cbc08 --- /dev/null +++ b/src/test/ui/proc-macro/negative-token.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:negative-token.rs + +extern crate negative_token; + +use negative_token::*; + +fn main() { + assert_eq!(-1, neg_one!()); + assert_eq!(-1.0, neg_one_float!()); +} diff --git a/src/test/ui/proc-macro/nested-derive-cfg.rs b/src/test/ui/proc-macro/nested-derive-cfg.rs new file mode 100644 index 000000000..53cfbb7c9 --- /dev/null +++ b/src/test/ui/proc-macro/nested-derive-cfg.rs @@ -0,0 +1,23 @@ +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs +// check-pass + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[derive(Print)] +struct Foo { + #[cfg(FALSE)] removed: bool, + my_array: [bool; { + struct Inner { + #[cfg(FALSE)] removed_inner_field: u8, + non_removed_inner_field: usize + } + 0 + }] +} + +fn main() {} diff --git a/src/test/ui/proc-macro/nested-derive-cfg.stdout b/src/test/ui/proc-macro/nested-derive-cfg.stdout new file mode 100644 index 000000000..9a562c971 --- /dev/null +++ b/src/test/ui/proc-macro/nested-derive-cfg.stdout @@ -0,0 +1,81 @@ +PRINT-DERIVE INPUT (DISPLAY): struct Foo +{ my_array : [bool ; { struct Inner { non_removed_inner_field : usize } 0 }] } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/nested-derive-cfg.rs:12:1: 12:7 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/nested-derive-cfg.rs:12:8: 12:11 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "my_array", + span: $DIR/nested-derive-cfg.rs:14:5: 14:13 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nested-derive-cfg.rs:14:13: 14:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "bool", + span: $DIR/nested-derive-cfg.rs:14:16: 14:20 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/nested-derive-cfg.rs:14:20: 14:21 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "struct", + span: $DIR/nested-derive-cfg.rs:15:9: 15:15 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/nested-derive-cfg.rs:15:16: 15:21 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "non_removed_inner_field", + span: $DIR/nested-derive-cfg.rs:17:13: 17:36 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nested-derive-cfg.rs:17:36: 17:37 (#0), + }, + Ident { + ident: "usize", + span: $DIR/nested-derive-cfg.rs:17:38: 17:43 (#0), + }, + ], + span: $DIR/nested-derive-cfg.rs:15:22: 18:10 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/nested-derive-cfg.rs:19:9: 19:10 (#0), + }, + ], + span: $DIR/nested-derive-cfg.rs:14:22: 20:6 (#0), + }, + ], + span: $DIR/nested-derive-cfg.rs:14:15: 20:7 (#0), + }, + ], + span: $DIR/nested-derive-cfg.rs:12:12: 21:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/nested-item-spans.rs b/src/test/ui/proc-macro/nested-item-spans.rs new file mode 100644 index 000000000..63da170d0 --- /dev/null +++ b/src/test/ui/proc-macro/nested-item-spans.rs @@ -0,0 +1,23 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[recollect_attr] +fn another() { + fn bar() { + let x: u32 = "x"; //~ ERROR: mismatched types + } + + bar(); +} + +fn main() { + #[recollect_attr] + fn bar() { + let x: u32 = "x"; //~ ERROR: mismatched types + } + + bar(); + another(); +} diff --git a/src/test/ui/proc-macro/nested-item-spans.stderr b/src/test/ui/proc-macro/nested-item-spans.stderr new file mode 100644 index 000000000..44b338fa6 --- /dev/null +++ b/src/test/ui/proc-macro/nested-item-spans.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/nested-item-spans.rs:9:22 + | +LL | let x: u32 = "x"; + | --- ^^^ expected `u32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/nested-item-spans.rs:18:22 + | +LL | let x: u32 = "x"; + | --- ^^^ expected `u32`, found `&str` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/nested-macro-rules.rs b/src/test/ui/proc-macro/nested-macro-rules.rs new file mode 100644 index 000000000..25ffcfad7 --- /dev/null +++ b/src/test/ui/proc-macro/nested-macro-rules.rs @@ -0,0 +1,23 @@ +// run-pass +// aux-build:nested-macro-rules.rs +// aux-build:test-macros.rs +// compile-flags: -Z span-debug -Z macro-backtrace +// edition:2018 + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate nested_macro_rules; +extern crate test_macros; + +use test_macros::{print_bang, print_attr}; + +use nested_macro_rules::FirstStruct; +struct SecondStruct; + +fn main() { + nested_macro_rules::inner_macro!(print_bang, print_attr); + + nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); + inner_macro!(print_bang, print_attr); +} diff --git a/src/test/ui/proc-macro/nested-macro-rules.stdout b/src/test/ui/proc-macro/nested-macro-rules.stdout new file mode 100644 index 000000000..311139040 --- /dev/null +++ b/src/test/ui/proc-macro/nested-macro-rules.stdout @@ -0,0 +1,46 @@ +PRINT-BANG INPUT (DISPLAY): FirstStruct +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "FirstStruct", + span: $DIR/auxiliary/nested-macro-rules.rs:16:14: 16:25 (#7), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct FirstAttrStruct {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#6), + }, + Ident { + ident: "FirstAttrStruct", + span: $DIR/auxiliary/nested-macro-rules.rs:16:27: 16:42 (#7), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#6), + }, +] +PRINT-BANG INPUT (DISPLAY): SecondStruct +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "SecondStruct", + span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#15), + }, + Ident { + ident: "SecondAttrStruct", + span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#15), + }, +] diff --git a/src/test/ui/proc-macro/nested-nonterminal-tokens.rs b/src/test/ui/proc-macro/nested-nonterminal-tokens.rs new file mode 100644 index 000000000..04d34e21c --- /dev/null +++ b/src/test/ui/proc-macro/nested-nonterminal-tokens.rs @@ -0,0 +1,26 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +// Tests that we properly pass tokens to proc-macro when nested +// nonterminals are involved. + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + + +macro_rules! wrap { + (first, $e:expr) => { wrap!(second, $e + 1) }; + (second, $e:expr) => { wrap!(third, $e + 2) }; + (third, $e:expr) => { + print_bang!($e + 3) + }; +} + +fn main() { + let _ = wrap!(first, 0); +} diff --git a/src/test/ui/proc-macro/nested-nonterminal-tokens.stdout b/src/test/ui/proc-macro/nested-nonterminal-tokens.stdout new file mode 100644 index 000000000..a3d24dd26 --- /dev/null +++ b/src/test/ui/proc-macro/nested-nonterminal-tokens.stdout @@ -0,0 +1,60 @@ +PRINT-BANG INPUT (DISPLAY): 0 + 1 + 2 + 3 +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/nested-nonterminal-tokens.rs:25:26: 25:27 (#0), + }, + ], + span: $DIR/nested-nonterminal-tokens.rs:17:41: 17:43 (#4), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nested-nonterminal-tokens.rs:17:44: 17:45 (#4), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nested-nonterminal-tokens.rs:17:46: 17:47 (#4), + }, + ], + span: $DIR/nested-nonterminal-tokens.rs:18:41: 18:43 (#5), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nested-nonterminal-tokens.rs:18:44: 18:45 (#5), + }, + Literal { + kind: Integer, + symbol: "2", + suffix: None, + span: $DIR/nested-nonterminal-tokens.rs:18:46: 18:47 (#5), + }, + ], + span: $DIR/nested-nonterminal-tokens.rs:20:21: 20:23 (#6), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nested-nonterminal-tokens.rs:20:24: 20:25 (#6), + }, + Literal { + kind: Integer, + symbol: "3", + suffix: None, + span: $DIR/nested-nonterminal-tokens.rs:20:26: 20:27 (#6), + }, +] diff --git a/src/test/ui/proc-macro/no-macro-use-attr.rs b/src/test/ui/proc-macro/no-macro-use-attr.rs new file mode 100644 index 000000000..a8a8fa4e1 --- /dev/null +++ b/src/test/ui/proc-macro/no-macro-use-attr.rs @@ -0,0 +1,10 @@ +// aux-build:test-macros.rs + +#![feature(rustc_attrs)] +#![warn(unused_extern_crates)] + +extern crate test_macros; +//~^ WARN unused extern crate + +#[rustc_error] +fn main() {} //~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/proc-macro/no-macro-use-attr.stderr b/src/test/ui/proc-macro/no-macro-use-attr.stderr new file mode 100644 index 000000000..a9e5256a0 --- /dev/null +++ b/src/test/ui/proc-macro/no-macro-use-attr.stderr @@ -0,0 +1,20 @@ +warning: unused extern crate + --> $DIR/no-macro-use-attr.rs:6:1 + | +LL | extern crate test_macros; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/no-macro-use-attr.rs:4:9 + | +LL | #![warn(unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: fatal error triggered by #[rustc_error] + --> $DIR/no-macro-use-attr.rs:10:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/test/ui/proc-macro/no-missing-docs.rs b/src/test/ui/proc-macro/no-missing-docs.rs new file mode 100644 index 000000000..e1e821858 --- /dev/null +++ b/src/test/ui/proc-macro/no-missing-docs.rs @@ -0,0 +1,16 @@ +//! Verify that the `decls` module implicitly added by the compiler does not cause `missing_docs` +//! warnings. + +// build-pass (FIXME(62277): could be check-pass?) +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(missing_docs)] + +extern crate proc_macro; +use proc_macro::*; + +/// Foo1. +#[proc_macro] +pub fn foo1(input: TokenStream) -> TokenStream { input } diff --git a/src/test/ui/proc-macro/nodelim-groups.rs b/src/test/ui/proc-macro/nodelim-groups.rs new file mode 100644 index 000000000..ec3019902 --- /dev/null +++ b/src/test/ui/proc-macro/nodelim-groups.rs @@ -0,0 +1,22 @@ +// run-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// edition:2018 +// +// Tests the pretty-printing behavior of inserting `Invisible`-delimited groups + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; +use test_macros::print_bang_consume; + +macro_rules! expand_it { + (($val1:expr) ($val2:expr)) => { expand_it!($val1 + $val2) }; + ($val:expr) => { print_bang_consume!("hi" $val (1 + 1)) }; +} + +fn main() { + expand_it!(1 + (25) + 1); + expand_it!(("hello".len()) ("world".len())); +} diff --git a/src/test/ui/proc-macro/nodelim-groups.stdout b/src/test/ui/proc-macro/nodelim-groups.stdout new file mode 100644 index 000000000..6b410f0bf --- /dev/null +++ b/src/test/ui/proc-macro/nodelim-groups.stdout @@ -0,0 +1,167 @@ +PRINT-BANG INPUT (DISPLAY): "hi" 1 + (25) + 1 (1 + 1) +PRINT-BANG INPUT (DEBUG): TokenStream [ + Literal { + kind: Str, + symbol: "hi", + suffix: None, + span: $DIR/nodelim-groups.rs:16:42: 16:46 (#4), + }, + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:20:16: 20:17 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:20:18: 20:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "25", + suffix: None, + span: $DIR/nodelim-groups.rs:20:21: 20:23 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:20:20: 20:24 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:20:25: 20:26 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:20:27: 20:28 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:16:47: 16:51 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:16:53: 16:54 (#4), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:16:55: 16:56 (#4), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:16:57: 16:58 (#4), + }, + ], + span: $DIR/nodelim-groups.rs:16:52: 16:59 (#4), + }, +] +PRINT-BANG INPUT (DISPLAY): "hi" "hello".len() + "world".len() (1 + 1) +PRINT-BANG INPUT (DEBUG): TokenStream [ + Literal { + kind: Str, + symbol: "hi", + suffix: None, + span: $DIR/nodelim-groups.rs:16:42: 16:46 (#9), + }, + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "hello", + suffix: None, + span: $DIR/nodelim-groups.rs:21:17: 21:24 (#0), + }, + Punct { + ch: '.', + spacing: Alone, + span: $DIR/nodelim-groups.rs:21:24: 21:25 (#0), + }, + Ident { + ident: "len", + span: $DIR/nodelim-groups.rs:21:25: 21:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/nodelim-groups.rs:21:28: 21:30 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:15:49: 15:54 (#8), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:15:55: 15:56 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "world", + suffix: None, + span: $DIR/nodelim-groups.rs:21:33: 21:40 (#0), + }, + Punct { + ch: '.', + spacing: Alone, + span: $DIR/nodelim-groups.rs:21:40: 21:41 (#0), + }, + Ident { + ident: "len", + span: $DIR/nodelim-groups.rs:21:41: 21:44 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/nodelim-groups.rs:21:44: 21:46 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:15:57: 15:62 (#8), + }, + ], + span: $DIR/nodelim-groups.rs:16:47: 16:51 (#9), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:16:53: 16:54 (#9), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:16:55: 16:56 (#9), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:16:57: 16:58 (#9), + }, + ], + span: $DIR/nodelim-groups.rs:16:52: 16:59 (#9), + }, +] diff --git a/src/test/ui/proc-macro/non-root.rs b/src/test/ui/proc-macro/non-root.rs new file mode 100644 index 000000000..a7c4ac00a --- /dev/null +++ b/src/test/ui/proc-macro/non-root.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +fn foo(arg: TokenStream) -> TokenStream { + #[proc_macro] + pub fn foo(arg: TokenStream) -> TokenStream { arg } + //~^ ERROR functions tagged with `#[proc_macro]` must currently reside in the root of the crate + + arg +} diff --git a/src/test/ui/proc-macro/non-root.stderr b/src/test/ui/proc-macro/non-root.stderr new file mode 100644 index 000000000..90f94b677 --- /dev/null +++ b/src/test/ui/proc-macro/non-root.stderr @@ -0,0 +1,8 @@ +error: functions tagged with `#[proc_macro]` must currently reside in the root of the crate + --> $DIR/non-root.rs:11:5 + | +LL | pub fn foo(arg: TokenStream) -> TokenStream { arg } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/nonterminal-expansion.rs b/src/test/ui/proc-macro/nonterminal-expansion.rs new file mode 100644 index 000000000..e62155871 --- /dev/null +++ b/src/test/ui/proc-macro/nonterminal-expansion.rs @@ -0,0 +1,37 @@ +// check-pass +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! pass_nonterminal { + ($line:expr) => { + #[print_attr_args(a, $line, b)] + struct S; + }; +} + +// `line!()` is not expanded before it's passed to the proc macro. +pass_nonterminal!(line!()); + +// Test case from #43860. + +#[macro_export] +macro_rules! use_contract { + ($name: ident, $path: expr) => { + #[derive(Empty)] + #[empty_helper(path = $path)] // OK + pub struct $name<T, C> { + api: T, + contract: C, + } + }; +} + +use_contract!(ContractName, file!()); + +fn main() {} diff --git a/src/test/ui/proc-macro/nonterminal-expansion.stdout b/src/test/ui/proc-macro/nonterminal-expansion.stdout new file mode 100644 index 000000000..4d884348f --- /dev/null +++ b/src/test/ui/proc-macro/nonterminal-expansion.stdout @@ -0,0 +1,42 @@ +PRINT-ATTR_ARGS INPUT (DISPLAY): a, line!(), b +PRINT-ATTR_ARGS RE-COLLECTED (DISPLAY): a, line! (), b +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "a", + span: $DIR/nonterminal-expansion.rs:13:27: 13:28 (#4), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/nonterminal-expansion.rs:13:28: 13:29 (#4), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "line", + span: $DIR/nonterminal-expansion.rs:19:19: 19:23 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/nonterminal-expansion.rs:19:23: 19:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/nonterminal-expansion.rs:19:24: 19:26 (#0), + }, + ], + span: $DIR/nonterminal-expansion.rs:13:30: 13:35 (#4), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/nonterminal-expansion.rs:13:35: 13:36 (#4), + }, + Ident { + ident: "b", + span: $DIR/nonterminal-expansion.rs:13:37: 13:38 (#4), + }, +] diff --git a/src/test/ui/proc-macro/nonterminal-recollect-attr.rs b/src/test/ui/proc-macro/nonterminal-recollect-attr.rs new file mode 100644 index 000000000..79c4ad4cd --- /dev/null +++ b/src/test/ui/proc-macro/nonterminal-recollect-attr.rs @@ -0,0 +1,21 @@ +// check-pass +// compile-flags: -Z span-debug +// aux-build:nonterminal-recollect-attr.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate nonterminal_recollect_attr; +use nonterminal_recollect_attr::*; + +macro_rules! my_macro { + ($v:ident) => { + #[first_attr] + $v struct Foo { + field: u8 + } + } +} + +my_macro!(pub); +fn main() {} diff --git a/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout new file mode 100644 index 000000000..6824395ae --- /dev/null +++ b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout @@ -0,0 +1,66 @@ +First recollected: TokenStream [ + Ident { + ident: "pub", + span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0), + }, + Ident { + ident: "struct", + span: $DIR/nonterminal-recollect-attr.rs:14:12: 14:18 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/nonterminal-recollect-attr.rs:14:19: 14:22 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/nonterminal-recollect-attr.rs:15:13: 15:18 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nonterminal-recollect-attr.rs:15:18: 15:19 (#4), + }, + Ident { + ident: "u8", + span: $DIR/nonterminal-recollect-attr.rs:15:20: 15:22 (#4), + }, + ], + span: $DIR/nonterminal-recollect-attr.rs:14:23: 16:10 (#4), + }, +] +Second recollected: TokenStream [ + Ident { + ident: "pub", + span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0), + }, + Ident { + ident: "struct", + span: $DIR/nonterminal-recollect-attr.rs:14:12: 14:18 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/nonterminal-recollect-attr.rs:14:19: 14:22 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/nonterminal-recollect-attr.rs:15:13: 15:18 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nonterminal-recollect-attr.rs:15:18: 15:19 (#4), + }, + Ident { + ident: "u8", + span: $DIR/nonterminal-recollect-attr.rs:15:20: 15:22 (#4), + }, + ], + span: $DIR/nonterminal-recollect-attr.rs:14:23: 16:10 (#4), + }, +] diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.rs b/src/test/ui/proc-macro/nonterminal-token-hygiene.rs new file mode 100644 index 000000000..fa52a975b --- /dev/null +++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.rs @@ -0,0 +1,34 @@ +// Make sure that marks from declarative macros are applied to tokens in nonterminal. + +// check-pass +// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene +// compile-flags: -Z trim-diagnostic-paths=no +// normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" +// aux-build:test-macros.rs + +#![feature(decl_macro)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! outer { + ($item:item) => { + macro inner() { + print_bang! { $item } + } + + inner!(); + }; +} + +struct S; + +outer! { + struct S; // OK, not a duplicate definition of `S` +} + +fn main() {} diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout new file mode 100644 index 000000000..c08e53081 --- /dev/null +++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -0,0 +1,92 @@ +PRINT-BANG INPUT (DISPLAY): struct S; +PRINT-BANG RE-COLLECTED (DISPLAY): struct S ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "struct", + span: $DIR/nonterminal-token-hygiene.rs:31:5: 31:11 (#5), + }, + Ident { + ident: "S", + span: $DIR/nonterminal-token-hygiene.rs:31:12: 31:13 (#5), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/nonterminal-token-hygiene.rs:31:13: 31:14 (#5), + }, + ], + span: $DIR/nonterminal-token-hygiene.rs:21:27: 21:32 (#6), + }, +] +#![feature /* 0#0 */(prelude_import)] +#![no_std /* 0#0 */] +// Make sure that marks from declarative macros are applied to tokens in nonterminal. + +// check-pass +// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene +// compile-flags: -Z trim-diagnostic-paths=no +// normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" +// aux-build:test-macros.rs + +#![feature /* 0#0 */(decl_macro)] + +#![no_std /* 0#0 */] +#[prelude_import /* 0#1 */] +use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*; +#[macro_use /* 0#1 */] +extern crate core /* 0#2 */; +#[macro_use /* 0#1 */] +extern crate compiler_builtins /* 0#2 */; +// Don't load unnecessary hygiene information from std +extern crate std /* 0#0 */; + +#[macro_use /* 0#0 */] +extern crate test_macros /* 0#0 */; + +macro_rules! outer + /* + 0#0 + */ { + ($item : item) => + { + macro inner() { print_bang! { $item } } inner! () ; + + } ; +} + +struct S /* 0#0 */; +macro inner /* 0#4 */ { () => { print_bang! { struct S; } } } + +struct S /* 0#5 */; +// OK, not a duplicate definition of `S` + +fn main /* 0#0 */() {} + +/* +Expansions: +crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) +crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") +crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") +crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) + +SyntaxContexts: +#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) +#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) +#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque) +#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#6: parent: #4, outer_mark: (crate0::{{expn3}}, Opaque) +#7: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) +#8: parent: #6, outer_mark: (crate0::{{expn4}}, Transparent) +#9: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) +*/ diff --git a/src/test/ui/proc-macro/not-joint.rs b/src/test/ui/proc-macro/not-joint.rs new file mode 100644 index 000000000..30da2811e --- /dev/null +++ b/src/test/ui/proc-macro/not-joint.rs @@ -0,0 +1,24 @@ +// run-pass +// aux-build:not-joint.rs + +extern crate not_joint as bar; +use bar::{tokens, nothing}; + +tokens![< -]; + +#[nothing] +a![< -]; + +#[nothing] +b!{< -} + +#[nothing] +c!(< -); + +#[nothing] +fn foo() { + //! dox + let x = 2 < - 3; +} + +fn main() {} diff --git a/src/test/ui/proc-macro/out-of-line-mod.rs b/src/test/ui/proc-macro/out-of-line-mod.rs new file mode 100644 index 000000000..658ed6c18 --- /dev/null +++ b/src/test/ui/proc-macro/out-of-line-mod.rs @@ -0,0 +1,13 @@ +// Out-of-line module is found on the filesystem if passed through a proc macro (issue #58818). + +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +mod outer { + identity! { mod inner; } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/outer/inner.rs b/src/test/ui/proc-macro/outer/inner.rs new file mode 100644 index 000000000..5777ed899 --- /dev/null +++ b/src/test/ui/proc-macro/outer/inner.rs @@ -0,0 +1 @@ +// ignore-test diff --git a/src/test/ui/proc-macro/parent-source-spans.rs b/src/test/ui/proc-macro/parent-source-spans.rs new file mode 100644 index 000000000..354657db4 --- /dev/null +++ b/src/test/ui/proc-macro/parent-source-spans.rs @@ -0,0 +1,53 @@ +// aux-build:parent-source-spans.rs + +#![feature(decl_macro)] + +extern crate parent_source_spans; + +use parent_source_spans::parent_source_spans; + +macro one($a:expr, $b:expr) { + two!($a, $b); + //~^ ERROR first parent: "hello" + //~| ERROR second parent: "world" +} + +macro two($a:expr, $b:expr) { + three!($a, $b); + //~^ ERROR first final: "hello" + //~| ERROR second final: "world" + //~| ERROR first final: "yay" + //~| ERROR second final: "rust" +} + +// forwarding tokens directly doesn't create a new source chain +macro three($($tokens:tt)*) { + four!($($tokens)*); +} + +macro four($($tokens:tt)*) { + parent_source_spans!($($tokens)*); + //~^ ERROR cannot find value `ok` in this scope + //~| ERROR cannot find value `ok` in this scope + //~| ERROR cannot find value `ok` in this scope +} + +fn main() { + one!("hello", "world"); + //~^ ERROR first grandparent: "hello" + //~| ERROR second grandparent: "world" + //~| ERROR first source: "hello" + //~| ERROR second source: "world" + + two!("yay", "rust"); + //~^ ERROR first parent: "yay" + //~| ERROR second parent: "rust" + //~| ERROR first source: "yay" + //~| ERROR second source: "rust" + + three!("hip", "hop"); + //~^ ERROR first final: "hip" + //~| ERROR second final: "hop" + //~| ERROR first source: "hip" + //~| ERROR second source: "hop" +} diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr new file mode 100644 index 000000000..65ce24e55 --- /dev/null +++ b/src/test/ui/proc-macro/parent-source-spans.stderr @@ -0,0 +1,189 @@ +error: first final: "hello" + --> $DIR/parent-source-spans.rs:16:12 + | +LL | three!($a, $b); + | ^^ +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `two` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: second final: "world" + --> $DIR/parent-source-spans.rs:16:16 + | +LL | three!($a, $b); + | ^^ +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `two` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: first parent: "hello" + --> $DIR/parent-source-spans.rs:10:5 + | +LL | two!($a, $b); + | ^^^^^^^^^^^^ +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: second parent: "world" + --> $DIR/parent-source-spans.rs:10:5 + | +LL | two!($a, $b); + | ^^^^^^^^^^^^ +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: first grandparent: "hello" + --> $DIR/parent-source-spans.rs:36:5 + | +LL | one!("hello", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: second grandparent: "world" + --> $DIR/parent-source-spans.rs:36:5 + | +LL | one!("hello", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: first source: "hello" + --> $DIR/parent-source-spans.rs:36:5 + | +LL | one!("hello", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: second source: "world" + --> $DIR/parent-source-spans.rs:36:5 + | +LL | one!("hello", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: first final: "yay" + --> $DIR/parent-source-spans.rs:16:12 + | +LL | three!($a, $b); + | ^^ +... +LL | two!("yay", "rust"); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: second final: "rust" + --> $DIR/parent-source-spans.rs:16:16 + | +LL | three!($a, $b); + | ^^ +... +LL | two!("yay", "rust"); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: first parent: "yay" + --> $DIR/parent-source-spans.rs:42:5 + | +LL | two!("yay", "rust"); + | ^^^^^^^^^^^^^^^^^^^ + +error: second parent: "rust" + --> $DIR/parent-source-spans.rs:42:5 + | +LL | two!("yay", "rust"); + | ^^^^^^^^^^^^^^^^^^^ + +error: first source: "yay" + --> $DIR/parent-source-spans.rs:42:5 + | +LL | two!("yay", "rust"); + | ^^^^^^^^^^^^^^^^^^^ + +error: second source: "rust" + --> $DIR/parent-source-spans.rs:42:5 + | +LL | two!("yay", "rust"); + | ^^^^^^^^^^^^^^^^^^^ + +error: first final: "hip" + --> $DIR/parent-source-spans.rs:48:12 + | +LL | three!("hip", "hop"); + | ^^^^^ + +error: second final: "hop" + --> $DIR/parent-source-spans.rs:48:19 + | +LL | three!("hip", "hop"); + | ^^^^^ + +error: first source: "hip" + --> $DIR/parent-source-spans.rs:48:12 + | +LL | three!("hip", "hop"); + | ^^^^^ + +error: second source: "hop" + --> $DIR/parent-source-spans.rs:48:19 + | +LL | three!("hip", "hop"); + | ^^^^^ + +error[E0425]: cannot find value `ok` in this scope + --> $DIR/parent-source-spans.rs:29:5 + | +LL | parent_source_spans!($($tokens)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + | + ::: $SRC_DIR/core/src/result.rs:LL:COL + | +LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), + | -- similarly named tuple variant `Ok` defined here + | + = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `ok` in this scope + --> $DIR/parent-source-spans.rs:29:5 + | +LL | parent_source_spans!($($tokens)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` +... +LL | two!("yay", "rust"); + | ------------------- in this macro invocation + | + ::: $SRC_DIR/core/src/result.rs:LL:COL + | +LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), + | -- similarly named tuple variant `Ok` defined here + | + = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `ok` in this scope + --> $DIR/parent-source-spans.rs:29:5 + | +LL | parent_source_spans!($($tokens)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` +... +LL | three!("hip", "hop"); + | -------------------- in this macro invocation + | + ::: $SRC_DIR/core/src/result.rs:LL:COL + | +LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), + | -- similarly named tuple variant `Ok` defined here + | + = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `three` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/proc-macro/pretty-print-tts.rs b/src/test/ui/proc-macro/pretty-print-tts.rs new file mode 100644 index 000000000..ffe2a7415 --- /dev/null +++ b/src/test/ui/proc-macro/pretty-print-tts.rs @@ -0,0 +1,20 @@ +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +// Tests the pretty-printing behavior of various (unparsed) tokens +print_bang_consume!({ + #![rustc_dummy] + let a = "hello".len(); + matches!(a, 5); +}); + +fn main() {} diff --git a/src/test/ui/proc-macro/pretty-print-tts.stdout b/src/test/ui/proc-macro/pretty-print-tts.stdout new file mode 100644 index 000000000..f52e97a86 --- /dev/null +++ b/src/test/ui/proc-macro/pretty-print-tts.stdout @@ -0,0 +1,102 @@ +PRINT-BANG INPUT (DISPLAY): { #! [rustc_dummy] let a = "hello".len() ; matches! (a, 5) ; } +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/pretty-print-tts.rs:15:5: 15:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:15:6: 15:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/pretty-print-tts.rs:15:8: 15:19 (#0), + }, + ], + span: $DIR/pretty-print-tts.rs:15:7: 15:20 (#0), + }, + Ident { + ident: "let", + span: $DIR/pretty-print-tts.rs:16:5: 16:8 (#0), + }, + Ident { + ident: "a", + span: $DIR/pretty-print-tts.rs:16:9: 16:10 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:16:11: 16:12 (#0), + }, + Literal { + kind: Str, + symbol: "hello", + suffix: None, + span: $DIR/pretty-print-tts.rs:16:13: 16:20 (#0), + }, + Punct { + ch: '.', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:16:20: 16:21 (#0), + }, + Ident { + ident: "len", + span: $DIR/pretty-print-tts.rs:16:21: 16:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/pretty-print-tts.rs:16:24: 16:26 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:16:26: 16:27 (#0), + }, + Ident { + ident: "matches", + span: $DIR/pretty-print-tts.rs:17:5: 17:12 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:17:12: 17:13 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/pretty-print-tts.rs:17:14: 17:15 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:17:15: 17:16 (#0), + }, + Literal { + kind: Integer, + symbol: "5", + suffix: None, + span: $DIR/pretty-print-tts.rs:17:17: 17:18 (#0), + }, + ], + span: $DIR/pretty-print-tts.rs:17:13: 17:19 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:17:19: 17:20 (#0), + }, + ], + span: $DIR/pretty-print-tts.rs:14:21: 18:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs new file mode 100644 index 000000000..8d96381b9 --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-attributes.rs @@ -0,0 +1,22 @@ +// aux-build:derive-b.rs + +#[macro_use] +extern crate derive_b; + +#[B] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[C] //~ ERROR cannot find attribute `C` in this scope +#[B(D)] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[B(E = "foo")] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[B(arbitrary tokens)] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[derive(B)] +struct B; + +fn main() {} diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr new file mode 100644 index 000000000..b66e4575e --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr @@ -0,0 +1,130 @@ +error: cannot find attribute `C` in this scope + --> $DIR/proc-macro-attributes.rs:9:3 + | +LL | #[C] + | ^ help: a derive helper attribute with a similar name exists: `B` + +error[E0659]: `B` is ambiguous + --> $DIR/proc-macro-attributes.rs:6:3 + | +LL | #[B] + | ^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:19:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error[E0659]: `B` is ambiguous + --> $DIR/proc-macro-attributes.rs:10:3 + | +LL | #[B(D)] + | ^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:19:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error[E0659]: `B` is ambiguous + --> $DIR/proc-macro-attributes.rs:13:3 + | +LL | #[B(E = "foo")] + | ^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:19:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error[E0659]: `B` is ambiguous + --> $DIR/proc-macro-attributes.rs:16:3 + | +LL | #[B(arbitrary tokens)] + | ^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:19:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:6:3 + | +LL | #[B] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = note: `#[warn(legacy_derive_helpers)]` on by default + = 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 #79202 <https://github.com/rust-lang/rust/issues/79202> + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:10:3 + | +LL | #[B(D)] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = 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 #79202 <https://github.com/rust-lang/rust/issues/79202> + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:13:3 + | +LL | #[B(E = "foo")] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = 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 #79202 <https://github.com/rust-lang/rust/issues/79202> + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:16:3 + | +LL | #[B(arbitrary tokens)] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = 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 #79202 <https://github.com/rust-lang/rust/issues/79202> + +error: aborting due to 5 previous errors; 4 warnings emitted + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs b/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs new file mode 100644 index 000000000..f1144a4a5 --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs @@ -0,0 +1,16 @@ +// check-pass +// force-host +// no-prefer-dynamic + +#![deny(deprecated)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +#[deprecated(since = "1.0.0", note = "test")] +pub fn test_compile_without_warning_with_deprecated(_: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs new file mode 100644 index 000000000..e2cf4e739 --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-gates.rs @@ -0,0 +1,53 @@ +// aux-build:test-macros.rs +// gate-test-proc_macro_hygiene + +#![feature(stmt_expr_attributes)] + +#[macro_use] +extern crate test_macros; + +fn _test_inner() { + #![empty_attr] //~ ERROR: inner macro attributes are unstable +} + +mod _test2_inner { + #![empty_attr] //~ ERROR: inner macro attributes are unstable +} + +#[empty_attr = "y"] //~ ERROR: key-value macro attributes are not supported +fn _test3() {} + +fn attrs() { + // Statement, item + #[empty_attr] // OK + struct S; + + // Statement, macro + #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements + println!(); + + // Statement, semi + #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements + S; + + // Statement, local + #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements + let _x = 2; + + // Expr + let _x = #[identity_attr] 2; //~ ERROR: custom attributes cannot be applied to expressions + + // Opt expr + let _x = [#[identity_attr] 2]; //~ ERROR: custom attributes cannot be applied to expressions + + // Expr macro + let _x = #[identity_attr] println!(); + //~^ ERROR: custom attributes cannot be applied to expressions +} + +fn test_case() { + #![test] //~ ERROR inner macro attributes are unstable + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr new file mode 100644 index 000000000..118213a17 --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-gates.stderr @@ -0,0 +1,91 @@ +error[E0658]: inner macro attributes are unstable + --> $DIR/proc-macro-gates.rs:10:8 + | +LL | #![empty_attr] + | ^^^^^^^^^^ + | + = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + +error[E0658]: inner macro attributes are unstable + --> $DIR/proc-macro-gates.rs:14:8 + | +LL | #![empty_attr] + | ^^^^^^^^^^ + | + = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + +error: key-value macro attributes are not supported + --> $DIR/proc-macro-gates.rs:17:1 + | +LL | #[empty_attr = "y"] + | ^^^^^^^^^^^^^^^^^^^ + +error[E0658]: custom attributes cannot be applied to statements + --> $DIR/proc-macro-gates.rs:26:5 + | +LL | #[empty_attr] + | ^^^^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to statements + --> $DIR/proc-macro-gates.rs:30:5 + | +LL | #[empty_attr] + | ^^^^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to statements + --> $DIR/proc-macro-gates.rs:34:5 + | +LL | #[empty_attr] + | ^^^^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to expressions + --> $DIR/proc-macro-gates.rs:38:14 + | +LL | let _x = #[identity_attr] 2; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to expressions + --> $DIR/proc-macro-gates.rs:41:15 + | +LL | let _x = [#[identity_attr] 2]; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to expressions + --> $DIR/proc-macro-gates.rs:44:14 + | +LL | let _x = #[identity_attr] println!(); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error: inner macro attributes are unstable + --> $DIR/proc-macro-gates.rs:49:8 + | +LL | #![test] + | ^^^^ + | + = note: `#[deny(soft_unstable)]` on by default + = 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 #64266 <https://github.com/rust-lang/rust/issues/64266> + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/proc-macro-gates2.rs b/src/test/ui/proc-macro/proc-macro-gates2.rs new file mode 100644 index 000000000..38fbd4733 --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-gates2.rs @@ -0,0 +1,24 @@ +// aux-build:test-macros.rs + +#![feature(stmt_expr_attributes)] + +#[macro_use] +extern crate test_macros; + +// NB. these errors aren't the best errors right now, but they're definitely +// intended to be errors. Somehow using a custom attribute in these positions +// should either require a feature gate or not be allowed on stable. + +fn _test6<#[empty_attr] T>() {} +//~^ ERROR: expected non-macro attribute, found attribute macro + +fn _test7() { + match 1 { + #[empty_attr] //~ ERROR: expected non-macro attribute, found attribute macro + 0 => {} + _ => {} + } +} + +fn main() { +} diff --git a/src/test/ui/proc-macro/proc-macro-gates2.stderr b/src/test/ui/proc-macro/proc-macro-gates2.stderr new file mode 100644 index 000000000..64df34e7c --- /dev/null +++ b/src/test/ui/proc-macro/proc-macro-gates2.stderr @@ -0,0 +1,14 @@ +error: expected non-macro attribute, found attribute macro `empty_attr` + --> $DIR/proc-macro-gates2.rs:12:13 + | +LL | fn _test6<#[empty_attr] T>() {} + | ^^^^^^^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `empty_attr` + --> $DIR/proc-macro-gates2.rs:17:11 + | +LL | #[empty_attr] + | ^^^^^^^^^^ not a non-macro attribute + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/proc-macro/pub-at-crate-root.rs b/src/test/ui/proc-macro/pub-at-crate-root.rs new file mode 100644 index 000000000..54cf333a4 --- /dev/null +++ b/src/test/ui/proc-macro/pub-at-crate-root.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +pub mod a { //~ `proc-macro` crate types currently cannot export any items + use proc_macro::TokenStream; + + #[proc_macro_derive(B)] + pub fn bar(a: TokenStream) -> TokenStream { + //~^ ERROR: must currently reside in the root of the crate + a + } +} + +#[proc_macro_derive(B)] +fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream { +//~^ ERROR: functions tagged with `#[proc_macro_derive]` must be `pub` + a +} diff --git a/src/test/ui/proc-macro/pub-at-crate-root.stderr b/src/test/ui/proc-macro/pub-at-crate-root.stderr new file mode 100644 index 000000000..2e7536a0c --- /dev/null +++ b/src/test/ui/proc-macro/pub-at-crate-root.stderr @@ -0,0 +1,20 @@ +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/pub-at-crate-root.rs:8:1 + | +LL | pub mod a { + | ^^^^^^^^^ + +error: functions tagged with `#[proc_macro_derive]` must currently reside in the root of the crate + --> $DIR/pub-at-crate-root.rs:12:5 + | +LL | pub fn bar(a: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions tagged with `#[proc_macro_derive]` must be `pub` + --> $DIR/pub-at-crate-root.rs:19:1 + | +LL | fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/proc-macro/quote-debug.rs b/src/test/ui/proc-macro/quote-debug.rs new file mode 100644 index 000000000..e0304a014 --- /dev/null +++ b/src/test/ui/proc-macro/quote-debug.rs @@ -0,0 +1,18 @@ +// check-pass +// force-host +// no-prefer-dynamic +// compile-flags: -Z unpretty=expanded +// +// This file is not actually used as a proc-macro - instead, +// it's just used to show the output of the `quote!` macro + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +fn main() { + proc_macro::quote! { + let hello = "world"; + } +} diff --git a/src/test/ui/proc-macro/quote-debug.stdout b/src/test/ui/proc-macro/quote-debug.stdout new file mode 100644 index 000000000..d2cc5c6e2 --- /dev/null +++ b/src/test/ui/proc-macro/quote-debug.stdout @@ -0,0 +1,47 @@ +#![feature(prelude_import)] +#![no_std] +// check-pass +// force-host +// no-prefer-dynamic +// compile-flags: -Z unpretty=expanded +// +// This file is not actually used as a proc-macro - instead, +// it's just used to show the output of the `quote!` macro + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +extern crate proc_macro; + +fn main() { + [crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("let", + crate::Span::recover_proc_macro_span(0)))), + crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("hello", + crate::Span::recover_proc_macro_span(1)))), + crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('=', + crate::Spacing::Alone))), + crate::TokenStream::from(crate::TokenTree::Literal({ + let mut iter = + "\"world\"".parse::<crate::TokenStream>().unwrap().into_iter(); + if let (Some(crate::TokenTree::Literal(mut lit)), None) = + (iter.next(), iter.next()) { + lit.set_span(crate::Span::recover_proc_macro_span(2)); + lit + } else { + ::core::panicking::panic("internal error: entered unreachable code") + } + })), + crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new(';', + crate::Spacing::Alone)))].iter().cloned().collect::<crate::TokenStream>() +} +const _: () = + { + extern crate proc_macro; + #[rustc_proc_macro_decls] + #[allow(deprecated)] + static _DECLS: &[proc_macro::bridge::client::ProcMacro] = &[]; + }; diff --git a/src/test/ui/proc-macro/raw-ident.rs b/src/test/ui/proc-macro/raw-ident.rs new file mode 100644 index 000000000..03cb45714 --- /dev/null +++ b/src/test/ui/proc-macro/raw-ident.rs @@ -0,0 +1,16 @@ +// aux-build:raw-ident.rs + +#[macro_use] extern crate raw_ident; + +fn main() { + make_struct!(fn); + make_struct!(Foo); + make_struct!(await); + + r#fn; + r#Foo; + Foo; + r#await; + + make_bad_struct!(S); //~ ERROR expected one of +} diff --git a/src/test/ui/proc-macro/raw-ident.stderr b/src/test/ui/proc-macro/raw-ident.stderr new file mode 100644 index 000000000..905a5f946 --- /dev/null +++ b/src/test/ui/proc-macro/raw-ident.stderr @@ -0,0 +1,10 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `S` + --> $DIR/raw-ident.rs:15:5 + | +LL | make_bad_struct!(S); + | ^^^^^^^^^^^^^^^^^^^ expected one of 8 possible tokens + | + = note: this error originates in the macro `make_bad_struct` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/reserved-macro-names.rs b/src/test/ui/proc-macro/reserved-macro-names.rs new file mode 100644 index 000000000..c5e71a87d --- /dev/null +++ b/src/test/ui/proc-macro/reserved-macro-names.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream { + //~^ ERROR name `cfg` is reserved in attribute namespace + input +} + +#[proc_macro_attribute] +pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream { + //~^ ERROR name `cfg_attr` is reserved in attribute namespace + input +} diff --git a/src/test/ui/proc-macro/reserved-macro-names.stderr b/src/test/ui/proc-macro/reserved-macro-names.stderr new file mode 100644 index 000000000..39bdd03be --- /dev/null +++ b/src/test/ui/proc-macro/reserved-macro-names.stderr @@ -0,0 +1,14 @@ +error: name `cfg` is reserved in attribute namespace + --> $DIR/reserved-macro-names.rs:10:8 + | +LL | pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream { + | ^^^ + +error: name `cfg_attr` is reserved in attribute namespace + --> $DIR/reserved-macro-names.rs:16:8 + | +LL | pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream { + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs new file mode 100644 index 000000000..ad8a5bbb0 --- /dev/null +++ b/src/test/ui/proc-macro/resolve-error.rs @@ -0,0 +1,62 @@ +// aux-build:derive-foo.rs +// aux-build:derive-clona.rs +// aux-build:test-macros.rs + +#[macro_use] +extern crate derive_foo; +#[macro_use] +extern crate derive_clona; +extern crate test_macros; + +use test_macros::empty as bang_proc_macro; +use test_macros::empty_attr as attr_proc_macro; + +macro_rules! FooWithLongNam { + () => {} +} + +macro_rules! attr_proc_mac { + () => {} +} + +#[derive(FooWithLongNan)] +//~^ ERROR cannot find +//~| ERROR cannot find +struct Foo; + +// Interpreted as an unstable custom attribute +#[attr_proc_macra] //~ ERROR cannot find attribute `attr_proc_macra` in this scope +struct Bar; + +// Interpreted as an unstable custom attribute +#[FooWithLongNan] //~ ERROR cannot find attribute `FooWithLongNan` in this scope +struct Asdf; + +#[derive(Dlone)] +//~^ ERROR cannot find +//~| ERROR cannot find +struct A; + +#[derive(Dlona)] +//~^ ERROR cannot find +//~| ERROR cannot find +struct B; + +#[derive(attr_proc_macra)] +//~^ ERROR cannot find +//~| ERROR cannot find +struct C; + +fn main() { + FooWithLongNama!(); + //~^ ERROR cannot find + + attr_proc_macra!(); + //~^ ERROR cannot find + + Dlona!(); + //~^ ERROR cannot find + + bang_proc_macrp!(); + //~^ ERROR cannot find +} diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr new file mode 100644 index 000000000..a534b9d53 --- /dev/null +++ b/src/test/ui/proc-macro/resolve-error.stderr @@ -0,0 +1,132 @@ +error: cannot find macro `bang_proc_macrp` in this scope + --> $DIR/resolve-error.rs:60:5 + | +LL | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro` + | + ::: $DIR/auxiliary/test-macros.rs:15:1 + | +LL | pub fn empty(_: TokenStream) -> TokenStream { + | ------------------------------------------- similarly named macro `bang_proc_macro` defined here + +error: cannot find macro `Dlona` in this scope + --> $DIR/resolve-error.rs:57:5 + | +LL | Dlona!(); + | ^^^^^ + +error: cannot find macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:54:5 + | +LL | macro_rules! attr_proc_mac { + | -------------------------- similarly named macro `attr_proc_mac` defined here +... +LL | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac` + +error: cannot find macro `FooWithLongNama` in this scope + --> $DIR/resolve-error.rs:51:5 + | +LL | macro_rules! FooWithLongNam { + | --------------------------- similarly named macro `FooWithLongNam` defined here +... +LL | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam` + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:45:10 + | +LL | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:45:10 + | +LL | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:40:10 + | +LL | #[derive(Dlona)] + | ^^^^^ help: a derive macro with a similar name exists: `Clona` + | + ::: $DIR/auxiliary/derive-clona.rs:11:1 + | +LL | pub fn derive_clonea(input: TokenStream) -> TokenStream { + | ------------------------------------------------------- similarly named derive macro `Clona` defined here + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:40:10 + | +LL | #[derive(Dlona)] + | ^^^^^ help: a derive macro with a similar name exists: `Clona` + | + ::: $DIR/auxiliary/derive-clona.rs:11:1 + | +LL | pub fn derive_clonea(input: TokenStream) -> TokenStream { + | ------------------------------------------------------- similarly named derive macro `Clona` defined here + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:35:10 + | +LL | #[derive(Dlone)] + | ^^^^^ help: a derive macro with a similar name exists: `Clone` + | + ::: $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | pub macro Clone($item:item) { + | --------------- similarly named derive macro `Clone` defined here + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:35:10 + | +LL | #[derive(Dlone)] + | ^^^^^ help: a derive macro with a similar name exists: `Clone` + | + ::: $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | pub macro Clone($item:item) { + | --------------- similarly named derive macro `Clone` defined here + +error: cannot find attribute `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:32:3 + | +LL | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ + +error: cannot find attribute `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:28:3 + | +LL | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro` + | + ::: $DIR/auxiliary/test-macros.rs:20:1 + | +LL | pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream { + | ---------------------------------------------------------------- similarly named attribute macro `attr_proc_macro` defined here + +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:22:10 + | +LL | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` + | + ::: $DIR/auxiliary/derive-foo.rs:11:1 + | +LL | pub fn derive_foo(input: TokenStream) -> TokenStream { + | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here + +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:22:10 + | +LL | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` + | + ::: $DIR/auxiliary/derive-foo.rs:11:1 + | +LL | pub fn derive_foo(input: TokenStream) -> TokenStream { + | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here + +error: aborting due to 14 previous errors + diff --git a/src/test/ui/proc-macro/resolved-located-at.rs b/src/test/ui/proc-macro/resolved-located-at.rs new file mode 100644 index 000000000..b785573f2 --- /dev/null +++ b/src/test/ui/proc-macro/resolved-located-at.rs @@ -0,0 +1,10 @@ +// aux-build:resolved-located-at.rs + +#[macro_use] +extern crate resolved_located_at; + +fn main() { + resolve_located_at!(a b) + //~^ ERROR expected error + //~| ERROR mismatched types +} diff --git a/src/test/ui/proc-macro/resolved-located-at.stderr b/src/test/ui/proc-macro/resolved-located-at.stderr new file mode 100644 index 000000000..422820e9d --- /dev/null +++ b/src/test/ui/proc-macro/resolved-located-at.stderr @@ -0,0 +1,21 @@ +error: expected error + --> $DIR/resolved-located-at.rs:7:25 + | +LL | resolve_located_at!(a b) + | ^ + | + = note: this error originates in the macro `resolve_located_at` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/resolved-located-at.rs:7:27 + | +LL | fn main() { + | - expected `()` because of default return type +LL | resolve_located_at!(a b) + | ^ expected `()`, found struct `S` + | + = note: this error originates in the macro `resolve_located_at` (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 E0308`. diff --git a/src/test/ui/proc-macro/shadow.rs b/src/test/ui/proc-macro/shadow.rs new file mode 100644 index 000000000..61959594c --- /dev/null +++ b/src/test/ui/proc-macro/shadow.rs @@ -0,0 +1,8 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; +#[macro_use] +extern crate test_macros; //~ ERROR the name `test_macros` is defined multiple times + +fn main() {} diff --git a/src/test/ui/proc-macro/shadow.stderr b/src/test/ui/proc-macro/shadow.stderr new file mode 100644 index 000000000..e7d95cc83 --- /dev/null +++ b/src/test/ui/proc-macro/shadow.stderr @@ -0,0 +1,14 @@ +error[E0259]: the name `test_macros` is defined multiple times + --> $DIR/shadow.rs:6:1 + | +LL | extern crate test_macros; + | ------------------------- previous import of the extern crate `test_macros` here +LL | #[macro_use] +LL | extern crate test_macros; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `test_macros` reimported here + | + = note: `test_macros` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/proc-macro/signature.rs b/src/test/ui/proc-macro/signature.rs new file mode 100644 index 000000000..230223825 --- /dev/null +++ b/src/test/ui/proc-macro/signature.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![allow(warnings)] + +extern crate proc_macro; + +#[proc_macro_derive(A)] +pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 { + //~^ ERROR: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn + loop {} +} diff --git a/src/test/ui/proc-macro/signature.stderr b/src/test/ui/proc-macro/signature.stderr new file mode 100644 index 000000000..a6bd98ddb --- /dev/null +++ b/src/test/ui/proc-macro/signature.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn(i32, u32) -> u32 {foo}` + --> $DIR/signature.rs:10:1 + | +LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 { +LL | | +LL | | loop {} +LL | | } + | |_^ call the function in a closure: `|| unsafe { /* code */ }` + | + = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}` + = note: unsafe function cannot be called generically without an unsafe block +note: required by a bound in `ProcMacro::custom_derive` + --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL + | +LL | expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ProcMacro::custom_derive` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/proc-macro/smoke.rs b/src/test/ui/proc-macro/smoke.rs new file mode 100644 index 000000000..04625559b --- /dev/null +++ b/src/test/ui/proc-macro/smoke.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(path_statements)] +// aux-build:derive-a.rs + +#[macro_use] +extern crate derive_a; + +#[derive(Debug, PartialEq, A, Eq, Copy, Clone)] +struct A; + +fn main() { + A; + assert_eq!(A, A); + A.clone(); + let a = A; + let _c = a; + let _d = a; +} diff --git a/src/test/ui/proc-macro/span-absolute-posititions.rs b/src/test/ui/proc-macro/span-absolute-posititions.rs new file mode 100644 index 000000000..6d70fe611 --- /dev/null +++ b/src/test/ui/proc-macro/span-absolute-posititions.rs @@ -0,0 +1,24 @@ +// aux-build:assert-span-pos.rs +// ignore-tidy-tab +extern crate assert_span_pos; + +assert_span_pos::assert_span_pos!(5, 35); + +// Test space indentation + assert_span_pos::assert_span_pos!(8, 39); +// Test tab indentation + assert_span_pos::assert_span_pos!(10, 36); + +// Two tests to ensure the promise of the docs that the column is the number +// of UTF-8 bytes instead of some other number like number of code points. + +// Test that multi byte UTF-8 characters indeed count as multiple bytes +/*🌈*/assert_span_pos::assert_span_pos!(16, 40); +// Test with a complete grapheme cluster +/*🏳️🌈*/assert_span_pos::assert_span_pos!(18, 43); + +// Test that the macro actually emits an error on a mismatch: +assert_span_pos::assert_span_pos!(0, 35); //~ ERROR line/column mismatch: (0, 35) != (21, 35) +assert_span_pos::assert_span_pos!(22, 0); //~ ERROR line/column mismatch: (22, 0) != (22, 35) + +fn main() {} diff --git a/src/test/ui/proc-macro/span-absolute-posititions.stderr b/src/test/ui/proc-macro/span-absolute-posititions.stderr new file mode 100644 index 000000000..6aca44a6b --- /dev/null +++ b/src/test/ui/proc-macro/span-absolute-posititions.stderr @@ -0,0 +1,14 @@ +error: line/column mismatch: (0, 35) != (21, 35) + --> $DIR/span-absolute-posititions.rs:21:35 + | +LL | assert_span_pos::assert_span_pos!(0, 35); + | ^ + +error: line/column mismatch: (22, 0) != (22, 35) + --> $DIR/span-absolute-posititions.rs:22:35 + | +LL | assert_span_pos::assert_span_pos!(22, 0); + | ^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/proc-macro/span-api-tests.rs b/src/test/ui/proc-macro/span-api-tests.rs new file mode 100644 index 000000000..914ad54ed --- /dev/null +++ b/src/test/ui/proc-macro/span-api-tests.rs @@ -0,0 +1,61 @@ +// run-pass +// ignore-pretty +// aux-build:span-api-tests.rs +// aux-build:span-test-macros.rs + +#[macro_use] +extern crate span_test_macros; + +extern crate span_api_tests; + +// FIXME(69775): Investigate `assert_fake_source_file`. + +use span_api_tests::{reemit, assert_source_file, macro_stringify}; + +macro_rules! say_hello { + ($macname:ident) => ( $macname! { "Hello, world!" }) +} + +assert_source_file! { "Hello, world!" } + +say_hello! { assert_source_file } + +reemit_legacy! { + assert_source_file! { "Hello, world!" } +} + +say_hello_extern! { assert_source_file } + +reemit! { + assert_source_file! { "Hello, world!" } +} + +fn main() { + let s = macro_stringify!(Hello, world!); + assert_eq!(s, "Hello, world!"); + assert_eq!(macro_stringify!(Hello, world!), "Hello, world!"); + assert_eq!(reemit_legacy!(macro_stringify!(Hello, world!)), "Hello, world!"); + reemit_legacy!(assert_eq!(macro_stringify!(Hello, world!), "Hello, world!")); + // reemit change the span to be that of the call site + assert_eq!( + reemit!(macro_stringify!(Hello, world!)), + "reemit!(macro_stringify!(Hello, world!))" + ); + let r = "reemit!(assert_eq!(macro_stringify!(Hello, world!), r))"; + reemit!(assert_eq!(macro_stringify!(Hello, world!), r)); + + assert_eq!(macro_stringify!( + Hello, + world! + ), "Hello,\n world!"); + + assert_eq!(macro_stringify!(Hello, /*world */ !), "Hello, /*world */ !"); + assert_eq!(macro_stringify!( + Hello, + // comment + world! + ), "Hello,\n // comment\n world!"); + + assert_eq!(say_hello! { macro_stringify }, "\"Hello, world!\""); + assert_eq!(say_hello_extern! { macro_stringify }, "\"Hello, world!\""); +} diff --git a/src/test/ui/proc-macro/span-from-proc-macro.rs b/src/test/ui/proc-macro/span-from-proc-macro.rs new file mode 100644 index 000000000..ecff2d725 --- /dev/null +++ b/src/test/ui/proc-macro/span-from-proc-macro.rs @@ -0,0 +1,17 @@ +// aux-build:custom-quote.rs +// aux-build:span-from-proc-macro.rs +// compile-flags: -Z macro-backtrace + +#[macro_use] +extern crate span_from_proc_macro; + +#[error_from_attribute] //~ ERROR cannot find type `MissingType` +struct ShouldBeRemoved; + +#[derive(ErrorFromDerive)] //~ ERROR cannot find type `OtherMissingType` +struct Kept; + +fn main() { + error_from_bang!(); //~ ERROR mismatched types + other_error_from_bang!(); //~ ERROR cannot find value `my_ident` +} diff --git a/src/test/ui/proc-macro/span-from-proc-macro.stderr b/src/test/ui/proc-macro/span-from-proc-macro.stderr new file mode 100644 index 000000000..7beed505a --- /dev/null +++ b/src/test/ui/proc-macro/span-from-proc-macro.stderr @@ -0,0 +1,62 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/auxiliary/span-from-proc-macro.rs:37:20 + | +LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream { + | ----------------------------------------------------------------------------------- in this expansion of `#[error_from_attribute]` +... +LL | field: MissingType + | ^^^^^^^^^^^ not found in this scope + | + ::: $DIR/span-from-proc-macro.rs:8:1 + | +LL | #[error_from_attribute] + | ----------------------- in this procedural macro expansion + +error[E0412]: cannot find type `OtherMissingType` in this scope + --> $DIR/auxiliary/span-from-proc-macro.rs:46:21 + | +LL | pub fn error_from_derive(_input: TokenStream) -> TokenStream { + | ------------------------------------------------------------ in this expansion of `#[derive(ErrorFromDerive)]` +... +LL | Variant(OtherMissingType) + | ^^^^^^^^^^^^^^^^ not found in this scope + | + ::: $DIR/span-from-proc-macro.rs:11:10 + | +LL | #[derive(ErrorFromDerive)] + | --------------- in this derive macro expansion + +error[E0425]: cannot find value `my_ident` in this scope + --> $DIR/auxiliary/span-from-proc-macro.rs:29:9 + | +LL | pub fn other_error_from_bang(_input: TokenStream) -> TokenStream { + | ---------------------------------------------------------------- in this expansion of `other_error_from_bang!` +LL | custom_quote::custom_quote! { +LL | my_ident + | ^^^^^^^^ not found in this scope + | + ::: $DIR/span-from-proc-macro.rs:16:5 + | +LL | other_error_from_bang!(); + | ------------------------ in this macro invocation + +error[E0308]: mismatched types + --> $DIR/auxiliary/span-from-proc-macro.rs:16:36 + | +LL | let bang_error: bool = 25; + | ---- ^^ expected `bool`, found integer + | | + | expected due to this +... +LL | pub fn error_from_bang(_input: TokenStream) -> TokenStream { + | ---------------------------------------------------------- in this expansion of `error_from_bang!` + | + ::: $DIR/span-from-proc-macro.rs:15:5 + | +LL | error_from_bang!(); + | ------------------ in this macro invocation + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0412, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs new file mode 100644 index 000000000..0c7358655 --- /dev/null +++ b/src/test/ui/proc-macro/span-preservation.rs @@ -0,0 +1,57 @@ +// For each of these, we should get the appropriate type mismatch error message, +// and the function should be echoed. + +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[recollect_attr] +fn a() { + let x: usize = "hello"; //~ ERROR mismatched types +} + +#[recollect_attr] +fn b(x: Option<isize>) -> usize { + match x { + Some(x) => { return x }, //~ ERROR mismatched types + None => 10 + } +} + +#[recollect_attr] +fn c() { + struct Foo { + a: usize + } + + struct Bar { + a: usize, + b: usize + } + + let x = Foo { a: 10isize }; //~ ERROR mismatched types + let y = Foo { a: 10, b: 10isize }; //~ ERROR has no field named `b` +} + +#[recollect_attr] +extern "C" fn bar() { + 0 //~ ERROR mismatched types +} + +#[recollect_attr] +extern "C" fn baz() { + 0 //~ ERROR mismatched types +} + +#[recollect_attr] +extern "Rust" fn rust_abi() { + 0 //~ ERROR mismatched types +} + +#[recollect_attr] +extern "\x43" fn c_abi_escaped() { + 0 //~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr new file mode 100644 index 000000000..66c68be2f --- /dev/null +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -0,0 +1,72 @@ +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:11:20 + | +LL | let x: usize = "hello"; + | ----- ^^^^^^^ expected `usize`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:17:29 + | +LL | fn b(x: Option<isize>) -> usize { + | ----- expected `usize` because of return type +LL | match x { +LL | Some(x) => { return x }, + | ^ expected `usize`, found `isize` + | +help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit + | +LL | Some(x) => { return x.try_into().unwrap() }, + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:33:22 + | +LL | let x = Foo { a: 10isize }; + | ^^^^^^^ expected `usize`, found `isize` + +error[E0560]: struct `Foo` has no field named `b` + --> $DIR/span-preservation.rs:34:26 + | +LL | let y = Foo { a: 10, b: 10isize }; + | ^ `Foo` does not have this field + | + = note: available fields are: `a` + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:39:5 + | +LL | extern "C" fn bar() { + | - help: try adding a return type: `-> i32` +LL | 0 + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:44:5 + | +LL | extern "C" fn baz() { + | - help: try adding a return type: `-> i32` +LL | 0 + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:49:5 + | +LL | extern "Rust" fn rust_abi() { + | - help: try adding a return type: `-> i32` +LL | 0 + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:54:5 + | +LL | extern "\x43" fn c_abi_escaped() { + | - help: try adding a return type: `-> i32` +LL | 0 + | ^ expected `()`, found integer + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0560. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/struct-field-macro.rs b/src/test/ui/proc-macro/struct-field-macro.rs new file mode 100644 index 000000000..460f4d9f7 --- /dev/null +++ b/src/test/ui/proc-macro/struct-field-macro.rs @@ -0,0 +1,18 @@ +// run-pass + +#![allow(dead_code)] +// aux-build:derive-nothing.rs + +#[macro_use] +extern crate derive_nothing; + +macro_rules! int { + () => { i32 } +} + +#[derive(Nothing)] +struct S { + x: int!(), +} + +fn main() {} diff --git a/src/test/ui/proc-macro/subspan.rs b/src/test/ui/proc-macro/subspan.rs new file mode 100644 index 000000000..a4187f9e7 --- /dev/null +++ b/src/test/ui/proc-macro/subspan.rs @@ -0,0 +1,26 @@ +// aux-build:subspan.rs + +extern crate subspan; + +use subspan::subspan; + +// This one emits no error. +subspan!(""); + +// Exactly one 'hi'. +subspan!("hi"); //~ ERROR found 'hi's + +// Now two, back to back. +subspan!("hihi"); //~ ERROR found 'hi's + +// Now three, back to back. +subspan!("hihihi"); //~ ERROR found 'hi's + +// Now several, with spacing. +subspan!("why I hide? hi!"); //~ ERROR found 'hi's +subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's +subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's +subspan!("how are you this evening"); //~ ERROR found 'hi's +subspan!("this is highly eradic"); //~ ERROR found 'hi's + +fn main() { } diff --git a/src/test/ui/proc-macro/subspan.stderr b/src/test/ui/proc-macro/subspan.stderr new file mode 100644 index 000000000..b5dacba0e --- /dev/null +++ b/src/test/ui/proc-macro/subspan.stderr @@ -0,0 +1,106 @@ +error: found 'hi's + --> $DIR/subspan.rs:11:1 + | +LL | subspan!("hi"); + | ^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:11:11 + | +LL | subspan!("hi"); + | ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:14:1 + | +LL | subspan!("hihi"); + | ^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:14:11 + | +LL | subspan!("hihi"); + | ^^^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:17:1 + | +LL | subspan!("hihihi"); + | ^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:17:11 + | +LL | subspan!("hihihi"); + | ^^^^^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:20:1 + | +LL | subspan!("why I hide? hi!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:20:17 + | +LL | subspan!("why I hide? hi!"); + | ^^ ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:21:1 + | +LL | subspan!("hey, hi, hidy, hidy, hi hi"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:21:16 + | +LL | subspan!("hey, hi, hidy, hidy, hi hi"); + | ^^ ^^ ^^ ^^ ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:22:1 + | +LL | subspan!("this is a hi, and this is another hi"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:22:12 + | +LL | subspan!("this is a hi, and this is another hi"); + | ^^ ^^ ^^ ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:23:1 + | +LL | subspan!("how are you this evening"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:23:24 + | +LL | subspan!("how are you this evening"); + | ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:24:1 + | +LL | subspan!("this is highly eradic"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:24:12 + | +LL | subspan!("this is highly eradic"); + | ^^ ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + diff --git a/src/test/ui/proc-macro/test.rs b/src/test/ui/proc-macro/test.rs new file mode 100644 index 000000000..c96aa7317 --- /dev/null +++ b/src/test/ui/proc-macro/test.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:api/mod.rs + +//! This is for everything that *would* be a #[test] inside of libproc_macro, +//! except for the fact that proc_macro objects are not capable of existing +//! inside of an ordinary Rust test execution, only inside a macro. + +extern crate proc_macro_api_tests; + +proc_macro_api_tests::run!(); + +fn main() {} diff --git a/src/test/ui/proc-macro/three-equals.rs b/src/test/ui/proc-macro/three-equals.rs new file mode 100644 index 000000000..21b137c99 --- /dev/null +++ b/src/test/ui/proc-macro/three-equals.rs @@ -0,0 +1,25 @@ +// aux-build:three-equals.rs + +extern crate three_equals; + +use three_equals::three_equals; + +fn main() { + // This one is okay. + three_equals!(===); + + // Need exactly three equals. + three_equals!(==); //~ ERROR found 2 equal signs, need exactly 3 + + // Need exactly three equals. + three_equals!(=====); //~ ERROR expected EOF + + // Only equals accepted. + three_equals!(abc); //~ ERROR expected `=` + + // Only equals accepted. + three_equals!(!!); //~ ERROR expected `=` + + // Only three characters expected. + three_equals!(===a); //~ ERROR expected EOF +} diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr new file mode 100644 index 000000000..1ce5e02bd --- /dev/null +++ b/src/test/ui/proc-macro/three-equals.stderr @@ -0,0 +1,49 @@ +error: found 2 equal signs, need exactly 3 + --> $DIR/three-equals.rs:12:5 + | +LL | three_equals!(==); + | ^^^^^^^^^^^^^^^^^ + | + = help: input must be: `===` + = note: this error originates in the macro `three_equals` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected EOF, found `=`. + --> $DIR/three-equals.rs:15:21 + | +LL | three_equals!(=====); + | ^^ + | +note: last good input was here + --> $DIR/three-equals.rs:15:21 + | +LL | three_equals!(=====); + | ^^ + = help: input must be: `===` + +error: expected `=`, found `abc`. + --> $DIR/three-equals.rs:18:19 + | +LL | three_equals!(abc); + | ^^^ + +error: expected `=`, found `!`. + --> $DIR/three-equals.rs:21:19 + | +LL | three_equals!(!!); + | ^ + +error: expected EOF, found `a`. + --> $DIR/three-equals.rs:24:22 + | +LL | three_equals!(===a); + | ^ + | +note: last good input was here + --> $DIR/three-equals.rs:24:21 + | +LL | three_equals!(===a); + | ^ + = help: input must be: `===` + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/proc-macro/trailing-plus.rs b/src/test/ui/proc-macro/trailing-plus.rs new file mode 100644 index 000000000..4f61de47d --- /dev/null +++ b/src/test/ui/proc-macro/trailing-plus.rs @@ -0,0 +1,14 @@ +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; + +#[test_macros::print_attr] +fn foo<T>() where T: Copy + { +} + +fn main() {} diff --git a/src/test/ui/proc-macro/trailing-plus.stdout b/src/test/ui/proc-macro/trailing-plus.stdout new file mode 100644 index 000000000..b90057cd6 --- /dev/null +++ b/src/test/ui/proc-macro/trailing-plus.stdout @@ -0,0 +1,57 @@ +PRINT-ATTR INPUT (DISPLAY): fn foo < T > () where T : Copy + {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/trailing-plus.rs:11:1: 11:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/trailing-plus.rs:11:4: 11:7 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/trailing-plus.rs:11:7: 11:8 (#0), + }, + Ident { + ident: "T", + span: $DIR/trailing-plus.rs:11:8: 11:9 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/trailing-plus.rs:11:9: 11:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/trailing-plus.rs:11:10: 11:12 (#0), + }, + Ident { + ident: "where", + span: $DIR/trailing-plus.rs:11:13: 11:18 (#0), + }, + Ident { + ident: "T", + span: $DIR/trailing-plus.rs:11:19: 11:20 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/trailing-plus.rs:11:20: 11:21 (#0), + }, + Ident { + ident: "Copy", + span: $DIR/trailing-plus.rs:11:22: 11:26 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/trailing-plus.rs:11:27: 11:28 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/trailing-plus.rs:11:29: 12:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/trait-fn-args-2015.rs b/src/test/ui/proc-macro/trait-fn-args-2015.rs new file mode 100644 index 000000000..6b8df78a0 --- /dev/null +++ b/src/test/ui/proc-macro/trait-fn-args-2015.rs @@ -0,0 +1,16 @@ +// Unnamed arguments in trait functions can be passed through proc macros on 2015 edition. + +// check-pass +// aux-build:test-macros.rs + +#![allow(anonymous_parameters)] + +#[macro_use] +extern crate test_macros; + +trait Tr { + #[identity_attr] + fn method(u8); +} + +fn main() {} diff --git a/src/test/ui/proc-macro/two-crate-types-1.rs b/src/test/ui/proc-macro/two-crate-types-1.rs new file mode 100644 index 000000000..80bfd357f --- /dev/null +++ b/src/test/ui/proc-macro/two-crate-types-1.rs @@ -0,0 +1,7 @@ +// error-pattern: cannot mix `proc-macro` crate type with others + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![crate_type = "rlib"] diff --git a/src/test/ui/proc-macro/two-crate-types-1.stderr b/src/test/ui/proc-macro/two-crate-types-1.stderr new file mode 100644 index 000000000..deaba1cf2 --- /dev/null +++ b/src/test/ui/proc-macro/two-crate-types-1.stderr @@ -0,0 +1,4 @@ +error: cannot mix `proc-macro` crate type with others + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/two-crate-types-2.rs b/src/test/ui/proc-macro/two-crate-types-2.rs new file mode 100644 index 000000000..39cbf7d3b --- /dev/null +++ b/src/test/ui/proc-macro/two-crate-types-2.rs @@ -0,0 +1,3 @@ +// error-pattern: cannot mix `proc-macro` crate type with others +// compile-flags: --crate-type rlib --crate-type proc-macro +// force-host diff --git a/src/test/ui/proc-macro/two-crate-types-2.stderr b/src/test/ui/proc-macro/two-crate-types-2.stderr new file mode 100644 index 000000000..deaba1cf2 --- /dev/null +++ b/src/test/ui/proc-macro/two-crate-types-2.stderr @@ -0,0 +1,4 @@ +error: cannot mix `proc-macro` crate type with others + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/unsafe-foreign-mod.rs b/src/test/ui/proc-macro/unsafe-foreign-mod.rs new file mode 100644 index 000000000..7bdfa93c2 --- /dev/null +++ b/src/test/ui/proc-macro/unsafe-foreign-mod.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:macro-only-syntax.rs + +extern crate macro_only_syntax; + +#[macro_only_syntax::expect_unsafe_foreign_mod] +unsafe extern { + type T; +} + +#[macro_only_syntax::expect_unsafe_extern_cpp_mod] +unsafe extern "C++" {} + +fn main() {} diff --git a/src/test/ui/proc-macro/unsafe-mod.rs b/src/test/ui/proc-macro/unsafe-mod.rs new file mode 100644 index 000000000..8ff6e352c --- /dev/null +++ b/src/test/ui/proc-macro/unsafe-mod.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:macro-only-syntax.rs + +#![feature(proc_macro_hygiene)] + +extern crate macro_only_syntax; + +#[macro_only_syntax::expect_unsafe_mod] +unsafe mod m { + pub unsafe mod inner; +} + +fn main() {} diff --git a/src/test/ui/proc-macro/visibility-path.rs b/src/test/ui/proc-macro/visibility-path.rs new file mode 100644 index 000000000..a73430db2 --- /dev/null +++ b/src/test/ui/proc-macro/visibility-path.rs @@ -0,0 +1,25 @@ +// Proc macro defined with `pub(path)` doesn't ICEs due to resolving the `path` (issue #68921). + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub(self) fn outer(input: TokenStream) -> TokenStream { + //~^ ERROR functions tagged with `#[proc_macro]` must be `pub` + input +} + +mod m { + use proc_macro::*; + + #[proc_macro] + pub(super) fn inner(input: TokenStream) -> TokenStream { + //~^ ERROR functions tagged with `#[proc_macro]` must currently reside in the root + input + } +} diff --git a/src/test/ui/proc-macro/visibility-path.stderr b/src/test/ui/proc-macro/visibility-path.stderr new file mode 100644 index 000000000..1a73cc196 --- /dev/null +++ b/src/test/ui/proc-macro/visibility-path.stderr @@ -0,0 +1,14 @@ +error: functions tagged with `#[proc_macro]` must be `pub` + --> $DIR/visibility-path.rs:12:1 + | +LL | pub(self) fn outer(input: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions tagged with `#[proc_macro]` must currently reside in the root of the crate + --> $DIR/visibility-path.rs:21:5 + | +LL | pub(super) fn inner(input: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/proc-macro/weird-braces.rs b/src/test/ui/proc-macro/weird-braces.rs new file mode 100644 index 000000000..b9a7e08f9 --- /dev/null +++ b/src/test/ui/proc-macro/weird-braces.rs @@ -0,0 +1,23 @@ +// aux-build:test-macros.rs +// check-pass +// compile-flags: -Z span-debug + +#![feature(custom_inner_attributes)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; +use test_macros::{print_target_and_args}; + +struct Foo<const V: bool>; +trait Bar<const V: bool> {} + +#[print_target_and_args(first_outer)] +#[print_target_and_args(second_outer)] +impl Bar<{1 > 0}> for Foo<{true}> { + #![print_target_and_args(first_inner)] + #![print_target_and_args(second_inner)] +} + +fn main() {} diff --git a/src/test/ui/proc-macro/weird-braces.stdout b/src/test/ui/proc-macro/weird-braces.stdout new file mode 100644 index 000000000..9bf562217 --- /dev/null +++ b/src/test/ui/proc-macro/weird-braces.stdout @@ -0,0 +1,524 @@ +PRINT-ATTR_ARGS INPUT (DISPLAY): first_outer +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "first_outer", + span: $DIR/weird-braces.rs:16:25: 16:36 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second_outer)] impl Bar < { 1 > 0 } > for Foo < +{ true } > +{ + #! [print_target_and_args(first_inner)] #! + [print_target_and_args(second_inner)] +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/weird-braces.rs:17:1: 17:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:17:3: 17:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second_outer", + span: $DIR/weird-braces.rs:17:25: 17:37 (#0), + }, + ], + span: $DIR/weird-braces.rs:17:24: 17:38 (#0), + }, + ], + span: $DIR/weird-braces.rs:17:2: 17:39 (#0), + }, + Ident { + ident: "impl", + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), + }, + Ident { + ident: "for", + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:19:6: 19:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:19:8: 19:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "first_inner", + span: $DIR/weird-braces.rs:19:30: 19:41 (#0), + }, + ], + span: $DIR/weird-braces.rs:19:29: 19:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:19:7: 19:43 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second_inner", + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:29: 20:43 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:7: 20:44 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): second_outer +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_outer", + span: $DIR/weird-braces.rs:17:25: 17:37 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > +{ + #! [print_target_and_args(first_inner)] #! + [print_target_and_args(second_inner)] +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), + }, + Ident { + ident: "for", + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:19:6: 19:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:19:8: 19:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "first_inner", + span: $DIR/weird-braces.rs:19:30: 19:41 (#0), + }, + ], + span: $DIR/weird-braces.rs:19:29: 19:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:19:7: 19:43 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second_inner", + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:29: 20:43 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:7: 20:44 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): first_inner +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "first_inner", + span: $DIR/weird-braces.rs:19:30: 19:41 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > +{ #! [print_target_and_args(second_inner)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), + }, + Ident { + ident: "for", + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second_inner", + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:29: 20:43 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:7: 20:44 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): second_inner +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_inner", + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), + }, + Ident { + ident: "for", + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/weird-hygiene.rs b/src/test/ui/proc-macro/weird-hygiene.rs new file mode 100644 index 000000000..7ba3f98a7 --- /dev/null +++ b/src/test/ui/proc-macro/weird-hygiene.rs @@ -0,0 +1,46 @@ +// aux-build:weird-hygiene.rs + +#![feature(stmt_expr_attributes)] +#![feature(proc_macro_hygiene)] + +extern crate weird_hygiene; +use weird_hygiene::*; + +macro_rules! other { + ($tokens:expr) => { + macro_rules! call_it { + ($outer_ident:ident) => { + macro_rules! inner { + () => { + $outer_ident; + } + } + } + } + + #[derive(WeirdDerive)] + enum MyEnum { + Value = (stringify!($tokens + hidden_ident), 1).1 //~ ERROR cannot find + } + + inner!(); + } +} + +macro_rules! invoke_it { + ($token:expr) => { + #[recollect_attr] { + $token; + hidden_ident //~ ERROR cannot find + } + } +} + +fn main() { + // `other` and `invoke_it` are both macro_rules! macros, + // so it should be impossible for them to ever see `hidden_ident`, + // even if they invoke a proc macro. + let hidden_ident = "Hello1"; + other!(50); + invoke_it!(25); +} diff --git a/src/test/ui/proc-macro/weird-hygiene.stderr b/src/test/ui/proc-macro/weird-hygiene.stderr new file mode 100644 index 000000000..256e68e89 --- /dev/null +++ b/src/test/ui/proc-macro/weird-hygiene.stderr @@ -0,0 +1,25 @@ +error[E0425]: cannot find value `hidden_ident` in this scope + --> $DIR/weird-hygiene.rs:23:43 + | +LL | Value = (stringify!($tokens + hidden_ident), 1).1 + | ^^^^^^^^^^^^ not found in this scope +... +LL | other!(50); + | ---------- in this macro invocation + | + = note: this error originates in the macro `inner` which comes from the expansion of the macro `other` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `hidden_ident` in this scope + --> $DIR/weird-hygiene.rs:34:13 + | +LL | hidden_ident + | ^^^^^^^^^^^^ not found in this scope +... +LL | invoke_it!(25); + | -------------- in this macro invocation + | + = note: this error originates in the macro `invoke_it` (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 E0425`. |