提交 f8a29bd9 编写于 作者: B bors

Auto merge of #94875 - matthiaskrgr:rollup-tq1li2d, r=matthiaskrgr

Rollup of 3 pull requests

Successful merges:

 - #94150 (rustdoc-json: Include GenericParamDefKind::Type::synthetic in JSON)
 - #94833 ([2/2] Implement macro meta-variable expression)
 - #94863 (Remove redundant slicing of whole ranges in `bootstrap`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
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(())
}
......@@ -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())
}
......
......@@ -340,9 +340,10 @@ fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
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) }
......
......@@ -9,7 +9,7 @@
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<String> },
Type { bounds: Vec<GenericBound>, default: Option<Type> },
Const { ty: Type, default: Option<String> },
Lifetime {
outlives: Vec<String>,
},
Type {
bounds: Vec<GenericBound>,
default: Option<Type>,
/// 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: Trait>(_: 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<String>,
},
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
......
// ignore-tidy-linelength
#![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<T: Wham>(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) {}
// 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)
}
......@@ -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);
}
// 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);
}
#![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 } );
}
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
......@@ -10,6 +10,7 @@
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 @@
//~| 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);
}
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`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册