diff options
Diffstat (limited to 'tests/ui/macros/rfc-3086-metavar-expr')
10 files changed, 1299 insertions, 0 deletions
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs new file mode 100644 index 000000000..ab8d95a41 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs @@ -0,0 +1,271 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +fn main() { + macro_rules! one_nested_count_and_length { + ( $( [ $( $l:literal ),* ] ),* ) => { + [ + // outer-most repetition + $( + // inner-most repetition + $( + ${ignore(l)} ${index()}, ${length()}, + )* + ${count(l)}, ${index()}, ${length()}, + )* + ${count(l)}, + ] + }; + } + assert_eq!( + one_nested_count_and_length!(["foo"], ["bar", "baz"]), + [ + // # ["foo"] + + // ## inner-most repetition (first iteration) + // + // `index` is 0 because this is the first inner-most iteration. + // `length` is 1 because there is only one inner-most repetition, "foo". + 0, 1, + + // ## outer-most repetition (first iteration) + // + // `count` is 1 because of "foo", i,e, `$l` has only one repetition, + // `index` is 0 because this is the first outer-most iteration. + // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] + 1, 0, 2, + + // # ["bar", "baz"] + + // ## inner-most repetition (first iteration) + // + // `index` is 0 because this is the first inner-most iteration + // `length` is 2 because there are repetitions, "bar" and "baz" + 0, 2, + + // ## inner-most repetition (second iteration) + // + // `index` is 1 because this is the second inner-most iteration + // `length` is 2 because there are repetitions, "bar" and "baz" + 1, 2, + + // ## outer-most repetition (second iteration) + // + // `count` is 2 because of "bar" and "baz", i,e, `$l` has two repetitions, + // `index` is 1 because this is the second outer-most iteration + // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] + 2, 1, 2, + + // # last count + + // Because there are a total of 3 repetitions of `$l`, "foo", "bar" and "baz" + 3, + ] + ); + + // Based on the above explanation, the following macros should be straightforward + + // Grouped from the outer-most to the inner-most + macro_rules! three_nested_count { + ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => { + &[ + $( $( $( + &[ + ${ignore(i)} ${count(i, 0)}, + ][..], + )* )* )* + + $( $( + &[ + ${ignore(i)} ${count(i, 0)}, + ${ignore(i)} ${count(i, 1)}, + ][..], + )* )* + + $( + &[ + ${ignore(i)} ${count(i, 0)}, + ${ignore(i)} ${count(i, 1)}, + ${ignore(i)} ${count(i, 2)}, + ][..], + )* + + &[ + ${count(i, 0)}, + ${count(i, 1)}, + ${count(i, 2)}, + ${count(i, 3)}, + ][..] + ][..] + } + } + assert_eq!( + three_nested_count!( + { + [ (a b c) (d e f) ] + [ (g h) (i j k l m) ] + [ (n) ] + } + { + [ (o) (p q) (r s) ] + [ (t u v w x y z) ] + } + ), + &[ + // a b c + &[3][..], + // d e f + &[3][..], + // g h + &[2][..], + // i j k l m + &[5][..], + // n + &[1][..], + // o + &[1][..], + // p q + &[2][..], + // r s + &[2][..], + // t u v w x y z + &[7][..], + + // (a b c) (d e f) + &[2, 6][..], + // (g h) (i j k l m) + &[2, 7][..], + // (n) + &[1, 1][..], + // (o) (p q) (r s) + &[3, 5][..], + // (t u v w x y z) + &[1, 7][..], + + // [ (a b c) (d e f) ] + // [ (g h) (i j k l m) ] + // [ (n) ] + &[3, 5, 14][..], + // [ (o) (p q) (r s) ] + // [ (t u v w x y z) ] + &[2, 4, 12][..], + + // { + // [ (a b c) (d e f) ] + // [ (g h) (i j k l m) ] + // [ (n) ] + // } + // { + // [ (o) (p q) (r s) ] + // [ (t u v w x y z) ] + // } + &[2, 5, 9, 26][..] + ][..] + ); + + // Grouped from the outer-most to the inner-most + macro_rules! three_nested_length { + ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => { + &[ + $( $( $( $( + &[ + ${ignore(i)} ${length(3)}, + ${ignore(i)} ${length(2)}, + ${ignore(i)} ${length(1)}, + ${ignore(i)} ${length(0)}, + ][..], + )* )* )* )* + + $( $( $( + &[ + ${ignore(i)} ${length(2)}, + ${ignore(i)} ${length(1)}, + ${ignore(i)} ${length(0)}, + ][..], + )* )* )* + + $( $( + &[ + ${ignore(i)} ${length(1)}, + ${ignore(i)} ${length(0)}, + ][..], + )* )* + + $( + &[ + ${ignore(i)} ${length(0)}, + ][..], + )* + ][..] + } + } + assert_eq!( + three_nested_length!( + { + [ (a b c) (d e f) ] + [ (g h) (i j k l m) ] + [ (n) ] + } + { + [ (o) (p q) (r s) ] + [ (t u v w x y z) ] + } + ), + &[ + // a b c + &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], + // d e f + &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], + // g h + &[2, 3, 2, 2][..], &[2, 3, 2, 2][..], + // i j k l m + &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], + &[2, 3, 2, 5][..], + // n + &[2, 3, 1, 1][..], + // o + &[2, 2, 3, 1][..], + // p q + &[2, 2, 3, 2][..], &[2, 2, 3, 2][..], + // r s + &[2, 2, 3, 2][..], &[2, 2, 3, 2][..], + // t u v w x y z + &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], + &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], + + // (a b c) (d e f) + &[2, 3, 2][..], &[2, 3, 2][..], + // (g h) (i j k l m) + &[2, 3, 2][..], &[2, 3, 2][..], + // (n) + &[2, 3, 1][..], + // (o) (p q) (r s) + &[2, 2, 3][..], &[2, 2, 3][..], &[2, 2, 3][..], + // (t u v w x y z) + &[2, 2, 1][..], + + // [ (a b c) (d e f) ] + // [ (g h) (i j k l m) ] + // [ (n) ] + &[2, 3][..], &[2, 3][..], &[2, 3,][..], + // [ (o) (p q) (r s) ] + // [ (t u v w x y z) ] + &[2, 2][..], &[2, 2][..], + + // { + // [ (a b c) (d e f) ] + // [ (g h) (i j k l m) ] + // [ (n) ] + // } + // { + // [ (o) (p q) (r s) ] + // [ (t u v w x y z) ] + // } + &[2][..], &[2][..] + ][..] + ); + + // It is possible to say, to some degree, that count is an "amalgamation" of length (see + // each length line result and compare them with the count results) +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs b/tests/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs new file mode 100644 index 000000000..ed94c27cf --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs @@ -0,0 +1,28 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +macro_rules! nested { + ( $a:ident ) => { + macro_rules! $a { + ( $$( $b:ident ),* ) => { + $$( + macro_rules! $b { + ( $$$$( $c:ident ),* ) => { + $$$$( + fn $c() -> &'static str { stringify!($c) } + ),* + }; + } + )* + }; + } + }; +} + +fn main() { + nested!(a); + a!(b); + b!(c); + assert_eq!(c(), "c"); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs b/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs new file mode 100644 index 000000000..d05cd1b31 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs @@ -0,0 +1,148 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +/// Count the number of idents in a macro repetition. +macro_rules! count_idents { + ( $( $i:ident ),* ) => { + ${count(i)} + }; +} + +/// Count the number of idents in a 2-dimensional macro repetition. +macro_rules! count_idents_2 { + ( $( [ $( $i:ident ),* ] ),* ) => { + ${count(i)} + }; +} + +/// Mostly counts the number of OUTER-MOST repetitions +macro_rules! count_depth_limits { + ( $( { $( [ $( $outer:ident : ( $( $inner:ident )* ) )* ] )* } )* ) => { + ( + ( + ${count(inner)}, + ${count(inner, 0)}, + ${count(inner, 1)}, + ${count(inner, 2)}, + ${count(inner, 3)}, + ), + ( + ${count(outer)}, + ${count(outer, 0)}, + ${count(outer, 1)}, + ${count(outer, 2)}, + ), + ) + }; +} + +/// Produce (index, length) pairs for literals in a macro repetition. +/// The literal is not included in the output, so this macro uses the +/// `ignore` meta-variable expression to create a non-expanding +/// repetition binding. +macro_rules! enumerate_literals { + ( $( ($l:stmt) ),* ) => { + [$( ${ignore(l)} (${index()}, ${length()}) ),*] + }; +} + +/// Produce index and length tuples for literals in a 2-dimensional +/// macro repetition. +macro_rules! enumerate_literals_2 { + ( $( [ $( ($l:literal) ),* ] ),* ) => { + [ + $( + $( + ( + ${index(1)}, + ${length(1)}, + ${index(0)}, + ${length(0)}, + $l + ), + )* + )* + ] + }; +} + +/// Generate macros that count idents and then add a constant number +/// to the count. +/// +/// This macro uses dollar escaping to make it unambiguous as to which +/// macro the repetition belongs to. +macro_rules! make_count_adders { + ( $( $i:ident, $b:literal );* ) => { + $( + macro_rules! $i { + ( $$( $$j:ident ),* ) => { + $b + $${count(j)} + }; + } + )* + }; +} + +make_count_adders! { plus_one, 1; plus_five, 5 } + +/// Generate a macro that allows selection of a particular literal +/// from a sequence of inputs by their identifier. +/// +/// This macro uses dollar escaping to make it unambiguous as to which +/// macro the repetition belongs to, and to allow expansion of an +/// identifier the name of which is not known in the definition +/// of `make_picker`. +macro_rules! make_picker { + ( $m:ident => $( $i:ident ),* ; $p:ident ) => { + macro_rules! $m { + ( $( $$ $i:literal ),* ) => { + $$ $p + }; + } + }; +} + +make_picker!(first => a, b; a); + +make_picker!(second => a, b; b); + +fn main() { + assert_eq!(count_idents!(a, b, c), 3); + assert_eq!(count_idents_2!([a, b, c], [d, e], [f]), 6); + assert_eq!( + count_depth_limits! { + { + [ A: (a b c) D: (d e f) ] + [ G: (g h) I: (i j k l m) ] + [ N: (n) ] + } + { + [ O: (o) P: (p q) R: (r s) ] + [ T: (t u v w x y z) ] + } + }, + ((26, 2, 5, 9, 26), (9, 2, 5, 9)) + ); + assert_eq!(enumerate_literals![("foo"), ("bar")], [(0, 2), (1, 2)]); + assert_eq!( + enumerate_literals_2![ + [("foo"), ("bar"), ("baz")], + [("qux"), ("quux"), ("quuz"), ("xyzzy")] + ], + [ + (0, 2, 0, 3, "foo"), + (0, 2, 1, 3, "bar"), + (0, 2, 2, 3, "baz"), + + (1, 2, 0, 4, "qux"), + (1, 2, 1, 4, "quux"), + (1, 2, 2, 4, "quuz"), + (1, 2, 3, 4, "xyzzy"), + ] + ); + assert_eq!(plus_one!(a, b, c), 4); + assert_eq!(plus_five!(a, b), 7); + assert_eq!(first!(1, 2), 1); + assert_eq!(second!(1, 2), 2); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs b/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs new file mode 100644 index 000000000..b954967c4 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs @@ -0,0 +1,102 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +#[derive(Debug)] +struct Example<'a> { + _indexes: &'a [(u32, u32)], + _counts: &'a [u32], + _nested: Vec<Example<'a>>, +} + +macro_rules! example { + ( $( [ $( ( $( $x:ident )* ) )* ] )* ) => { + Example { + _indexes: &[], + _counts: &[${count(x, 0)}, ${count(x, 1)}, ${count(x, 2)}], + _nested: vec![ + $( + Example { + _indexes: &[(${index()}, ${length()})], + _counts: &[${count(x, 0)}, ${count(x, 1)}], + _nested: vec![ + $( + Example { + _indexes: &[(${index(1)}, ${length(1)}), (${index()}, ${length()})], + _counts: &[${count(x)}], + _nested: vec![ + $( + Example { + _indexes: &[ + (${index(2)}, ${length(2)}), + (${index(1)}, ${length(1)}), + (${index()}, ${length()}) + ], + _counts: &[], + _nested: vec![], + ${ignore(x)} + } + ),* + ] + } + ),* + ] + } + ),* + ] + } + }; +} + +static EXPECTED: &str = concat!( + "Example { _indexes: [], _counts: [2, 4, 13], _nested: [", + concat!( + "Example { _indexes: [(0, 2)], _counts: [3, 10], _nested: [", + concat!( + "Example { _indexes: [(0, 2), (0, 3)], _counts: [4], _nested: [", + concat!( + "Example { _indexes: [(0, 2), (0, 3), (0, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (0, 3), (1, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (0, 3), (2, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (0, 3), (3, 4)], _counts: [], _nested: [] }", + ), + "] }, ", + "Example { _indexes: [(0, 2), (1, 3)], _counts: [4], _nested: [", + concat!( + "Example { _indexes: [(0, 2), (1, 3), (0, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (1, 3), (1, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (1, 3), (2, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (1, 3), (3, 4)], _counts: [], _nested: [] }", + ), + "] }, ", + "Example { _indexes: [(0, 2), (2, 3)], _counts: [2], _nested: [", + concat!( + "Example { _indexes: [(0, 2), (2, 3), (0, 2)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (2, 3), (1, 2)], _counts: [], _nested: [] }", + ), + "] }", + ), + "] }, ", + "Example { _indexes: [(1, 2)], _counts: [1, 3], _nested: [", + concat!( + "Example { _indexes: [(1, 2), (0, 1)], _counts: [3], _nested: [", + concat!( + "Example { _indexes: [(1, 2), (0, 1), (0, 3)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(1, 2), (0, 1), (1, 3)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(1, 2), (0, 1), (2, 3)], _counts: [], _nested: [] }", + ), + "] }", + ), + "] }", + ), + "] }", +); + +fn main() { + let e = example! { + [ ( A B C D ) ( E F G H ) ( I J ) ] + [ ( K L M ) ] + }; + let debug = format!("{:?}", e); + assert_eq!(debug, EXPECTED); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs new file mode 100644 index 000000000..6a0d68bd6 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs @@ -0,0 +1,43 @@ +#![feature(macro_metavar_expr)] + +macro_rules! a { + ( $( { $( [ $( ( $( $foo:ident )* ) )* ] )* } )* ) => { + ( + ${count(foo, 0)}, + ${count(foo, 10)}, + //~^ ERROR depth parameter on meta-variable expression `count` must be less than 4 + ) + }; +} + +macro_rules! b { + ( $( { $( [ $( $foo:ident )* ] )* } )* ) => { + ( + $( $( $( + ${ignore(foo)} + ${index(0)}, + ${index(10)}, + //~^ ERROR depth parameter on meta-variable expression `index` must be less than 3 + )* )* )* + ) + }; +} + +macro_rules! c { + ( $( { $( $foo:ident )* } )* ) => { + ( + $( $( + ${ignore(foo)} + ${length(0)} + ${length(10)} + //~^ ERROR depth parameter on meta-variable expression `length` must be less than 2 + )* )* + ) + }; +} + +fn main() { + a!( { [ (a) ] [ (b c) ] } ); + b!( { [ a b ] } ); + c!({ a }); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr new file mode 100644 index 000000000..236122b64 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr @@ -0,0 +1,20 @@ +error: depth parameter on meta-variable expression `count` must be less than 4 + --> $DIR/out-of-bounds-arguments.rs:7:14 + | +LL | ${count(foo, 10)}, + | ^^^^^^^^^^^^^^^^ + +error: depth parameter on meta-variable expression `index` must be less than 3 + --> $DIR/out-of-bounds-arguments.rs:19:18 + | +LL | ${index(10)}, + | ^^^^^^^^^^^ + +error: depth parameter on meta-variable expression `length` must be less than 2 + --> $DIR/out-of-bounds-arguments.rs:32:18 + | +LL | ${length(10)} + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs new file mode 100644 index 000000000..b4fef11f1 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs @@ -0,0 +1,44 @@ +macro_rules! count { + ( $( $e:stmt ),* ) => { + ${ count(e) } + //~^ ERROR meta-variable expressions are unstable + }; +} + +macro_rules! dollar_dollar { + () => { + macro_rules! bar { + ( $$( $$any:tt )* ) => { $$( $$any )* }; + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + } + }; +} + +macro_rules! index { + ( $( $e:stmt ),* ) => { + $( ${ignore(e)} ${index()} )* + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + }; +} + +macro_rules! ignore { + ( $( $i:stmt ),* ) => {{ + 0 $( + 1 ${ignore(i)} )* + //~^ ERROR meta-variable expressions are unstable + }}; +} + +macro_rules! length { + ( $( $e:stmt ),* ) => { + $( ${ignore(e)} ${length()} )* + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + }; +} + +fn main() { +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr new file mode 100644 index 000000000..ecf598b10 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr @@ -0,0 +1,93 @@ +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:3:10 + | +LL | ${ count(e) } + | ^^^^^^^^^^^^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:16 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:20 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:39 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:43 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:22:13 + | +LL | $( ${ignore(e)} ${index()} )* + | ^^^^^^^^^^^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:22:26 + | +LL | $( ${ignore(e)} ${index()} )* + | ^^^^^^^^^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:30:19 + | +LL | 0 $( + 1 ${ignore(i)} )* + | ^^^^^^^^^^^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:37:13 + | +LL | $( ${ignore(e)} ${length()} )* + | ^^^^^^^^^^^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:37:26 + | +LL | $( ${ignore(e)} ${length()} )* + | ^^^^^^^^^^ + | + = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs new file mode 100644 index 000000000..fdf16442d --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs @@ -0,0 +1,165 @@ +#![feature(macro_metavar_expr)] + +// `curly` = Right hand side curly brackets +// `no_rhs_dollar` = No dollar sign at the right hand side meta variable "function" +// `round` = Left hand side round brackets + +macro_rules! curly__no_rhs_dollar__round { + ( $( $i:ident ),* ) => { ${ count(i) } }; +} + +macro_rules! curly__no_rhs_dollar__no_round { + ( $i:ident ) => { ${ count(i) } }; + //~^ ERROR `count` can not be placed inside the inner-most repetition +} + +macro_rules! curly__rhs_dollar__round { + ( $( $i:ident ),* ) => { ${ count($i) } }; + //~^ ERROR expected identifier, found `$` + //~| ERROR expected expression, found `$` +} + +macro_rules! curly__rhs_dollar__no_round { + ( $i:ident ) => { ${ count($i) } }; + //~^ ERROR expected identifier, found `$` + //~| ERROR expected expression, found `$` +} + +macro_rules! no_curly__no_rhs_dollar__round { + ( $( $i:ident ),* ) => { count(i) }; + //~^ ERROR cannot find function `count` in this scope + //~| ERROR cannot find value `i` in this scope +} + +macro_rules! no_curly__no_rhs_dollar__no_round { + ( $i:ident ) => { count(i) }; + //~^ ERROR cannot find function `count` in this scope + //~| ERROR cannot find value `i` in this scope +} + +macro_rules! no_curly__rhs_dollar__round { + ( $( $i:ident ),* ) => { count($i) }; + //~^ ERROR variable 'i' is still repeating at this depth +} + +macro_rules! no_curly__rhs_dollar__no_round { + ( $i:ident ) => { count($i) }; + //~^ ERROR cannot find function `count` in this scope +} + +// Other scenarios + +macro_rules! dollar_dollar_in_the_lhs { + ( $$ $a:ident ) => { + //~^ ERROR unexpected token: $ + }; +} + +macro_rules! extra_garbage_after_metavar { + ( $( $i:ident ),* ) => { + ${count() a b c} + //~^ ERROR unexpected token: a + //~| ERROR expected expression, found `$` + ${count(i a b c)} + //~^ ERROR unexpected token: a + ${count(i, 1 a b c)} + //~^ ERROR unexpected token: a + ${count(i) a b c} + //~^ ERROR unexpected token: a + + ${ignore(i) a b c} + //~^ ERROR unexpected token: a + ${ignore(i a b c)} + //~^ ERROR unexpected token: a + + ${index() a b c} + //~^ ERROR unexpected token: a + ${index(1 a b c)} + //~^ ERROR unexpected token: a + + ${index() a b c} + //~^ ERROR unexpected token: a + ${index(1 a b c)} + //~^ ERROR unexpected token: a + }; +} + +const IDX: usize = 1; +macro_rules! metavar_depth_is_not_literal { + ( $( $i:ident ),* ) => { ${ index(IDX) } }; + //~^ ERROR meta-variable expression depth must be a literal + //~| ERROR expected expression, found `$` +} + +macro_rules! metavar_in_the_lhs { + ( ${ length() } ) => { + //~^ ERROR unexpected token: { + //~| ERROR expected one of: `*`, `+`, or `?` + }; +} + +macro_rules! metavar_token_without_ident { + ( $( $i:ident ),* ) => { ${ ignore() } }; + //~^ ERROR expected identifier + //~| ERROR expected expression, found `$` +} + +macro_rules! metavar_with_literal_suffix { + ( $( $i:ident ),* ) => { ${ index(1u32) } }; + //~^ ERROR only unsuffixes integer literals are supported in meta-variable expressions + //~| ERROR expected expression, found `$` +} + +macro_rules! metavar_without_parens { + ( $( $i:ident ),* ) => { ${ count{i} } }; + //~^ ERROR meta-variable expression parameter must be wrapped in parentheses + //~| ERROR expected expression, found `$` +} + +macro_rules! open_brackets_without_tokens { + ( $( $i:ident ),* ) => { ${ {} } }; + //~^ ERROR expected expression, found `$` + //~| ERROR expected identifier +} + +macro_rules! unknown_count_ident { + ( $( $i:ident )* ) => { + ${count(foo)} + //~^ ERROR variable `foo` is not recognized in meta-variable expression + }; +} + +macro_rules! unknown_ignore_ident { + ( $( $i:ident )* ) => { + ${ignore(bar)} + //~^ ERROR variable `bar` is not recognized in meta-variable expression + }; +} + +macro_rules! unknown_metavar { + ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; + //~^ ERROR unrecognized meta-variable expression + //~| ERROR expected expression +} + +fn main() { + curly__no_rhs_dollar__round!(a, b, c); + curly__no_rhs_dollar__no_round!(a); + curly__rhs_dollar__round!(a, b, c); + curly__rhs_dollar__no_round!(a); + no_curly__no_rhs_dollar__round!(a, b, c); + no_curly__no_rhs_dollar__no_round!(a); + no_curly__rhs_dollar__round!(a, b, c); + no_curly__rhs_dollar__no_round!(a); + //~^ ERROR cannot find value `a` in this scope + + extra_garbage_after_metavar!(a); + metavar_depth_is_not_literal!(a); + metavar_token_without_ident!(a); + metavar_with_literal_suffix!(a); + metavar_without_parens!(a); + open_brackets_without_tokens!(a); + unknown_count_ident!(a); + unknown_ignore_ident!(a); + unknown_metavar!(a); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr new file mode 100644 index 000000000..a6cff95fd --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr @@ -0,0 +1,385 @@ +error: expected identifier, found `$` + --> $DIR/syntax-errors.rs:17:33 + | +LL | ( $( $i:ident ),* ) => { ${ count($i) } }; + | ^^^^^ - help: try removing `$` + +error: expected identifier, found `$` + --> $DIR/syntax-errors.rs:23:26 + | +LL | ( $i:ident ) => { ${ count($i) } }; + | ^^^^^ - help: try removing `$` + +error: unexpected token: $ + --> $DIR/syntax-errors.rs:53:8 + | +LL | ( $$ $a:ident ) => { + | ^ + +note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions + --> $DIR/syntax-errors.rs:53:8 + | +LL | ( $$ $a:ident ) => { + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:60:19 + | +LL | ${count() a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:60:19 + | +LL | ${count() a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:63:19 + | +LL | ${count(i a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:63:19 + | +LL | ${count(i a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:65:22 + | +LL | ${count(i, 1 a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:65:22 + | +LL | ${count(i, 1 a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:67:20 + | +LL | ${count(i) a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:67:20 + | +LL | ${count(i) a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:70:21 + | +LL | ${ignore(i) a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:70:21 + | +LL | ${ignore(i) a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:72:20 + | +LL | ${ignore(i a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:72:20 + | +LL | ${ignore(i a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:75:19 + | +LL | ${index() a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:75:19 + | +LL | ${index() a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:77:19 + | +LL | ${index(1 a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:77:19 + | +LL | ${index(1 a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:80:19 + | +LL | ${index() a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:80:19 + | +LL | ${index() a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:82:19 + | +LL | ${index(1 a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:82:19 + | +LL | ${index(1 a b c)} + | ^ + +error: meta-variable expression depth must be a literal + --> $DIR/syntax-errors.rs:89:33 + | +LL | ( $( $i:ident ),* ) => { ${ index(IDX) } }; + | ^^^^^ + +error: unexpected token: { + --> $DIR/syntax-errors.rs:95:8 + | +LL | ( ${ length() } ) => { + | ^^^^^^^^^^^^ + +note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions + --> $DIR/syntax-errors.rs:95:8 + | +LL | ( ${ length() } ) => { + | ^^^^^^^^^^^^ + +error: expected one of: `*`, `+`, or `?` + --> $DIR/syntax-errors.rs:95:8 + | +LL | ( ${ length() } ) => { + | ^^^^^^^^^^^^ + +error: expected identifier + --> $DIR/syntax-errors.rs:102:33 + | +LL | ( $( $i:ident ),* ) => { ${ ignore() } }; + | ^^^^^^ + +error: only unsuffixes integer literals are supported in meta-variable expressions + --> $DIR/syntax-errors.rs:108:33 + | +LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; + | ^^^^^ + +error: meta-variable expression parameter must be wrapped in parentheses + --> $DIR/syntax-errors.rs:114:33 + | +LL | ( $( $i:ident ),* ) => { ${ count{i} } }; + | ^^^^^ + +error: expected identifier + --> $DIR/syntax-errors.rs:120:31 + | +LL | ( $( $i:ident ),* ) => { ${ {} } }; + | ^^^^^^ + +error: unrecognized meta-variable expression + --> $DIR/syntax-errors.rs:140:33 + | +LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; + | ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and length + +error: `count` can not be placed inside the inner-most repetition + --> $DIR/syntax-errors.rs:12:24 + | +LL | ( $i:ident ) => { ${ count(i) } }; + | ^^^^^^^^^^^^ + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:17:30 + | +LL | ( $( $i:ident ),* ) => { ${ count($i) } }; + | ^ expected expression +... +LL | curly__rhs_dollar__round!(a, b, c); + | ---------------------------------- in this macro invocation + | + = note: this error originates in the macro `curly__rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:23:23 + | +LL | ( $i:ident ) => { ${ count($i) } }; + | ^ expected expression +... +LL | curly__rhs_dollar__no_round!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: variable 'i' is still repeating at this depth + --> $DIR/syntax-errors.rs:41:36 + | +LL | ( $( $i:ident ),* ) => { count($i) }; + | ^^ + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:60:9 + | +LL | ${count() a b c} + | ^ expected expression +... +LL | extra_garbage_after_metavar!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `extra_garbage_after_metavar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:89:30 + | +LL | ( $( $i:ident ),* ) => { ${ index(IDX) } }; + | ^ expected expression +... +LL | metavar_depth_is_not_literal!(a); + | -------------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_depth_is_not_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:102:30 + | +LL | ( $( $i:ident ),* ) => { ${ ignore() } }; + | ^ expected expression +... +LL | metavar_token_without_ident!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_token_without_ident` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:108:30 + | +LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; + | ^ expected expression +... +LL | metavar_with_literal_suffix!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_with_literal_suffix` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:114:30 + | +LL | ( $( $i:ident ),* ) => { ${ count{i} } }; + | ^ expected expression +... +LL | metavar_without_parens!(a); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_without_parens` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:120:30 + | +LL | ( $( $i:ident ),* ) => { ${ {} } }; + | ^ expected expression +... +LL | open_brackets_without_tokens!(a); + | -------------------------------- in this macro invocation + | + = note: this error originates in the macro `open_brackets_without_tokens` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: variable `foo` is not recognized in meta-variable expression + --> $DIR/syntax-errors.rs:127:17 + | +LL | ${count(foo)} + | ^^^ + +error: variable `bar` is not recognized in meta-variable expression + --> $DIR/syntax-errors.rs:134:18 + | +LL | ${ignore(bar)} + | ^^^ + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:140:30 + | +LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; + | ^ expected expression +... +LL | unknown_metavar!(a); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `i` in this scope + --> $DIR/syntax-errors.rs:29:36 + | +LL | ( $( $i:ident ),* ) => { count(i) }; + | ^ not found in this scope +... +LL | no_curly__no_rhs_dollar__round!(a, b, c); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `i` in this scope + --> $DIR/syntax-errors.rs:35:29 + | +LL | ( $i:ident ) => { count(i) }; + | ^ not found in this scope +... +LL | no_curly__no_rhs_dollar__no_round!(a); + | ------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/syntax-errors.rs:153:37 + | +LL | no_curly__rhs_dollar__no_round!(a); + | ^ not found in this scope + +error[E0425]: cannot find function `count` in this scope + --> $DIR/syntax-errors.rs:29:30 + | +LL | ( $( $i:ident ),* ) => { count(i) }; + | ^^^^^ not found in this scope +... +LL | no_curly__no_rhs_dollar__round!(a, b, c); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `count` in this scope + --> $DIR/syntax-errors.rs:35:23 + | +LL | ( $i:ident ) => { count(i) }; + | ^^^^^ not found in this scope +... +LL | no_curly__no_rhs_dollar__no_round!(a); + | ------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `count` in this scope + --> $DIR/syntax-errors.rs:46:23 + | +LL | ( $i:ident ) => { count($i) }; + | ^^^^^ not found in this scope +... +LL | no_curly__rhs_dollar__no_round!(a); + | ---------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 40 previous errors + +For more information about this error, try `rustc --explain E0425`. |