From c586fe40f1d1b136604250e7c0bd5d1e8bc41f5f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 5 Jan 2024 17:25:31 +0300 Subject: [PATCH] macro_rules: Add more tests for using `tt` in addition to `ident` Generally, `tt` and `ident` should behave identically, modulo the latter accepting only a subset of token trees. --- .../anon-params-edition-hygiene.rs | 5 +-- .../anon-params-edition-hygiene.stderr | 23 +++++++++++++ .../auxiliary/anon-params-edition-hygiene.rs | 13 +++++-- .../auxiliary/edition-kw-macro-2015.rs | 5 +++ .../auxiliary/edition-kw-macro-2018.rs | 5 +++ .../edition-keywords-2015-2015-parsing.rs | 2 ++ .../ui/editions/edition-keywords-2015-2015.rs | 2 ++ .../edition-keywords-2015-2018-parsing.rs | 2 ++ .../ui/editions/edition-keywords-2015-2018.rs | 2 ++ .../edition-keywords-2018-2015-parsing.rs | 4 ++- .../edition-keywords-2018-2015-parsing.stderr | 14 +++++--- .../ui/editions/edition-keywords-2018-2015.rs | 2 ++ .../edition-keywords-2018-2018-parsing.rs | 15 +++++++- .../edition-keywords-2018-2018-parsing.stderr | 34 ++++++++++++++----- .../ui/editions/edition-keywords-2018-2018.rs | 2 ++ tests/ui/lint/wide_pointer_comparisons.rs | 9 +++++ tests/ui/lint/wide_pointer_comparisons.stderr | 17 ++++++++-- .../method-on-ambiguous-numeric-type.rs | 7 ++++ .../method-on-ambiguous-numeric-type.stderr | 23 +++++++++---- 19 files changed, 159 insertions(+), 27 deletions(-) create mode 100644 tests/ui/anon-params/anon-params-edition-hygiene.stderr diff --git a/tests/ui/anon-params/anon-params-edition-hygiene.rs b/tests/ui/anon-params/anon-params-edition-hygiene.rs index 6936205f8b9..0b69081d4ed 100644 --- a/tests/ui/anon-params/anon-params-edition-hygiene.rs +++ b/tests/ui/anon-params/anon-params-edition-hygiene.rs @@ -1,4 +1,3 @@ -// check-pass // edition:2018 // aux-build:anon-params-edition-hygiene.rs @@ -8,6 +7,8 @@ #[macro_use] extern crate anon_params_edition_hygiene; -generate_trait_2015!(u8); +generate_trait_2015_ident!(u8); +// FIXME: Edition hygiene doesn't work correctly with `tt`s in this case. +generate_trait_2015_tt!(u8); //~ ERROR expected one of `:`, `@`, or `|`, found `)` fn main() {} diff --git a/tests/ui/anon-params/anon-params-edition-hygiene.stderr b/tests/ui/anon-params/anon-params-edition-hygiene.stderr new file mode 100644 index 00000000000..373d7c6aebb --- /dev/null +++ b/tests/ui/anon-params/anon-params-edition-hygiene.stderr @@ -0,0 +1,23 @@ +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/anon-params-edition-hygiene.rs:12:1 + | +LL | generate_trait_2015_tt!(u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) + = note: this error originates in the macro `generate_trait_2015_tt` (in Nightly builds, run with -Z macro-backtrace for more info) +help: if this is a `self` type, give it a parameter name + | +LL | generate_trait_2015_tt!(self: u8); + | +++++ +help: if this is a parameter name, give it a type + | +LL | generate_trait_2015_tt!(u8: TypeName); + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | generate_trait_2015_tt!(_: u8); + | ++ + +error: aborting due to 1 previous error + diff --git a/tests/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs b/tests/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs index aa4221becc2..28365655293 100644 --- a/tests/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs +++ b/tests/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs @@ -1,9 +1,18 @@ // edition:2015 #[macro_export] -macro_rules! generate_trait_2015 { +macro_rules! generate_trait_2015_ident { ($Type: ident) => { - trait Trait { + trait Trait1 { + fn method($Type) {} + } + }; +} + +#[macro_export] +macro_rules! generate_trait_2015_tt { + ($Type: tt) => { + trait Trait2 { fn method($Type) {} } }; diff --git a/tests/ui/editions/auxiliary/edition-kw-macro-2015.rs b/tests/ui/editions/auxiliary/edition-kw-macro-2015.rs index 7cfd128f2bf..a4a2b156e13 100644 --- a/tests/ui/editions/auxiliary/edition-kw-macro-2015.rs +++ b/tests/ui/editions/auxiliary/edition-kw-macro-2015.rs @@ -26,3 +26,8 @@ macro_rules! consumes_async_raw { macro_rules! passes_ident { ($i: ident) => ($i) } + +#[macro_export] +macro_rules! passes_tt { + ($i: tt) => ($i) +} diff --git a/tests/ui/editions/auxiliary/edition-kw-macro-2018.rs b/tests/ui/editions/auxiliary/edition-kw-macro-2018.rs index d07c0218db3..02db38103d2 100644 --- a/tests/ui/editions/auxiliary/edition-kw-macro-2018.rs +++ b/tests/ui/editions/auxiliary/edition-kw-macro-2018.rs @@ -26,3 +26,8 @@ macro_rules! consumes_async_raw { macro_rules! passes_ident { ($i: ident) => ($i) } + +#[macro_export] +macro_rules! passes_tt { + ($i: tt) => ($i) +} diff --git a/tests/ui/editions/edition-keywords-2015-2015-parsing.rs b/tests/ui/editions/edition-keywords-2015-2015-parsing.rs index d1752a7ec71..3574bc81515 100644 --- a/tests/ui/editions/edition-keywords-2015-2015-parsing.rs +++ b/tests/ui/editions/edition-keywords-2015-2015-parsing.rs @@ -19,6 +19,8 @@ pub fn check_async() { if passes_ident!(async) == 1 {} // OK if passes_ident!(r#async) == 1 {} // OK + if passes_tt!(async) == 1 {} // OK + if passes_tt!(r#async) == 1 {} // OK module::async(); // OK module::r#async(); // OK } diff --git a/tests/ui/editions/edition-keywords-2015-2015.rs b/tests/ui/editions/edition-keywords-2015-2015.rs index 943d203b806..77a2cb2e6de 100644 --- a/tests/ui/editions/edition-keywords-2015-2015.rs +++ b/tests/ui/editions/edition-keywords-2015-2015.rs @@ -20,6 +20,8 @@ pub fn check_async() { if passes_ident!(async) == 1 {} // OK if passes_ident!(r#async) == 1 {} // OK + if passes_tt!(async) == 1 {} // OK + if passes_tt!(r#async) == 1 {} // OK one_async::async(); // OK one_async::r#async(); // OK two_async::async(); // OK diff --git a/tests/ui/editions/edition-keywords-2015-2018-parsing.rs b/tests/ui/editions/edition-keywords-2015-2018-parsing.rs index 44455f43856..49f8562a6b1 100644 --- a/tests/ui/editions/edition-keywords-2015-2018-parsing.rs +++ b/tests/ui/editions/edition-keywords-2015-2018-parsing.rs @@ -19,6 +19,8 @@ pub fn check_async() { if passes_ident!(async) == 1 {} // OK if passes_ident!(r#async) == 1 {} // OK + if passes_tt!(async) == 1 {} // OK + if passes_tt!(r#async) == 1 {} // OK module::async(); // OK module::r#async(); // OK } diff --git a/tests/ui/editions/edition-keywords-2015-2018.rs b/tests/ui/editions/edition-keywords-2015-2018.rs index 8c3397c951d..a431a06bd10 100644 --- a/tests/ui/editions/edition-keywords-2015-2018.rs +++ b/tests/ui/editions/edition-keywords-2015-2018.rs @@ -20,6 +20,8 @@ pub fn check_async() { if passes_ident!(async) == 1 {} // OK if passes_ident!(r#async) == 1 {} // OK + if passes_tt!(async) == 1 {} // OK + if passes_tt!(r#async) == 1 {} // OK // one_async::async(); // ERROR, unresolved name // one_async::r#async(); // ERROR, unresolved name two_async::async(); // OK diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs index d5ed9fb9a28..8472430361f 100644 --- a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs +++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs @@ -21,8 +21,10 @@ pub fn check_async() { r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` r#async = consumes_async_raw!(r#async); // OK - if passes_ident!(async) == 1 {} + if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved if passes_ident!(r#async) == 1 {} // OK + if passes_tt!(async) == 1 {} //~ ERROR macro expansion ends with an incomplete expression + if passes_tt!(r#async) == 1 {} // OK module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr index 1a4a94e9733..42db75f6659 100644 --- a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -10,7 +10,7 @@ LL | let mut r#async = 1; | ++ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:26:13 + --> $DIR/edition-keywords-2018-2015-parsing.rs:28:13 | LL | module::async(); | ^^^^^ expected identifier, found keyword @@ -52,17 +52,23 @@ LL | ($i: ident) => ($i) | ::: $DIR/edition-keywords-2018-2015-parsing.rs:24:8 | -LL | if passes_ident!(async) == 1 {} +LL | if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved | -------------------- in this macro invocation +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` + --> $DIR/edition-keywords-2018-2015-parsing.rs:26:24 + | +LL | if passes_tt!(async) == 1 {} + | ^ expected one of `move`, `|`, or `||` + error[E0308]: mismatched types - --> $DIR/edition-keywords-2018-2015-parsing.rs:29:33 + --> $DIR/edition-keywords-2018-2015-parsing.rs:31:33 | LL | let _recovery_witness: () = 0; | -- ^ expected `()`, found integer | | | expected due to this -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/editions/edition-keywords-2018-2015.rs b/tests/ui/editions/edition-keywords-2018-2015.rs index 2cb2dfb18a0..4a02f867172 100644 --- a/tests/ui/editions/edition-keywords-2018-2015.rs +++ b/tests/ui/editions/edition-keywords-2018-2015.rs @@ -18,6 +18,8 @@ pub fn check_async() { // if passes_ident!(async) == 1 {} // ERROR, reserved if passes_ident!(r#async) == 1 {} // OK + // if passes_tt!(async) == 1 {} // ERROR, reserved + if passes_tt!(r#async) == 1 {} // OK // one_async::async(); // ERROR, reserved one_async::r#async(); // OK // two_async::async(); // ERROR, reserved diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs index 044ab249f2c..c0d8927d059 100644 --- a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs +++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs @@ -12,6 +12,13 @@ mod module { pub fn r#async() {} } +macro_rules! local_passes_ident { + ($i: ident) => ($i) //~ ERROR macro expansion ends with an incomplete expression +} +macro_rules! local_passes_tt { + ($i: tt) => ($i) //~ ERROR macro expansion ends with an incomplete expression +} + pub fn check_async() { let mut async = 1; //~ ERROR expected identifier, found keyword `async` let mut r#async = 1; // OK @@ -21,8 +28,14 @@ pub fn check_async() { r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` r#async = consumes_async_raw!(r#async); // OK - if passes_ident!(async) == 1 {} + if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved if passes_ident!(r#async) == 1 {} // OK + if passes_tt!(async) == 1 {} //~ ERROR macro expansion ends with an incomplete expression + if passes_tt!(r#async) == 1 {} // OK + if local_passes_ident!(async) == 1 {} // Error reported above in the macro + if local_passes_ident!(r#async) == 1 {} // OK + if local_passes_tt!(async) == 1 {} // Error reported above in the macro + if local_passes_tt!(r#async) == 1 {} // OK module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr index 19eb7ac9823..6f08cff433b 100644 --- a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:16:13 + --> $DIR/edition-keywords-2018-2018-parsing.rs:23:13 | LL | let mut async = 1; | ^^^^^ expected identifier, found keyword @@ -10,7 +10,7 @@ LL | let mut r#async = 1; | ++ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:26:13 + --> $DIR/edition-keywords-2018-2018-parsing.rs:39:13 | LL | module::async(); | ^^^^^ expected identifier, found keyword @@ -21,7 +21,7 @@ LL | module::r#async(); | ++ error: no rules expected the token `r#async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:20:31 + --> $DIR/edition-keywords-2018-2018-parsing.rs:27:31 | LL | r#async = consumes_async!(r#async); | ^^^^^^^ no rules expected this token in macro call @@ -33,7 +33,7 @@ LL | (async) => (1) | ^^^^^ error: no rules expected the token `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:21:35 + --> $DIR/edition-keywords-2018-2018-parsing.rs:28:35 | LL | r#async = consumes_async_raw!(async); | ^^^^^ no rules expected this token in macro call @@ -50,19 +50,37 @@ error: macro expansion ends with an incomplete expression: expected one of `move LL | ($i: ident) => ($i) | ^ expected one of `move`, `|`, or `||` | - ::: $DIR/edition-keywords-2018-2018-parsing.rs:24:8 + ::: $DIR/edition-keywords-2018-2018-parsing.rs:31:8 | -LL | if passes_ident!(async) == 1 {} +LL | if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved | -------------------- in this macro invocation +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` + --> $DIR/edition-keywords-2018-2018-parsing.rs:33:24 + | +LL | if passes_tt!(async) == 1 {} + | ^ expected one of `move`, `|`, or `||` + +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` + --> $DIR/edition-keywords-2018-2018-parsing.rs:16:23 + | +LL | ($i: ident) => ($i) + | ^ expected one of `move`, `|`, or `||` + +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` + --> $DIR/edition-keywords-2018-2018-parsing.rs:19:20 + | +LL | ($i: tt) => ($i) + | ^ expected one of `move`, `|`, or `||` + error[E0308]: mismatched types - --> $DIR/edition-keywords-2018-2018-parsing.rs:29:33 + --> $DIR/edition-keywords-2018-2018-parsing.rs:42:33 | LL | let _recovery_witness: () = 0; | -- ^ expected `()`, found integer | | | expected due to this -error: aborting due to 6 previous errors +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/editions/edition-keywords-2018-2018.rs b/tests/ui/editions/edition-keywords-2018-2018.rs index 5043440aa16..e7294326137 100644 --- a/tests/ui/editions/edition-keywords-2018-2018.rs +++ b/tests/ui/editions/edition-keywords-2018-2018.rs @@ -18,6 +18,8 @@ pub fn check_async() { // if passes_ident!(async) == 1 {} // ERROR, reserved if passes_ident!(r#async) == 1 {} // OK + // if passes_tt!(async) == 1 {} // ERROR, reserved + if passes_tt!(r#async) == 1 {} // OK // one_async::async(); // ERROR, reserved // one_async::r#async(); // ERROR, unresolved name // two_async::async(); // ERROR, reserved diff --git a/tests/ui/lint/wide_pointer_comparisons.rs b/tests/ui/lint/wide_pointer_comparisons.rs index 8334575cf52..961b998c956 100644 --- a/tests/ui/lint/wide_pointer_comparisons.rs +++ b/tests/ui/lint/wide_pointer_comparisons.rs @@ -107,6 +107,15 @@ fn main() { //~^ WARN ambiguous wide pointer comparison } + { + macro_rules! cmp { + ($a:tt, $b:tt) => { $a == $b } + //~^ WARN ambiguous wide pointer comparison + } + + cmp!(a, b); + } + { macro_rules! cmp { ($a:ident, $b:ident) => { $a == $b } diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr index 926b8775902..349ff467d0f 100644 --- a/tests/ui/lint/wide_pointer_comparisons.stderr +++ b/tests/ui/lint/wide_pointer_comparisons.stderr @@ -421,7 +421,18 @@ LL | std::ptr::eq(*a, *b) | ~~~~~~~~~~~~~ ~ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected - --> $DIR/wide_pointer_comparisons.rs:112:39 + --> $DIR/wide_pointer_comparisons.rs:112:33 + | +LL | ($a:tt, $b:tt) => { $a == $b } + | ^^^^^^^^ + | +help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses + | +LL | ($a:tt, $b:tt) => { std::ptr::addr_eq($a, $b) } + | ++++++++++++++++++ ~ + + +warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected + --> $DIR/wide_pointer_comparisons.rs:121:39 | LL | ($a:ident, $b:ident) => { $a == $b } | ^^^^^^^^ @@ -436,7 +447,7 @@ LL | ($a:ident, $b:ident) => { std::ptr::addr_eq($a, $b) } | ++++++++++++++++++ ~ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected - --> $DIR/wide_pointer_comparisons.rs:122:37 + --> $DIR/wide_pointer_comparisons.rs:131:37 | LL | ($a:expr, $b:expr) => { $a == $b } | ^^ @@ -448,5 +459,5 @@ LL | cmp!(&a, &b); = help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 37 warnings emitted +warning: 38 warnings emitted diff --git a/tests/ui/methods/method-on-ambiguous-numeric-type.rs b/tests/ui/methods/method-on-ambiguous-numeric-type.rs index 82f47438d50..f42b72e9f9c 100644 --- a/tests/ui/methods/method-on-ambiguous-numeric-type.rs +++ b/tests/ui/methods/method-on-ambiguous-numeric-type.rs @@ -5,6 +5,9 @@ macro_rules! local_mac { ($ident:ident) => { let $ident = 42; } } +macro_rules! local_mac_tt { + ($tt:tt) => { let $tt = 42; } +} fn main() { let x = 2.0.neg(); @@ -23,6 +26,10 @@ fn main() { local_mac!(local_bar); local_bar.pow(2); //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` + + local_mac_tt!(local_bar_tt); + local_bar_tt.pow(2); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` } fn qux() { diff --git a/tests/ui/methods/method-on-ambiguous-numeric-type.stderr b/tests/ui/methods/method-on-ambiguous-numeric-type.stderr index 91733411637..060595e1d40 100644 --- a/tests/ui/methods/method-on-ambiguous-numeric-type.stderr +++ b/tests/ui/methods/method-on-ambiguous-numeric-type.stderr @@ -1,5 +1,5 @@ error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` - --> $DIR/method-on-ambiguous-numeric-type.rs:10:17 + --> $DIR/method-on-ambiguous-numeric-type.rs:13:17 | LL | let x = 2.0.neg(); | ^^^ @@ -10,7 +10,7 @@ LL | let x = 2.0_f32.neg(); | ~~~~~~~ error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` - --> $DIR/method-on-ambiguous-numeric-type.rs:14:15 + --> $DIR/method-on-ambiguous-numeric-type.rs:17:15 | LL | let x = y.neg(); | ^^^ @@ -21,7 +21,7 @@ LL | let y: f32 = 2.0; | +++++ error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` - --> $DIR/method-on-ambiguous-numeric-type.rs:19:26 + --> $DIR/method-on-ambiguous-numeric-type.rs:22:26 | LL | for i in 0..100 { | - you must specify a type for this binding, like `i32` @@ -29,7 +29,7 @@ LL | println!("{}", i.pow(2)); | ^^^ error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` - --> $DIR/method-on-ambiguous-numeric-type.rs:24:15 + --> $DIR/method-on-ambiguous-numeric-type.rs:27:15 | LL | local_bar.pow(2); | ^^^ @@ -40,7 +40,18 @@ LL | ($ident:ident) => { let $ident: i32 = 42; } | +++++ error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` - --> $DIR/method-on-ambiguous-numeric-type.rs:30:9 + --> $DIR/method-on-ambiguous-numeric-type.rs:31:18 + | +LL | local_bar_tt.pow(2); + | ^^^ + | +help: you must specify a type for this binding, like `i32` + | +LL | ($tt:tt) => { let $tt: i32 = 42; } + | +++++ + +error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` + --> $DIR/method-on-ambiguous-numeric-type.rs:37:9 | LL | bar.pow(2); | ^^^ @@ -51,6 +62,6 @@ help: you must specify a type for this binding, like `i32` LL | ($ident:ident) => { let $ident: i32 = 42; } | +++++ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0689`.