about summary refs log tree commit diff
path: root/compiler/rustc_expand/src/expand.rs
AgeCommit message (Collapse)AuthorLines
2025-10-01mbe: `expand_invoc`: Add comment about not needing to check safety of ↵Josh Triplett-0/+3
`LegacyAttr` here `LegacyAttr` is only used for builtin attributes, and builtin attributes have their safety checked by `check_attribute_safety`, so we don't need to check `unsafety` here.
2025-10-01mbe: Support `unsafe` attribute rulesJosh Triplett-1/+5
2025-09-22Switch `dummy_bang` from `LegacyBang` to `Bang`Josh Triplett-1/+1
2025-09-14Move more early buffered lints to dyn lint diagnostics (4/N)León Orell Valerian Liehr-2/+1
2025-09-14Move more early buffered lints to dyn lint diagnostics (2/N)León Orell Valerian Liehr-1/+1
2025-09-08fixup limit handling codeJana Dönszelmann-1/+3
2025-08-24Warn on macro calls for attributes that had this behaviour previouslyJonathan Brouwer-6/+8
2025-08-22Auto merge of #144689 - JonathanBrouwer:share_parse_path, r=jdonszelmannbors-6/+16
Rewrite the new attribute argument parser Fixes https://github.com/rust-lang/rust/issues/143940 This rewrites the parser, should improve performance and maintainability. This can be reviewed commit by commit
2025-08-22Use the new attribute parser throughout the codebaseJonathan Brouwer-5/+16
2025-08-22Move validate_attr to `rustc_attr_parsing`Jonathan Brouwer-2/+1
2025-08-22Auto merge of #145410 - cuviper:expand-stack, r=lqdbors-1/+2
rustc_expand: ensure stack in `InvocationCollector::visit_expr` In Fedora, when we built rustc with PGO on ppc64le, we started failing the test `issue-74564-if-expr-stack-overflow.rs`. This could also be reproduced on other arches by setting a smaller `RUST_MIN_STACK`, so it's probably just unlucky that ppc64le PGO created a large stack frame somewhere in this recursion path. Adding an `ensure_sufficient_stack` solves the stack overflow. Historically, that test and its fix were added in rust-lang/rust#74708, which was also an `ensure_sufficient_stack` in this area of code at the time. However, the refactor in rust-lang/rust#92573 basically left that to the general `MutVisitor`, and then rust-lang/rust#142240 removed even that ensure call. It may be luck that our tier-1 tested targets did not regress the original issue across those refactors.
2025-08-21Rollup merge of #145590 - nnethercote:ModKind-Inline, r=petrochenkovJacob Pratt-5/+6
Prevent impossible combinations in `ast::ModKind`. `ModKind::Loaded` has an `inline` field and a `had_parse_error` field. If the `inline` field is `Inline::Yes` then `had_parse_error` must be `Ok(())`. This commit moves the `had_parse_error` field into the `Inline::No` variant. This makes it impossible to create the nonsensical combination of `inline == Inline::Yes` and `had_parse_error = Err(_)`. r? ```@Urgau```
2025-08-19Prevent impossible combinations in `ast::ModKind`.Nicholas Nethercote-5/+6
`ModKind::Loaded` has an `inline` field and a `had_parse_error` field. If the `inline` field is `Inline::Yes` then `had_parse_error` must be `Ok(())`. This commit moves the `had_parse_error` field into the `Inline::No` variant. This makes it impossible to create the nonsensical combination of `inline == Inline::Yes` and `had_parse_error = Err(_)`.
2025-08-14rustc_expand: ensure stack in `InvocationCollector::visit_expr`Josh Stone-1/+2
In Fedora, when we built rustc with PGO on ppc64le, we started failing the test `issue-74564-if-expr-stack-overflow.rs`. This could also be reproduced on other arches by setting a smaller `RUST_MIN_STACK`, so it's probably just unlucky that ppc64le PGO created a large stack frame somewhere in this recursion path. Adding an `ensure_sufficient_stack` solves the stack overflow. Historically, that test and its fix were added in rust-lang/rust#74708, which was also an `ensure_sufficient_stack` in this area of code at the time. However, the refactor in rust-lang/rust#92573 basically left that to the general `MutVisitor`, and then rust-lang/rust#142240 removed even that ensure call. It may be luck that our tier-1 tested targets did not regress the original issue across those refactors.
2025-08-14mbe: Handle applying `macro_rules` derivesJosh Triplett-0/+31
Add infrastructure to apply a derive macro to arguments, consuming and returning a `TokenTree` only. Handle `SyntaxExtensionKind::MacroRules` when expanding a derive, if the macro's kinds support derive. Add tests covering various cases of `macro_rules` derives. Note that due to a pre-existing FIXME in `expand.rs`, derives are re-queued and some errors get emitted twice. Duplicate diagnostic suppression makes them not visible, but the FIXME should still get fixed.
2025-08-13Rollup merge of #145153 - joshtriplett:macro-kinds-plural, r=petrochenkovGuillaume Gomez-14/+13
Handle macros with multiple kinds, and improve errors (I recommend reviewing this commit-by-commit.) Switch to a bitflags `MacroKinds` to support macros with more than one kind Review everything that uses `MacroKind`, and switch anything that could refer to more than one kind to use `MacroKinds`. Add a new `SyntaxExtensionKind::MacroRules` for `macro_rules!` macros, using the concrete `MacroRulesMacroExpander` type, and have it track which kinds it can handle. Eliminate the separate optional `attr_ext`, now that a `SyntaxExtension` can handle multiple macro kinds. This also avoids the need to downcast when calling methods on `MacroRulesMacroExpander`, such as `get_unused_rule`. Integrate macro kind checking into name resolution's `sub_namespace_match`, so that we only find a macro if it's the right type, and eliminate the special-case hack for attributes. This allows detecting and report macro kind mismatches early, and more precisely, improving various error messages. In particular, this eliminates the case in `failed_to_match_macro` to check for a function-like invocation of a macro with no function-like rules. Instead, macro kind mismatches now result in an unresolved macro, and we detect this case in `unresolved_macro_suggestions`, which now carefully distinguishes between a kind mismatch and other errors. This also handles cases of forward-referenced attributes and cyclic attributes. ---- In this PR, I've minimally fixed up `rustdoc` so that it compiles and passes tests. This is just the minimal necessary fixes to handle the switch to `MacroKinds`, and it only works for macros that don't actually have multiple kinds. This will panic (with a `todo!`) if it encounters a macro with multiple kinds. rustdoc needs further fixes to handle macros with multiple kinds, and to handle attributes and derive macros that aren't proc macros. I'd appreciate some help from a rustdoc expert on that. ---- r? ````````@petrochenkov````````
2025-08-13Rollup merge of #145274 - compiler-errors:unused-must-use, r=fmeaseJakub Beránek-0/+1
Remove unused `#[must_use]` Self-explanatory Fixes https://github.com/rust-lang/rust/issues/145257
2025-08-12Remove unused must_useMichael Goulet-0/+1
2025-08-12Switch to a bitflags `MacroKinds` to support macros with more than one kindJosh Triplett-14/+13
Review everything that uses `MacroKind`, and switch anything that could refer to more than one kind to use `MacroKinds`. Add a new `SyntaxExtensionKind::MacroRules` for `macro_rules!` macros, using the concrete `MacroRulesMacroExpander` type, and have it track which kinds it can handle. Eliminate the separate optional `attr_ext`, now that a `SyntaxExtension` can handle multiple macro kinds. This also avoids the need to downcast when calling methods on `MacroRulesMacroExpander`, such as `get_unused_rule`. Integrate macro kind checking into name resolution's `sub_namespace_match`, so that we only find a macro if it's the right type, and eliminate the special-case hack for attributes.
2025-08-09remove `P`Deadbeef-62/+60
2025-08-01tiny cleanupEsteban Küber-4/+2
2025-08-01remove recursive search for itemsEsteban Küber-33/+15
2025-08-01Limit how deep we visit items to find cfg'd out namesEsteban Küber-3/+12
2025-08-01Detect more `cfg`d out items in resolution errorsEsteban Küber-14/+24
Use a visitor to collect *all* items (including those nested) that were stripped behind a `cfg` condition. ``` error[E0425]: cannot find function `f` in this scope --> $DIR/nested-cfg-attrs.rs:4:13 | LL | fn main() { f() } | ^ not found in this scope | note: found an item that was configured out --> $DIR/nested-cfg-attrs.rs:2:4 | LL | fn f() {} | ^ note: the item is gated here --> $DIR/nested-cfg-attrs.rs:1:35 | LL | #[cfg_attr(all(), cfg_attr(all(), cfg(FALSE)))] | ^^^^^^^^^^ ```
2025-07-25Stop compilation if macro expansion failedGuillaume Gomez-3/+3
2025-07-15Fix ice for feature-gated cfg attributes applied to the crateJonathan Brouwer-2/+2
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
2025-07-15Define attribute parser & config evaluatorJonathan Brouwer-18/+20
2025-06-25Don't give APITs names with macro expansion placeholder fragments in itMichael Goulet-0/+10
2025-06-22Auto merge of #142706 - fee1-dead-contrib:push-zsznlqyrzsqo, r=oli-obkbors-6/+6
completely deduplicate `Visitor` and `MutVisitor` r? oli-obk This closes rust-lang/rust#127615. ### Discussion > * Give every `MutVisitor::visit_*` method a corresponding `flat_map_*` method. Not every AST node exists in a location where they can be mapped to multiple instances of themselves. Not every AST node exists in a location where they can be removed from existence (e.g. `filter_map_expr`). I don't think this is doable. > * Give every `MutVisitor::visit_*` method a corresponding `Visitor` method and vice versa The only three remaining method-level asymmetries after this PR are `visit_stmt` and `visit_nested_use_tree` (only on `Visitor`) and `visit_span` (only on `MutVisitor`). `visit_stmt` doesn't seem applicable to `MutVisitor` because `walk_flat_map_stmt_kind` will ask `flat_map_item` / `filter_map_expr` to potentially turn a single `Stmt` to multiple based on what a visitor wants. So only using `flat_map_stmt` seems appropriate. `visit_nested_use_tree` is used for `rustc_resolve` to track stuff. Not useful for `MutVisitor` for now. `visit_span` is currently not used for `MutVisitor` already, it was just kept in case we want to revive rust-lang/rust#127241. cc `@cjgillot` maybe we could remove for now and re-insert later if we find a use-case? It does involve some extra effort to maintain. * Remaining FIXMEs `visit_lifetime` has an extra param for `Visitor` that's not in `MutVisitor`. This is again something only used by `rustc_resolve`. I think we can keep that symmetry for now.
2025-06-21Rollup merge of #142690 - petrochenkov:expnoparam, r=compiler-errorsJana Dönszelmann-46/+46
expand: Remove some unnecessary generic parameters
2025-06-20Use a symbol for `ExpansionConfig::crate_name`.Nicholas Nethercote-5/+5
This avoids some symbol interning and `to_string` conversions.
2025-06-19completely deduplicate `Visitor` and `MutVisitor`Deadbeef-6/+6
2025-06-18expand: Remove some unnecessary generic parametersVadim Petrochenkov-46/+46
2025-06-17Rollup merge of #142371 - fee1-dead-contrib:push-xqlkumzurkus, r=petrochenkovJacob Pratt-17/+18
avoid `&mut P<T>` in `visit_expr` etc methods trying a different way than rust-lang/rust#141636 r? ghost
2025-06-12Introduce `-Zmacro-stats`.Nicholas Nethercote-45/+145
It collects data about macro expansions and prints them in a table after expansion finishes. It's very useful for detecting macro bloat, especially for proc macros. Details: - It measures code snippets by pretty-printing them and then measuring lines and bytes. This required a bunch of additional pretty-printing plumbing, in `rustc_ast_pretty` and `rustc_expand`. - The measurement is done in `MacroExpander::expand_invoc`. - The measurements are stored in `ExtCtxt::macro_stats`.
2025-06-12avoid `&mut P<T>` in `visit_expr` etc methodsDeadbeef-17/+18
2025-06-06Rollup merge of #141603 - nnethercote:reduce-P, r=fee1-deadGuillaume Gomez-21/+16
Reduce `ast::ptr::P` to a typedef of `Box` As per the MCP at https://github.com/rust-lang/compiler-team/issues/878. r? `@fee1-dead`
2025-05-30Rollup merge of #141430 - fee1-dead-contrib:push-nmzoprvtsvww, r=petrochenkovMatthias Krüger-30/+69
remove `visit_clobber` and move `DummyAstNode` to `rustc_expand` `visit_clobber` is not really useful except for one niche purpose involving generic code. We should just use the replace logic where we can.
2025-05-29avoid some usages of `&mut P<T>` in AST visitorsDeadbeef-1/+1
2025-05-29remove `visit_clobber` and move `DummyAstNode` to `rustc_expand`Deadbeef-30/+69
`visit_clobber` is not really useful except for one niche purpose involving generic code. We should just use the replace logic where we can.
2025-05-28consider glob imports in cfg suggestionbohan-3/+3
2025-05-27Reduce `P<T>` to a typedef of `Box<T>`.Nicholas Nethercote-21/+16
Keep the `P` constructor function for now, to minimize immediate churn. All the `into_inner` calls are removed, which is nice.
2025-05-08Remove associated type `InvocationCollectorNode::AttrsTy`Nicholas Nethercote-18/+12
It's always equal to `ast::AttrVec`, so just use that directly.
2025-05-03Report the `unsafe_attr_outside_unsafe` lint at the closest nodeUrgau-1/+5
2025-04-22Auto merge of #139897 - nnethercote:rm-OpenDelim-CloseDelim, r=petrochenkovbors-3/+2
Remove `token::{Open,Close}Delim` 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 { ``` r? `@petrochenkov`
2025-04-21Remove `token::{Open,Close}Delim`.Nicholas Nethercote-3/+2
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-17Replace infallible `name_or_empty` methods with fallible `name` methods.Nicholas Nethercote-6/+6
I'm removing empty identifiers everywhere, because in practice they always mean "no identifier" rather than "empty identifier". (An empty identifier is impossible.) It's better to use `Option` to mean "no identifier" because you then can't forget about the "no identifier" possibility. Some specifics: - When testing an attribute for a single name, the commit uses the `has_name` method. - When testing an attribute for multiple names, the commit uses the new `has_any_name` method. - When using `match` on an attribute, the match arms now have `Some` on them. In the tests, we now avoid printing empty identifiers by not printing the identifier in the `error:` line at all, instead letting the carets point out the problem.
2025-04-10Address review comments.Nicholas Nethercote-1/+1
2025-04-10Rename some `name` variables as `ident`.Nicholas Nethercote-5/+5
It bugs me when variables of type `Ident` are called `name`. It leads to silly things like `name.name`. `Ident` variables should be called `ident`, and `name` should be used for variables of type `Symbol`. This commit improves things by by doing `s/name/ident/` on a bunch of `Ident` variables. Not all of them, but a decent chunk.
2025-04-01Address review comments.Nicholas Nethercote-3/+1