From aa763fcf421e627455aa1de16df1292c8e1bcb9d Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sat, 19 Feb 2022 09:50:35 +0100 Subject: [PATCH 1/4] rustdoc-json: Include GenericParamDefKind::Type::synthetic in JSON The rustdoc JSON for ``` pub fn f(_: impl Clone) {} ``` will effectively be ``` pub fn f(_: impl Clone) ``` where a synthetic generic parameter called `impl Clone` with generic trait bound `Clone` is added to the function declaration. The generated HTML filters out these generic parameters by doing `self.params.iter().filter(|p| !p.is_synthetic_type_param())`, because the synthetic generic parameter is not of interest to regular users. For the same reason, we should expose whether or not a generic parameter is synthetic or not also in the rustdoc JSON, so that rustdoc JSON clients can also have the option to hide synthetic generic parameters. --- src/librustdoc/json/conversions.rs | 3 +- src/rustdoc-json-types/lib.rs | 40 ++++++++++++++++++++++++--- src/test/rustdoc-json/fns/generics.rs | 5 ++++ 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 src/test/rustdoc-json/fns/generics.rs diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4358dc8980f2f..7ffcfada5c079 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -340,9 +340,10 @@ impl FromWithTcx for GenericParamDefKind { Lifetime { outlives } => GenericParamDefKind::Lifetime { outlives: outlives.into_iter().map(|lt| lt.0.to_string()).collect(), }, - Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type { + Type { did: _, bounds, default, synthetic } => GenericParamDefKind::Type { bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(), default: default.map(|x| (*x).into_tcx(tcx)), + synthetic, }, Const { did: _, ty, default } => { GenericParamDefKind::Const { ty: (*ty).into_tcx(tcx), default: default.map(|x| *x) } diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 40b0de448293a..7df880a4ed807 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 12; +pub const FORMAT_VERSION: u32 = 13; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -346,9 +346,41 @@ pub struct GenericParamDef { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] pub enum GenericParamDefKind { - Lifetime { outlives: Vec }, - Type { bounds: Vec, default: Option }, - Const { ty: Type, default: Option }, + Lifetime { + outlives: Vec, + }, + Type { + bounds: Vec, + default: Option, + /// This is normally `false`, which means that this generic parameter is + /// declared in the Rust source text. + /// + /// If it is `true`, this generic parameter has been introduced by the + /// compiler behind the scenes. + /// + /// # Example + /// + /// Consider + /// + /// ```ignore (pseudo-rust) + /// pub fn f(_: impl Trait) {} + /// ``` + /// + /// The compiler will transform this behind the scenes to + /// + /// ```ignore (pseudo-rust) + /// pub fn f(_: impl Trait) {} + /// ``` + /// + /// In this example, the generic parameter named `impl Trait` (and which + /// is bound by `Trait`) is synthetic, because it was not originally in + /// the Rust source text. + synthetic: bool, + }, + Const { + ty: Type, + default: Option, + }, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] diff --git a/src/test/rustdoc-json/fns/generics.rs b/src/test/rustdoc-json/fns/generics.rs new file mode 100644 index 0000000000000..f80c380337bfe --- /dev/null +++ b/src/test/rustdoc-json/fns/generics.rs @@ -0,0 +1,5 @@ +// @has generics.json "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false +pub fn one_generic_param_fn(_: T) {} + +// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true +pub fn one_synthetic_generic_param_fn(_: impl Clone) {} From a424f42e97f2d1696f51a4bb71f4d305dedeb847 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Fri, 25 Feb 2022 20:34:00 +0100 Subject: [PATCH 2/4] rustdoc-json: Make the `fns/generics.rs` test much more robust --- src/test/rustdoc-json/fns/generics.rs | 29 +++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/test/rustdoc-json/fns/generics.rs b/src/test/rustdoc-json/fns/generics.rs index f80c380337bfe..e777fabaa52a7 100644 --- a/src/test/rustdoc-json/fns/generics.rs +++ b/src/test/rustdoc-json/fns/generics.rs @@ -1,5 +1,26 @@ -// @has generics.json "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false -pub fn one_generic_param_fn(_: T) {} +// ignore-tidy-linelength -// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true -pub fn one_synthetic_generic_param_fn(_: impl Clone) {} +#![feature(no_core)] +#![no_core] + +// @set wham_id = generics.json "$.index[*][?(@.name=='Wham')].id" +pub trait Wham {} + +// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.where_predicates" [] +// @count - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1 +// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"' +// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false +// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id +// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]' +pub fn one_generic_param_fn(w: T) {} + +// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.where_predicates" [] +// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1 +// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"' +// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true +// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id +// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1 +// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"' +// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"' +// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $wham_id +pub fn one_synthetic_generic_param_fn(w: impl Wham) {} From df9797b7918fdfffcae2681fb636bf621cad2fc7 Mon Sep 17 00:00:00 2001 From: pierwill Date: Fri, 11 Mar 2022 13:51:48 -0600 Subject: [PATCH 3/4] Remove redundant slicing of whole ranges in `bootstrap` --- src/bootstrap/setup.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index e1235829b3aef..aff2b6c3cbfdb 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -161,9 +161,9 @@ fn rustup_installed() -> bool { } fn stage_dir_exists(stage_path: &str) -> bool { - match fs::create_dir(&stage_path[..]) { + match fs::create_dir(&stage_path) { Ok(_) => true, - Err(_) => Path::new(&stage_path[..]).exists(), + Err(_) => Path::new(&stage_path).exists(), } } @@ -179,7 +179,7 @@ fn attempt_toolchain_link(stage_path: &str) { return; } - if try_link_toolchain(&stage_path[..]) { + if try_link_toolchain(&stage_path) { println!( "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain" ); @@ -188,7 +188,7 @@ fn attempt_toolchain_link(stage_path: &str) { println!( "To manually link stage 1 build to `stage1` toolchain, run:\n `rustup toolchain link stage1 {}`", - &stage_path[..] + &stage_path ); } } @@ -222,7 +222,7 @@ fn toolchain_is_linked() -> bool { fn try_link_toolchain(stage_path: &str) -> bool { Command::new("rustup") .stdout(std::process::Stdio::null()) - .args(&["toolchain", "link", "stage1", &stage_path[..]]) + .args(&["toolchain", "link", "stage1", &stage_path]) .output() .map_or(false, |output| output.status.success()) } From d0eca08bc4acbccd5125d245788979cc933bdf0f Mon Sep 17 00:00:00 2001 From: Caio Date: Fri, 11 Mar 2022 17:48:51 -0300 Subject: [PATCH 4/4] Implement macro meta-variable expression --- compiler/rustc_expand/src/mbe/transcribe.rs | 157 +++++++++- .../count-and-length-are-distinct.rs | 271 ++++++++++++++++++ .../feature-gate-macro_metavar_expr.rs | 146 +++++++++- .../rfc-3086-metavar-expr/macro-expansion.rs | 102 +++++++ .../out-of-bounds-arguments.rs | 44 +++ .../out-of-bounds-arguments.stderr | 20 ++ .../rfc-3086-metavar-expr/syntax-errors.rs | 25 +- .../syntax-errors.stderr | 164 ++++++----- 8 files changed, 836 insertions(+), 93 deletions(-) create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index b8d8394754134..387d5895e24d7 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, + 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, + 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, +) -> 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, - _repeats: &[(usize, usize)], - _result: &mut Vec, - _sp: &DelimSpan, + cx: &ExtCtxt<'a>, + expr: MetaVarExpr, + interp: &FxHashMap, + repeats: &[(usize, usize)], + result: &mut Vec, + 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 0000000000000..ab8d95a41d0d7 --- /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 6434ecc7e092d..d05cd1b31bc12 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 0000000000000..b954967c4fe5a --- /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>, +} + +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 0000000000000..d81c8628bab26 --- /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 0000000000000..7474c03c0f98b --- /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 ea73fd0813c5b..fdf16442d2aa5 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 dc8b7a668c4ee..0188938a30e8d 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`.