diff options
Diffstat (limited to 'compiler/rustc_expand/src')
| -rw-r--r-- | compiler/rustc_expand/src/errors.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/mbe/metavar_expr.rs | 105 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/mbe/transcribe.rs | 4 |
3 files changed, 70 insertions, 60 deletions
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index fe4d2af97a0..fdbc65aff68 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -28,14 +28,6 @@ pub(crate) struct CountRepetitionMisplaced { } #[derive(Diagnostic)] -#[diag(expand_meta_var_expr_unrecognized_var)] -pub(crate) struct MetaVarExprUnrecognizedVar { - #[primary_span] - pub span: Span, - pub key: MacroRulesNormalizedIdent, -} - -#[derive(Diagnostic)] #[diag(expand_var_still_repeating)] pub(crate) struct VarStillRepeating { #[primary_span] @@ -499,3 +491,16 @@ pub(crate) struct ProcMacroBackCompat { pub crate_name: String, pub fixed_version: String, } + +pub(crate) use metavar_exprs::*; +mod metavar_exprs { + use super::*; + + #[derive(Diagnostic)] + #[diag(expand_mve_unrecognized_var)] + pub(crate) struct MveUnrecognizedVar { + #[primary_span] + pub span: Span, + pub key: MacroRulesNormalizedIdent, + } +} diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 1ccb070f83a..ffd3548019a 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -47,46 +47,7 @@ impl MetaVarExpr { check_trailing_token(&mut iter, psess)?; let mut iter = args.iter(); let rslt = match ident.as_str() { - "concat" => { - let mut result = Vec::new(); - loop { - let is_var = try_eat_dollar(&mut iter); - let token = parse_token(&mut iter, psess, outer_span)?; - let element = if is_var { - MetaVarExprConcatElem::Var(parse_ident_from_token(psess, token)?) - } else if let TokenKind::Literal(Lit { - kind: token::LitKind::Str, - symbol, - suffix: None, - }) = token.kind - { - MetaVarExprConcatElem::Literal(symbol) - } else { - match parse_ident_from_token(psess, token) { - Err(err) => { - err.cancel(); - return Err(psess - .dcx() - .struct_span_err(token.span, UNSUPPORTED_CONCAT_ELEM_ERR)); - } - Ok(elem) => MetaVarExprConcatElem::Ident(elem), - } - }; - result.push(element); - if iter.peek().is_none() { - break; - } - if !try_eat_comma(&mut iter) { - return Err(psess.dcx().struct_span_err(outer_span, "expected comma")); - } - } - if result.len() < 2 { - return Err(psess - .dcx() - .struct_span_err(ident.span, "`concat` must have at least two elements")); - } - MetaVarExpr::Concat(result.into()) - } + "concat" => parse_concat(&mut iter, psess, outer_span, ident.span)?, "count" => parse_count(&mut iter, psess, ident.span)?, "ignore" => { eat_dollar(&mut iter, psess, ident.span)?; @@ -126,6 +87,22 @@ impl MetaVarExpr { } } +// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}` +fn check_trailing_token<'psess>( + iter: &mut TokenStreamIter<'_>, + psess: &'psess ParseSess, +) -> PResult<'psess, ()> { + if let Some(tt) = iter.next() { + let mut diag = psess + .dcx() + .struct_span_err(tt.span(), format!("unexpected token: {}", pprust::tt_to_string(tt))); + diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens"); + Err(diag) + } else { + Ok(()) + } +} + /// Indicates what is placed in a `concat` parameter. For example, literals /// (`${concat("foo", "bar")}`) or adhoc identifiers (`${concat(foo, bar)}`). #[derive(Debug, Decodable, Encodable, PartialEq)] @@ -140,20 +117,48 @@ pub(crate) enum MetaVarExprConcatElem { Var(Ident), } -// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}` -fn check_trailing_token<'psess>( +/// Parse a meta-variable `concat` expression: `concat($metavar, ident, ...)`. +fn parse_concat<'psess>( iter: &mut TokenStreamIter<'_>, psess: &'psess ParseSess, -) -> PResult<'psess, ()> { - if let Some(tt) = iter.next() { - let mut diag = psess + outer_span: Span, + expr_ident_span: Span, +) -> PResult<'psess, MetaVarExpr> { + let mut result = Vec::new(); + loop { + let is_var = try_eat_dollar(iter); + let token = parse_token(iter, psess, outer_span)?; + let element = if is_var { + MetaVarExprConcatElem::Var(parse_ident_from_token(psess, token)?) + } else if let TokenKind::Literal(Lit { kind: token::LitKind::Str, symbol, suffix: None }) = + token.kind + { + MetaVarExprConcatElem::Literal(symbol) + } else { + match parse_ident_from_token(psess, token) { + Err(err) => { + err.cancel(); + return Err(psess + .dcx() + .struct_span_err(token.span, UNSUPPORTED_CONCAT_ELEM_ERR)); + } + Ok(elem) => MetaVarExprConcatElem::Ident(elem), + } + }; + result.push(element); + if iter.peek().is_none() { + break; + } + if !try_eat_comma(iter) { + return Err(psess.dcx().struct_span_err(outer_span, "expected comma")); + } + } + if result.len() < 2 { + return Err(psess .dcx() - .struct_span_err(tt.span(), format!("unexpected token: {}", pprust::tt_to_string(tt))); - diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens"); - Err(diag) - } else { - Ok(()) + .struct_span_err(expr_ident_span, "`concat` must have at least two elements")); } + Ok(MetaVarExpr::Concat(result.into())) } /// Parse a meta-variable `count` expression: `count(ident[, depth])` diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index a8c4a9e4b1b..174844d6ad6 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -17,7 +17,7 @@ use rustc_span::{ use smallvec::{SmallVec, smallvec}; use crate::errors::{ - CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce, + CountRepetitionMisplaced, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar, NoSyntaxVarsExprRepeat, VarStillRepeating, }; use crate::mbe::macro_parser::NamedMatch; @@ -879,7 +879,7 @@ where { let span = ident.span; let key = MacroRulesNormalizedIdent::new(ident); - interp.get(&key).ok_or_else(|| dcx.create_err(MetaVarExprUnrecognizedVar { span, key })) + interp.get(&key).ok_or_else(|| dcx.create_err(MveUnrecognizedVar { span, key })) } /// Used by meta-variable expressions when an user input is out of the actual declared bounds. For |
