diff options
| author | Trevor Gross <tmgross@umich.edu> | 2025-06-17 22:25:51 -0400 |
|---|---|---|
| committer | Trevor Gross <tmgross@umich.edu> | 2025-06-24 04:37:32 -0400 |
| commit | be927caf063b5da94cae8f3f697d190f83115a4f (patch) | |
| tree | 0fcb8bdfbe94e940442a6b6969fb130feb9c2022 /compiler/rustc_expand/src | |
| parent | 77ec48f5642ee1aa451d270f11f308c297f55f76 (diff) | |
| download | rust-be927caf063b5da94cae8f3f697d190f83115a4f.tar.gz rust-be927caf063b5da94cae8f3f697d190f83115a4f.zip | |
mbe: Unnest nested matches with let-else and let chains
Non-functional change to simplify control flow.
Diffstat (limited to 'compiler/rustc_expand/src')
| -rw-r--r-- | compiler/rustc_expand/src/mbe/quoted.rs | 121 |
1 files changed, 63 insertions, 58 deletions
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 0c2362f23bc..de3e949af23 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -54,66 +54,71 @@ pub(super) fn parse( // Given the parsed tree, if there is a metavar and we are expecting matchers, actually // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). let tree = parse_tree(tree, &mut iter, parsing_patterns, sess, node_id, features, edition); - match tree { - TokenTree::MetaVar(start_sp, ident) if parsing_patterns => { - // Not consuming the next token immediately, as it may not be a colon - let span = match iter.peek() { - Some(&tokenstream::TokenTree::Token( - Token { kind: token::Colon, span: colon_span }, - _, - )) => { - // Consume the colon first - iter.next(); - - // It's ok to consume the next tree no matter how, - // since if it's not a token then it will be an invalid declaration. - match iter.next() { - Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { - Some((fragment, _)) => { - let span = token.span.with_lo(start_sp.lo()); - let edition = || { - // FIXME(#85708) - once we properly decode a foreign - // crate's `SyntaxContext::root`, then we can replace - // this with just `span.edition()`. A - // `SyntaxContext::root()` from the current crate will - // have the edition of the current crate, and a - // `SyntaxContext::root()` from a foreign crate will - // have the edition of that crate (which we manually - // retrieve via the `edition` parameter). - if !span.from_expansion() { - edition - } else { - span.edition() - } - }; - let kind = NonterminalKind::from_symbol(fragment.name, edition) - .unwrap_or_else(|| { - sess.dcx().emit_err(errors::InvalidFragmentSpecifier { - span, - fragment, - help: VALID_FRAGMENT_NAMES_MSG.into(), - }); - NonterminalKind::Ident - }); - result.push(TokenTree::MetaVarDecl(span, ident, Some(kind))); - continue; - } - _ => token.span, - }, - // Invalid, return a nice source location - _ => colon_span.with_lo(start_sp.lo()), - } - } - // Whether it's none or some other tree, it doesn't belong to - // the current meta variable, returning the original span. - _ => start_sp, - }; - result.push(TokenTree::MetaVarDecl(span, ident, None)); - } + if !parsing_patterns { + // No matchers allowed, nothing to process here + result.push(tree); + continue; + } + + let TokenTree::MetaVar(start_sp, ident) = tree else { + // Not a metavariable, just return the tree + result.push(tree); + continue; + }; - // Not a metavar or no matchers allowed, so just return the tree - _ => result.push(tree), + // Push a metavariable with no fragment specifier at the given span + let mut push_empty_metavar = |span| { + result.push(TokenTree::MetaVarDecl(span, ident, None)); + }; + + // Not consuming the next token immediately, as it may not be a colon + if let Some(peek) = iter.peek() + && let tokenstream::TokenTree::Token(token, _spacing) = peek + && let Token { kind: token::Colon, span: colon_span } = token + { + // Next token is a colon; consume it + iter.next(); + + // It's ok to consume the next tree no matter how, + // since if it's not a token then it will be an invalid declaration. + let Some(tokenstream::TokenTree::Token(token, _)) = iter.next() else { + // Invalid, return a nice source location as `var:` + push_empty_metavar(colon_span.with_lo(start_sp.lo())); + continue; + }; + + let Some((fragment, _)) = token.ident() else { + // No identifier for the fragment specifier; + push_empty_metavar(token.span); + continue; + }; + + let span = token.span.with_lo(start_sp.lo()); + let edition = || { + // FIXME(#85708) - once we properly decode a foreign + // crate's `SyntaxContext::root`, then we can replace + // this with just `span.edition()`. A + // `SyntaxContext::root()` from the current crate will + // have the edition of the current crate, and a + // `SyntaxContext::root()` from a foreign crate will + // have the edition of that crate (which we manually + // retrieve via the `edition` parameter). + if !span.from_expansion() { edition } else { span.edition() } + }; + let kind = NonterminalKind::from_symbol(fragment.name, edition).unwrap_or_else(|| { + sess.dcx().emit_err(errors::InvalidFragmentSpecifier { + span, + fragment, + help: VALID_FRAGMENT_NAMES_MSG.into(), + }); + NonterminalKind::Ident + }); + result.push(TokenTree::MetaVarDecl(span, ident, Some(kind))); + } else { + // Whether it's none or some other tree, it doesn't belong to + // the current meta variable, returning the original span. + push_empty_metavar(start_sp); } } result |
