about summary refs log tree commit diff
path: root/compiler/rustc_expand/src/mbe
AgeCommit message (Collapse)AuthorLines
2025-07-13Auto merge of #143461 - folkertdev:cfg-select-builtin-macro, r=petrochenkovbors-27/+38
make `cfg_select` a builtin macro tracking issue: https://github.com/rust-lang/rust/issues/115585 This parses mostly the same as the `macro cfg_select` version, except: 1. wrapping in double brackets is no longer supported (or needed): `cfg_select {{ /* ... */ }}` is now rejected. 2. in an expression context, the rhs is no longer wrapped in a block, so that this now works: ```rust fn main() { println!(cfg_select! { unix => { "foo" } _ => { "bar" } }); } ``` 3. a single wildcard rule is now supported: `cfg_select { _ => 1 }` now works I've also added an error if none of the rules evaluate to true, and warnings for any arms that follow the `_` wildcard rule. cc `@traviscross` if I'm missing any feature that should/should not be included r? `@petrochenkov` for the macro logic details
2025-07-13make `cfg_select` a builtin macroFolkert de Vries-27/+38
2025-07-09mbe: Refactor the diagnostic for unrecognized metavariable expressionsTrevor Gross-9/+5
Change to a structural diagnostic, update the valid list, and move the valid list to a note.
2025-07-09mbe: Refactor diagnostics for invalid metavar expression syntaxTrevor Gross-15/+69
Give a more user-friendly diagnostic about the following: * Trailing tokens within braces, e.g. `${foo() extra}` * Missing parentheses, e.g. `${foo}` * Incorrect number of arguments, with a hint about correct usage.
2025-07-06mbe: Clarify comments about error handling in `compile_declarative_macro`Josh Triplett-3/+2
2025-07-06mbe: Factor out a helper to check for unexpected EOF in definitionJosh Triplett-7/+14
Will get called additional times when expanding parsing to cover attributes
2025-07-06mbe: Factor out a helper to check an LHSJosh Triplett-2/+7
This currently gets called only once, but will get called multiple times when handling attributes.
2025-07-06mbe: Simplify compile_declarative_macro by factoring out some variablesJosh Triplett-11/+4
2025-07-05mbe: Defer checks for `compile_error!` until reporting an unused macro ruleJosh Triplett-73/+51
The MBE parser checks rules at initial parse time to see if their RHS has `compile_error!` in it, and returns a list of rule indexes and LHS spans that don't map to `compile_error!`, for use in unused macro rule checking. Instead, have the unused macro rule reporting ask the macro for the rule to report, and let the macro check at that time. That avoids checking rules unless they're unused. In the process, refactor the data structure used to store macro rules, to group the LHS and RHS (and LHS span) of each rule together, and refactor the unused rule tracking to only track rule indexes. This ends up being a net simplification, and reduction in code size.
2025-07-05mbe: Simplify a match to a let-elseJosh Triplett-3/+2
2025-07-05mbe: Add a helper to parse a single `TokenTree`Josh Triplett-22/+20
The parser repeatedly invokes the `parse` function, constructing a one-entry vector, and assuming that the return value will be a one-entry vector. Add a helper for that case. This will simplify adding additional callers, and put all the logic in one place to allow potential future simplification of the one-TT case.
2025-07-05mbe: Introduce an enum for which part of a rule we're parsingJosh Triplett-17/+36
Rather than a `bool` that's `true` for the LHS and `false` for the RHS, use a self-documenting enum.
2025-07-03mbe: Gracefully handle macro rules that end after `=>`Josh Triplett-0/+9
Add a test for various cases of invalid macro definitions. Closes: https://github.com/rust-lang/rust/issues/143351
2025-07-02Rollup merge of #143070 - joshtriplett:macro-rules-parse, r=petrochenkovMatthias Krüger-206/+61
Rewrite `macro_rules!` parser to not use the MBE engine itself The `macro_rules!` parser was written to match the series of rules using the macros-by-example (MBE) engine and a hand-written equivalent of the left-hand side of a MBE macro. This was complex to read, difficult to extend, and produced confusing error messages. Because it was using the MBE engine, any parse failure would be reported as if some macro was being applied to the `macro_rules!` invocation itself; for instance, errors would talk about "macro invocation", "macro arguments", and "macro call", when they were actually about the macro *definition*. And in practice, the `macro_rules!` parser only used the MBE engine to extract the left-hand side and right-hand side of each rule as a token tree, and then parsed the rest using a separate parser. Rewrite it to parse the series of rules using a simple loop, instead. This makes it more extensible in the future, and improves error messages. For instance, omitting a semicolon between rules will result in "expected `;`" and "unexpected token", rather than the confusing "no rules expected this token in macro call". This work was greatly aided by pair programming with Vincenzo Palazzo (`@vincenzopalazzo)` and Eric Holk (`@eholk).` For review, I recommend reading the two commits separately.
2025-07-01Rollup merge of #143245 - tgross35:metavariable-expr-organization, ↵Matthias Krüger-52/+57
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 .
2025-06-30mbe: Move `MetaVarExprConcatElem` closer to where it is usedTrevor Gross-14/+14
Move this structure directly above the `parse_<expr>` functions that return it to keep top-down flow. This is a non-functional change.
2025-06-30mbe: Factor `concat` metavariable handling outTrevor Gross-40/+45
Move the `concat` implementation to a separate function so it is easier to work on. Other metavariable expressions are already split this way. This is a non-functional change.
2025-06-30mbe: Shorten `MetaVarExpr` -> `Mve` in structural diagnosticsTrevor Gross-2/+2
More diagnostic structs related to metavariable expressions will be introduced. Introduce the abbreviation "mve" which is reasonably unambiguous (`rg Mve` and `rg '(\b|_|-)mve(\b|_|-)'` return no results outside of a Thumb target feature) and use it for these diagnostic types. A new module is also created.
2025-06-26mbe: Fold calls to `check_meta_variables` into the parser loopJosh Triplett-18/+8
2025-06-26Rewrite `macro_rules!` parser to not use the MBE engine itselfJosh Triplett-188/+53
The `macro_rules!` parser was written to match the series of rules using the macros-by-example (MBE) engine and a hand-written equivalent of the left-hand side of a MBE macro. This was complex to read, difficult to extend, and produced confusing error messages. Because it was using the MBE engine, any parse failure would be reported as if some macro was being applied to the `macro_rules!` invocation itself; for instance, errors would talk about "macro invocation", "macro arguments", and "macro call", when they were actually about the macro *definition*. And in practice, the `macro_rules!` parser only used the MBE engine to extract the left-hand side and right-hand side of each rule as a token tree, and then parsed the rest using a separate parser. Rewrite it to parse the series of rules using a simple loop, instead. This makes it more extensible in the future, and improves error messages. For instance, omitting a semicolon between rules will result in "expected `;`" and "unexpected token", rather than the confusing "no rules expected this token in macro call". This work was greatly aided by pair programming with Vincenzo Palazzo and Eric Holk.
2025-06-24Rollup merge of #142657 - tgross35:nonoptional-fragment-specifiers-cleanup, ↵Matthias Krüger-132/+115
r=petrochenkov mbe: Clean up code with non-optional `NonterminalKind` Since [rust-lang/rust#128425], the fragment specifier is unconditionally required in all editions. This means `NonTerminalKind` no longer needs to be optional, as we can reject this code during the expansion of `macro_rules!` rather than handling it throughout the code. Do this cleanup here. [rust-lang/rust#128425]: https://github.com/rust-lang/rust/pull/128425
2025-06-24mbe: Use `TokenTree` as the fallback for invalid fragment specifiersTrevor Gross-2/+2
`tt` should match more, so use this for both missing and invalid fragment specifiers. Also remove one unneeded instance of `String`.
2025-06-24mbe: Clean up code with non-optional `NonterminalKind`Trevor Gross-80/+58
Since [1], the fragment specifier is unconditionally required in all editions. This means `NonTerminalKind` no longer needs to be optional, as we can reject this code during the expansion of `macro_rules!` rather than handling it throughout the code. Do this cleanup here. [1]: https://github.com/rust-lang/rust/pull/128425
2025-06-24mbe: Unnest nested matches with let-else and let chainsTrevor Gross-58/+63
Non-functional change to simplify control flow.
2025-06-19mbe: Refactor transcriptionTrevor Gross-348/+389
Introduce `MacroTcbCtx` that holds everything relevant to transcription. This allows for the following changes: * Split `transcribe_sequence` and `transcribe_metavar` out of the heavily nested `transcribe` * Split `metavar_expr_concat` out of `transcribe_metavar_expr` This is a nonfunctional change.
2025-06-19mbe: Move `transcribe_metavar_expr` directly after `transcribe`Trevor Gross-96/+96
Be more consistent with the otherwise top-down organization of this file.
2025-06-12Make `missing_fragment_specifier` an unconditional errorTrevor Gross-19/+6
This was attempted in [1] then reverted in [2] because of fallout. Recently, this was made an edition-dependent error in [3]. Make missing fragment specifiers an unconditional error again. [1]: https://github.com/rust-lang/rust/pull/75516 [2]: https://github.com/rust-lang/rust/pull/80210 [3]: https://github.com/rust-lang/rust/pull/128006
2025-05-18Remove rustc_attr_data_structures re-export from rustc_attr_parsingmejrs-1/+1
2025-04-30ast: Remove token visiting from AST visitorVadim Petrochenkov-16/+16
It's no longer necessary after the removal of nonterminal tokens in #124141.
2025-04-21Remove `token::{Open,Close}Delim`.Nicholas Nethercote-22/+20
By replacing them with `{Open,Close}{Param,Brace,Bracket,Invisible}`. PR #137902 made `ast::TokenKind` more like `lexer::TokenKind` by replacing the compound `BinOp{,Eq}(BinOpToken)` variants with fieldless variants `Plus`, `Minus`, `Star`, etc. This commit does a similar thing with delimiters. It also makes `ast::TokenKind` more similar to `parser::TokenType`. This requires a few new methods: - `TokenKind::is_{,open_,close_}delim()` replace various kinds of pattern matches. - `Delimiter::as_{open,close}_token_kind` are used to convert `Delimiter` values to `TokenKind`. Despite these additions, it's a net reduction in lines of code. This is because e.g. `token::OpenParen` is so much shorter than `token::OpenDelim(Delimiter::Parenthesis)` that many multi-line forms reduce to single line forms. And many places where the number of lines doesn't change are still easier to read, just because the names are shorter, e.g.: ``` - } else if self.token != token::CloseDelim(Delimiter::Brace) { + } else if self.token != token::CloseBrace { ```
2025-04-14Auto merge of #124141 - ↵bors-25/+20
nnethercote:rm-Nonterminal-and-TokenKind-Interpolated, r=petrochenkov Remove `Nonterminal` and `TokenKind::Interpolated` A third attempt at this; the first attempt was #96724 and the second was #114647. r? `@ghost`
2025-04-11suggest: remove redundant `$()?`around `vis` fragmentsMakai-6/+38
2025-04-02Impl `Copy` for `Token` and `TokenKind`.Nicholas Nethercote-11/+11
2025-04-02Remove `NtBlock`, `Nonterminal`, and `TokenKind::Interpolated`.Nicholas Nethercote-14/+9
`NtBlock` is the last remaining variant of `Nonterminal`, so once it is gone then `Nonterminal` can be removed as well.
2025-04-02Remove `NtExpr` and `NtLiteral`.Nicholas Nethercote-7/+28
Notes about tests: - tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs: some messages are now duplicated due to repeated parsing. - tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs: ditto. - `tests/ui/proc-macro/macro-rules-derive-cfg.rs`: the diff looks large but the only difference is the insertion of a single invisible-delimited group around a metavar. - `tests/ui/attributes/nonterminal-expansion.rs`: a slight span degradation, somehow related to the recent massive attr parsing rewrite (#135726). I couldn't work out exactly what is going wrong, but I don't think it's worth holding things up for a single slightly suboptimal error message.
2025-03-19Allow builtin macros to be used more than once.Mara Bos-2/+3
This removes E0773 "A builtin-macro was defined more than once."
2025-03-12Auto merge of #138083 - nnethercote:rm-NtItem-NtStmt, r=petrochenkovbors-1/+13
Remove `NtItem` and `NtStmt` Another piece of #124141. r? `@petrochenkov`
2025-03-12Introduce `sym::dummy` and `Ident::dummy`.Nicholas Nethercote-1/+1
The idea is to identify cases of symbols/identifiers that are not expected to be used. There isn't a perfectly sharp line between "dummy" and "not dummy", but I think it's useful nonetheless.
2025-03-07Remove `NtItem` and `NtStmt`.Nicholas Nethercote-1/+13
This involves replacing `nt_pretty_printing_compatibility_hack` with `stream_pretty_printing_compatibility_hack`. The handling of statements in `transcribe` is slightly different to other nonterminal kinds, due to the lack of `from_ast` implementation for empty statements. Notable test changes: - `tests/ui/proc-macro/expand-to-derive.rs`: the diff looks large but the only difference is the insertion of a single invisible-delimited group around a metavar.
2025-03-03Rename `ast::TokenKind::Not` as `ast::TokenKind::Bang`.Nicholas Nethercote-2/+2
For consistency with `rustc_lexer::TokenKind::Bang`, and because other `ast::TokenKind` variants generally have syntactic names instead of semantic names (e.g. `Star` and `DotDot` instead of `Mul` and `Range`).
2025-03-03Replace `ast::TokenKind::BinOp{,Eq}` and remove `BinOpToken`.Nicholas Nethercote-7/+7
`BinOpToken` is badly named, because it only covers the assignable binary ops and excludes comparisons and `&&`/`||`. Its use in `ast::TokenKind` does allow a small amount of code sharing, but it's a clumsy factoring. This commit removes `ast::TokenKind::BinOp{,Eq}`, replacing each one with 10 individual variants. This makes `ast::TokenKind` more similar to `rustc_lexer::TokenKind`, which has individual variants for all operators. Although the number of lines of code increases, the number of chars decreases due to the frequent use of shorter names like `token::Plus` instead of `token::BinOp(BinOpToken::Plus)`.
2025-02-28Remove `NtPath`.Nicholas Nethercote-0/+3
2025-02-28Remove `NtMeta`.Nicholas Nethercote-0/+8
Note: there was an existing code path involving `Interpolated` in `MetaItem::from_tokens` that was dead. This commit transfers that to the new form, but puts an `unreachable!` call inside it.
2025-02-28Remove `NtPat`.Nicholas Nethercote-4/+14
The one notable test change is `tests/ui/macros/trace_faulty_macros.rs`. This commit removes the complicated `Interpolated` handling in `expected_expression_found` that results in a longer error message. But I think the new, shorter message is actually an improvement. The original complaint was in #71039, when the error message started with "error: expected expression, found `1 + 1`". That was confusing because `1 + 1` is an expression. Other than that, the reporter said "the whole error message is not too bad if you ignore the first line". Subsequently, extra complexity and wording was added to the error message. But I don't think the extra wording actually helps all that much. In particular, it still says of the `1+1` that "this is expected to be expression". This repeats the problem from the original complaint! This commit removes the extra complexity, reverting to a simpler error message. This is primarily because the traversal is a pain without `Interpolated` tokens. Nonetheless, I think the error message is *improved*. It now starts with "expected expression, found `pat` metavariable", which is much clearer and the real problem. It also doesn't say anything specific about `1+1`, which is good, because the `1+1` isn't really relevant to the error -- it's the `$e:pat` that's important.
2025-02-24Introduce new-style attribute parsers for several attributesJana Dönszelmann-15/+5
note: compiler compiles but librustdoc and clippy don't
2025-02-22Rollup merge of #137333 - compiler-errors:edition-2024-fresh, r=NadrierilMatthias Krüger-2/+2
Use `edition = "2024"` in the compiler (redux) Most of this is binding mode changes, which I fixed by running `x.py fix`. Also adds some miscellaneous `unsafe` blocks for new unsafe standard library functions (the setenv ones), and a missing `unsafe extern` block in some enzyme codegen code, and fixes some precise capturing lifetime changes (but only when they led to errors). cc ``@ehuss`` ``@traviscross``
2025-02-22Fix binding mode problemsMichael Goulet-2/+2
2025-02-21Avoid snapshotting the parser in `parse_path_inner`.Nicholas Nethercote-2/+3
2025-02-21Remove `NtTy`.Nicholas Nethercote-0/+3
Notes about tests: - tests/ui/parser/macro/trait-object-macro-matcher.rs: the syntax error is duplicated, because it occurs now when parsing the decl macro input, and also when parsing the expanded decl macro. But this won't show up for normal users due to error de-duplication. - tests/ui/associated-consts/issue-93835.rs: similar, plus there are some additional errors about this very broken code. - The changes to metavariable descriptions in #132629 are now visible in error message for several tests.
2025-02-21Remove `NtVis`.Nicholas Nethercote-1/+34
We now use invisible delimiters for expanded `vis` fragments, instead of `Token::Interpolated`.