about summary refs log tree commit diff
path: root/compiler/rustc_expand/src
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-07-01 04:25:36 +0200
committerGitHub <noreply@github.com>2025-07-01 04:25:36 +0200
commitcfe1942a3f1a98ea733b544559bd4845e41d5797 (patch)
treed5503c6f0ad2ff03ab758d510e5f2f4981e0ab18 /compiler/rustc_expand/src
parente2ea213874477e0874af598eecdb730ef2a52b32 (diff)
parenta1a066999b9fbfc10e93931d9a552bf87dc32e4d (diff)
downloadrust-cfe1942a3f1a98ea733b544559bd4845e41d5797.tar.gz
rust-cfe1942a3f1a98ea733b544559bd4845e41d5797.zip
Rollup merge of #143245 - tgross35:metavariable-expr-organization, r=petrochenkov
mbe: Add tests and restructure metavariable expressions

Add tests that show better diagnostics, and factor `concat` handling to a separate function. Each commit message has further details.

This performs the nonfunctional perparation for further changes such as https://github.com/rust-lang/rust/pull/142950 and https://github.com/rust-lang/rust/pull/142975 .
Diffstat (limited to 'compiler/rustc_expand/src')
-rw-r--r--compiler/rustc_expand/src/errors.rs21
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs105
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs4
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