about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaio <c410.f3r@gmail.com>2022-03-11 17:48:51 -0300
committerCaio <c410.f3r@gmail.com>2022-03-11 17:48:51 -0300
commitd0eca08bc4acbccd5125d245788979cc933bdf0f (patch)
tree3103d1a8da266a5bcda4b67d69e74928976a10e5
parent8756ed20b28d87d63378f08790b82d69490e6eb6 (diff)
downloadrust-d0eca08bc4acbccd5125d245788979cc933bdf0f.tar.gz
rust-d0eca08bc4acbccd5125d245788979cc933bdf0f.zip
Implement macro meta-variable expression
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs157
-rw-r--r--src/test/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs271
-rw-r--r--src/test/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs146
-rw-r--r--src/test/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs102
-rw-r--r--src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs44
-rw-r--r--src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr20
-rw-r--r--src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs25
-rw-r--r--src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr164
8 files changed, 836 insertions, 93 deletions
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index b8d83947541..387d5895e24 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -1,15 +1,15 @@
 use crate::base::ExtCtxt;
-use crate::mbe;
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
-
+use crate::mbe::{self, MetaVarExpr};
 use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_ast::token::{self, NtTT, Token};
+use rustc_ast::token::{self, NtTT, Token, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{pluralize, PResult};
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
 use rustc_span::hygiene::{LocalExpnId, Transparency};
-use rustc_span::symbol::MacroRulesNormalizedIdent;
+use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
 use rustc_span::Span;
 
 use smallvec::{smallvec, SmallVec};
@@ -411,13 +411,150 @@ fn lockstep_iter_size(
     }
 }
 
+/// Used solely by the `count` meta-variable expression, counts the outer-most repetitions at a
+/// given optional nested depth.
+///
+/// For example, a macro parameter of `$( { $( $foo:ident ),* } )*` called with `{ a, b } { c }`:
+///
+/// * `[ $( ${count(foo)} ),* ]` will return [2, 1] with a, b = 2 and c = 1
+/// * `[ $( ${count(foo, 0)} ),* ]` will be the same as `[ $( ${count(foo)} ),* ]`
+/// * `[ $( ${count(foo, 1)} ),* ]` will return an error because `${count(foo, 1)}` is
+///   declared inside a single repetition and the index `1` implies two nested repetitions.
+fn count_repetitions<'a>(
+    cx: &ExtCtxt<'a>,
+    depth_opt: Option<usize>,
+    mut matched: &NamedMatch,
+    repeats: &[(usize, usize)],
+    sp: &DelimSpan,
+) -> PResult<'a, usize> {
+    // Recursively count the number of matches in `matched` at given depth
+    // (or at the top-level of `matched` if no depth is given).
+    fn count<'a>(
+        cx: &ExtCtxt<'a>,
+        declared_lhs_depth: usize,
+        depth_opt: Option<usize>,
+        matched: &NamedMatch,
+        sp: &DelimSpan,
+    ) -> PResult<'a, usize> {
+        match matched {
+            MatchedNonterminal(_) => {
+                if declared_lhs_depth == 0 {
+                    return Err(cx.struct_span_err(
+                        sp.entire(),
+                        "`count` can not be placed inside the inner-most repetition",
+                    ));
+                }
+                match depth_opt {
+                    None => Ok(1),
+                    Some(_) => Err(out_of_bounds_err(cx, declared_lhs_depth, sp.entire(), "count")),
+                }
+            }
+            MatchedSeq(ref named_matches) => {
+                let new_declared_lhs_depth = declared_lhs_depth + 1;
+                match depth_opt {
+                    None => named_matches
+                        .iter()
+                        .map(|elem| count(cx, new_declared_lhs_depth, None, elem, sp))
+                        .sum(),
+                    Some(0) => Ok(named_matches.len()),
+                    Some(depth) => named_matches
+                        .iter()
+                        .map(|elem| count(cx, new_declared_lhs_depth, Some(depth - 1), elem, sp))
+                        .sum(),
+                }
+            }
+        }
+    }
+    // `repeats` records all of the nested levels at which we are currently
+    // matching meta-variables. The meta-var-expr `count($x)` only counts
+    // matches that occur in this "subtree" of the `NamedMatch` where we
+    // are currently transcribing, so we need to descend to that subtree
+    // before we start counting. `matched` contains the various levels of the
+    // tree as we descend, and its final value is the subtree we are currently at.
+    for &(idx, _) in repeats {
+        if let MatchedSeq(ref ads) = matched {
+            matched = &ads[idx];
+        }
+    }
+    count(cx, 0, depth_opt, matched, sp)
+}
+
+/// Returns a `NamedMatch` item declared on the RHS given an arbitrary [Ident]
+fn matched_from_ident<'ctx, 'interp, 'rslt>(
+    cx: &ExtCtxt<'ctx>,
+    ident: Ident,
+    interp: &'interp FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
+) -> PResult<'ctx, &'rslt NamedMatch>
+where
+    'interp: 'rslt,
+{
+    let span = ident.span;
+    let key = MacroRulesNormalizedIdent::new(ident);
+    interp.get(&key).ok_or_else(|| {
+        cx.struct_span_err(
+            span,
+            &format!("variable `{}` is not recognized in meta-variable expression", key),
+        )
+    })
+}
+
+/// Used by meta-variable expressions when an user input is out of the actual declared bounds. For
+/// example, index(999999) in an repetition of only three elements.
+fn out_of_bounds_err<'a>(
+    cx: &ExtCtxt<'a>,
+    max: usize,
+    span: Span,
+    ty: &str,
+) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+    cx.struct_span_err(span, &format!("{ty} depth must be less than {max}"))
+}
+
 fn transcribe_metavar_expr<'a>(
-    _cx: &ExtCtxt<'a>,
-    _expr: mbe::MetaVarExpr,
-    _interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
-    _repeats: &[(usize, usize)],
-    _result: &mut Vec<TreeAndSpacing>,
-    _sp: &DelimSpan,
+    cx: &ExtCtxt<'a>,
+    expr: MetaVarExpr,
+    interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
+    repeats: &[(usize, usize)],
+    result: &mut Vec<TreeAndSpacing>,
+    sp: &DelimSpan,
 ) -> PResult<'a, ()> {
+    match expr {
+        MetaVarExpr::Count(original_ident, depth_opt) => {
+            let matched = matched_from_ident(cx, original_ident, interp)?;
+            let count = count_repetitions(cx, depth_opt, matched, &repeats, sp)?;
+            let tt = TokenTree::token(
+                TokenKind::lit(token::Integer, sym::integer(count), None),
+                sp.entire(),
+            );
+            result.push(tt.into());
+        }
+        MetaVarExpr::Ignore(original_ident) => {
+            // Used to ensure that `original_ident` is present in the LHS
+            let _ = matched_from_ident(cx, original_ident, interp)?;
+        }
+        MetaVarExpr::Index(depth) => match repeats.iter().nth_back(depth) {
+            Some((index, _)) => {
+                result.push(
+                    TokenTree::token(
+                        TokenKind::lit(token::Integer, sym::integer(*index), None),
+                        sp.entire(),
+                    )
+                    .into(),
+                );
+            }
+            None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "index")),
+        },
+        MetaVarExpr::Length(depth) => match repeats.iter().nth_back(depth) {
+            Some((_, length)) => {
+                result.push(
+                    TokenTree::token(
+                        TokenKind::lit(token::Integer, sym::integer(*length), None),
+                        sp.entire(),
+                    )
+                    .into(),
+                );
+            }
+            None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "length")),
+        },
+    }
     Ok(())
 }
diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs b/src/test/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs
new file mode 100644
index 00000000000..ab8d95a41d0
--- /dev/null
+++ b/src/test/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/src/test/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs b/src/test/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs
index 6434ecc7e09..d05cd1b31bc 100644
--- a/src/test/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs
@@ -2,13 +2,147 @@
 
 #![feature(macro_metavar_expr)]
 
-macro_rules! ignore {
-    ( $( $i:ident ),* ) => {{
-        let array: [i32; 0] = [$( ${ignore(i)} )*];
-        array
-    }};
+/// 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!(ignore!(a, b, c), []);
+    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/src/test/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs b/src/test/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs
new file mode 100644
index 00000000000..b954967c4fe
--- /dev/null
+++ b/src/test/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/src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs b/src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs
new file mode 100644
index 00000000000..d81c8628bab
--- /dev/null
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs
@@ -0,0 +1,44 @@
+#![feature(macro_metavar_expr)]
+
+macro_rules! a {
+    ( $( { $( [ $( ( $( $foo:ident )* ) )* ] )* } )* ) => {
+        (
+            ${count(foo, 0)},
+            ${count(foo, 10)},
+            //~^ ERROR count depth must be less than 4
+        )
+    };
+}
+
+macro_rules! b {
+    ( $( { $( [ $( $foo:ident )* ] )* } )* ) => {
+        (
+            $( $( $(
+                ${ignore(foo)}
+                ${index(0)},
+                ${index(10)},
+                //~^ ERROR index depth must be less than 3
+            )* )* )*
+        )
+    };
+}
+
+macro_rules! c {
+    ( $( { $( $foo:ident )* } )* ) => {
+        (
+            $( $(
+                ${ignore(foo)}
+                ${length(0)}
+                ${length(10)}
+                //~^ ERROR length depth must be less than 2
+            )* )*
+        )
+    };
+}
+
+
+fn main() {
+    a!( { [ (a) ] [ (b c) ] } );
+    b!( { [ a b ] } );
+    c!( { a } );
+}
diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr b/src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr
new file mode 100644
index 00000000000..7474c03c0f9
--- /dev/null
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr
@@ -0,0 +1,20 @@
+error: count depth must be less than 4
+  --> $DIR/out-of-bounds-arguments.rs:7:14
+   |
+LL |             ${count(foo, 10)},
+   |              ^^^^^^^^^^^^^^^^
+
+error: index depth must be less than 3
+  --> $DIR/out-of-bounds-arguments.rs:19:18
+   |
+LL |                 ${index(10)},
+   |                  ^^^^^^^^^^^
+
+error: length depth 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/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs
index ea73fd0813c..fdf16442d2a 100644
--- a/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs
@@ -10,6 +10,7 @@ macro_rules! curly__no_rhs_dollar__round {
 
 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 {
@@ -121,6 +122,20 @@ macro_rules! open_brackets_without_tokens {
     //~| 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
@@ -139,10 +154,12 @@ fn main() {
     //~^ ERROR cannot find value `a` in this scope
 
     extra_garbage_after_metavar!(a);
-    unknown_metavar!(a);
-    metavar_without_parens!(a);
-    metavar_token_without_ident!(a);
     metavar_depth_is_not_literal!(a);
+    metavar_token_without_ident!(a);
     metavar_with_literal_suffix!(a);
-    open_brackets_without_tokens!(a)
+    metavar_without_parens!(a);
+    open_brackets_without_tokens!(a);
+    unknown_count_ident!(a);
+    unknown_ignore_ident!(a);
+    unknown_metavar!(a);
 }
diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
index dc8b7a668c4..0188938a30e 100644
--- a/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
@@ -1,203 +1,209 @@
 error: expected identifier, found `$`
-  --> $DIR/syntax-errors.rs:16:33
+  --> $DIR/syntax-errors.rs:17:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ count($i) } };
    |                                 ^^^^^ - help: try removing `$`
 
 error: expected identifier, found `$`
-  --> $DIR/syntax-errors.rs:22:26
+  --> $DIR/syntax-errors.rs:23:26
    |
 LL |     ( $i:ident ) => { ${ count($i) } };
    |                          ^^^^^ - help: try removing `$`
 
 error: unexpected token: $
-  --> $DIR/syntax-errors.rs:52:8
+  --> $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:52:8
+  --> $DIR/syntax-errors.rs:53:8
    |
 LL |     ( $$ $a:ident ) => {
    |        ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:59:19
+  --> $DIR/syntax-errors.rs:60:19
    |
 LL |         ${count() a b c}
    |                   ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:59:19
+  --> $DIR/syntax-errors.rs:60:19
    |
 LL |         ${count() a b c}
    |                   ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:62:19
+  --> $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:62:19
+  --> $DIR/syntax-errors.rs:63:19
    |
 LL |         ${count(i a b c)}
    |                   ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:64:22
+  --> $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:64:22
+  --> $DIR/syntax-errors.rs:65:22
    |
 LL |         ${count(i, 1 a b c)}
    |                      ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:66:20
+  --> $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:66:20
+  --> $DIR/syntax-errors.rs:67:20
    |
 LL |         ${count(i) a b c}
    |                    ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:69:21
+  --> $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:69:21
+  --> $DIR/syntax-errors.rs:70:21
    |
 LL |         ${ignore(i) a b c}
    |                     ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:71:20
+  --> $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:71:20
+  --> $DIR/syntax-errors.rs:72:20
    |
 LL |         ${ignore(i a b c)}
    |                    ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:74:19
+  --> $DIR/syntax-errors.rs:75:19
    |
 LL |         ${index() a b c}
    |                   ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:74:19
+  --> $DIR/syntax-errors.rs:75:19
    |
 LL |         ${index() a b c}
    |                   ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:76:19
+  --> $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:76:19
+  --> $DIR/syntax-errors.rs:77:19
    |
 LL |         ${index(1 a b c)}
    |                   ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:79:19
+  --> $DIR/syntax-errors.rs:80:19
    |
 LL |         ${index() a b c}
    |                   ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:79:19
+  --> $DIR/syntax-errors.rs:80:19
    |
 LL |         ${index() a b c}
    |                   ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:81:19
+  --> $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:81:19
+  --> $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:88:33
+  --> $DIR/syntax-errors.rs:89:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ index(IDX) } };
    |                                 ^^^^^
 
 error: unexpected token: {
-  --> $DIR/syntax-errors.rs:94:8
+  --> $DIR/syntax-errors.rs:95:8
    |
 LL |     ( ${ length() } ) => {
    |        ^^^^^^^^^^^^
 
 note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions
-  --> $DIR/syntax-errors.rs:94:8
+  --> $DIR/syntax-errors.rs:95:8
    |
 LL |     ( ${ length() } ) => {
    |        ^^^^^^^^^^^^
 
 error: expected one of: `*`, `+`, or `?`
-  --> $DIR/syntax-errors.rs:94:8
+  --> $DIR/syntax-errors.rs:95:8
    |
 LL |     ( ${ length() } ) => {
    |        ^^^^^^^^^^^^
 
 error: expected identifier
-  --> $DIR/syntax-errors.rs:101:33
+  --> $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:107:33
+  --> $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:113:33
+  --> $DIR/syntax-errors.rs:114:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ count{i} } };
    |                                 ^^^^^
 
 error: expected identifier
-  --> $DIR/syntax-errors.rs:119:31
+  --> $DIR/syntax-errors.rs:120:31
    |
 LL |     ( $( $i:ident ),* ) => { ${ {} } };
    |                               ^^^^^^
 
 error: unrecognized meta-variable expression
-  --> $DIR/syntax-errors.rs:125:33
+  --> $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:16:30
+  --> $DIR/syntax-errors.rs:17:30
    |
 LL |     ( $( $i:ident ),* ) => { ${ count($i) } };
    |                              ^ expected expression
@@ -208,7 +214,7 @@ LL |     curly__rhs_dollar__round!(a, b, c);
    = 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:22:23
+  --> $DIR/syntax-errors.rs:23:23
    |
 LL |     ( $i:ident ) => { ${ count($i) } };
    |                       ^ expected expression
@@ -219,13 +225,13 @@ LL |     curly__rhs_dollar__no_round!(a);
    = 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:40:36
+  --> $DIR/syntax-errors.rs:41:36
    |
 LL |     ( $( $i:ident ),* ) => { count($i) };
    |                                    ^^
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:59:9
+  --> $DIR/syntax-errors.rs:60:9
    |
 LL |         ${count() a b c}
    |         ^ expected expression
@@ -236,29 +242,18 @@ LL |     extra_garbage_after_metavar!(a);
    = 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:125:30
+  --> $DIR/syntax-errors.rs:89: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: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:113:30
-   |
-LL |     ( $( $i:ident ),* ) => { ${ count{i} } };
+LL |     ( $( $i:ident ),* ) => { ${ index(IDX) } };
    |                              ^ expected expression
 ...
-LL |     metavar_without_parens!(a);
-   |     -------------------------- in this macro invocation
+LL |     metavar_depth_is_not_literal!(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)
+   = 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:101:30
+  --> $DIR/syntax-errors.rs:102:30
    |
 LL |     ( $( $i:ident ),* ) => { ${ ignore() } };
    |                              ^ expected expression
@@ -269,40 +264,63 @@ LL |     metavar_token_without_ident!(a);
    = 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:88:30
+  --> $DIR/syntax-errors.rs:108:30
    |
-LL |     ( $( $i:ident ),* ) => { ${ index(IDX) } };
+LL |     ( $( $i:ident ),* ) => { ${ index(1u32) } };
    |                              ^ expected expression
 ...
-LL |     metavar_depth_is_not_literal!(a);
-   |     -------------------------------- in this macro invocation
+LL |     metavar_with_literal_suffix!(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)
+   = 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:107:30
+  --> $DIR/syntax-errors.rs:114:30
    |
-LL |     ( $( $i:ident ),* ) => { ${ index(1u32) } };
+LL |     ( $( $i:ident ),* ) => { ${ count{i} } };
    |                              ^ expected expression
 ...
-LL |     metavar_with_literal_suffix!(a);
-   |     ------------------------------- in this macro invocation
+LL |     metavar_without_parens!(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)
+   = 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:119:30
+  --> $DIR/syntax-errors.rs:120:30
    |
 LL |     ( $( $i:ident ),* ) => { ${ {} } };
    |                              ^ expected expression
 ...
-LL |     open_brackets_without_tokens!(a)
+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 function `count` in this scope
-  --> $DIR/syntax-errors.rs:28:30
+  --> $DIR/syntax-errors.rs:29:30
    |
 LL |     ( $( $i:ident ),* ) => { count(i) };
    |                              ^^^^^ not found in this scope
@@ -313,7 +331,7 @@ LL |     no_curly__no_rhs_dollar__round!(a, b, c);
    = 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:28:36
+  --> $DIR/syntax-errors.rs:29:36
    |
 LL |     ( $( $i:ident ),* ) => { count(i) };
    |                                    ^ not found in this scope
@@ -324,7 +342,7 @@ LL |     no_curly__no_rhs_dollar__round!(a, b, c);
    = 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:34:23
+  --> $DIR/syntax-errors.rs:35:23
    |
 LL |     ( $i:ident ) => { count(i) };
    |                       ^^^^^ not found in this scope
@@ -335,7 +353,7 @@ LL |     no_curly__no_rhs_dollar__no_round!(a);
    = 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 `i` in this scope
-  --> $DIR/syntax-errors.rs:34:29
+  --> $DIR/syntax-errors.rs:35:29
    |
 LL |     ( $i:ident ) => { count(i) };
    |                             ^ not found in this scope
@@ -346,7 +364,7 @@ LL |     no_curly__no_rhs_dollar__no_round!(a);
    = 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:45:23
+  --> $DIR/syntax-errors.rs:46:23
    |
 LL |     ( $i:ident ) => { count($i) };
    |                       ^^^^^ not found in this scope
@@ -357,11 +375,11 @@ LL |     no_curly__rhs_dollar__no_round!(a);
    = 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[E0425]: cannot find value `a` in this scope
-  --> $DIR/syntax-errors.rs:138:37
+  --> $DIR/syntax-errors.rs:153:37
    |
 LL |     no_curly__rhs_dollar__no_round!(a);
    |                                     ^ not found in this scope
 
-error: aborting due to 37 previous errors
+error: aborting due to 40 previous errors
 
 For more information about this error, try `rustc --explain E0425`.