Commit Graph

275 Commits

Author SHA1 Message Date
Jonathan Brouwer
3851e6c7b6 Warn on macro calls for attributes that had this behaviour previously 2025-08-24 14:29:03 +02:00
bors
f5703d5dd3 Auto merge of #144689 - JonathanBrouwer:share_parse_path, r=jdonszelmann
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-22 10:27:12 +00:00
Jonathan Brouwer
17e34f6b24 Use the new attribute parser throughout the codebase 2025-08-22 08:58:45 +02:00
Jonathan Brouwer
21d3189779 Move validate_attr to rustc_attr_parsing 2025-08-22 08:37:19 +02:00
bors
d127901d94 Auto merge of #145410 - cuviper:expand-stack, r=lqd
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-22 04:05:26 +00:00
Jacob Pratt
25b81bf5ad Rollup merge of #145590 - nnethercote:ModKind-Inline, r=petrochenkov
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-21 01:12:19 -04:00
Nicholas Nethercote
bfd5d59f97 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(_)`.
2025-08-19 21:57:31 +10:00
Josh Stone
f68bcb376d 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-14 16:02:31 -07:00
Josh Triplett
354fcf2b52 mbe: Handle applying macro_rules derives
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-14 14:23:05 -07:00
Guillaume Gomez
bd6fb63596 Rollup merge of #145153 - joshtriplett:macro-kinds-plural, r=petrochenkov
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-13 18:43:01 +02:00
Jakub Beránek
c2bc9265f0 Rollup merge of #145274 - compiler-errors:unused-must-use, r=fmease
Remove unused `#[must_use]`

Self-explanatory

Fixes https://github.com/rust-lang/rust/issues/145257
2025-08-13 07:03:49 +02:00
Michael Goulet
2c0409c7e8 Remove unused must_use 2025-08-12 19:54:57 +00:00
Josh Triplett
0b855bcdc9 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.
2025-08-12 09:24:45 -07:00
Deadbeef
ad1113f87e remove P 2025-08-09 15:47:01 +08:00
Esteban Küber
77f75f91c5 tiny cleanup 2025-08-01 22:11:45 +00:00
Esteban Küber
4ba4559a9d remove recursive search for items 2025-08-01 22:02:52 +00:00
Esteban Küber
5210c501bc Limit how deep we visit items to find cfg'd out names 2025-08-01 21:51:05 +00:00
Esteban Küber
adcda6ca9a Detect more cfgd out items in resolution errors
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-08-01 21:50:36 +00:00
Guillaume Gomez
96340f6714 Stop compilation if macro expansion failed 2025-07-25 23:46:28 +02:00
Jonathan Brouwer
8e400f97e5 Fix ice for feature-gated cfg attributes applied to the crate
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
2025-07-15 23:28:15 +02:00
Jonathan Brouwer
6133c676d7 Define attribute parser & config evaluator 2025-07-15 09:21:26 +02:00
Michael Goulet
8cd3fa04e2 Don't give APITs names with macro expansion placeholder fragments in it 2025-06-25 15:42:11 +00:00
bors
c2ec7532ee Auto merge of #142706 - fee1-dead-contrib:push-zsznlqyrzsqo, r=oli-obk
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-22 14:03:44 +00:00
Jana Dönszelmann
6ed5d48cec Rollup merge of #142690 - petrochenkov:expnoparam, r=compiler-errors
expand: Remove some unnecessary generic parameters
2025-06-21 15:32:06 +02:00
Nicholas Nethercote
4a1f445142 Use a symbol for ExpansionConfig::crate_name.
This avoids some symbol interning and `to_string` conversions.
2025-06-20 13:17:39 +10:00
Deadbeef
3da58e673a completely deduplicate Visitor and MutVisitor 2025-06-19 17:50:44 +08:00
Vadim Petrochenkov
95cd989055 expand: Remove some unnecessary generic parameters 2025-06-18 20:34:20 +03:00
Jacob Pratt
e95fb09dfb Rollup merge of #142371 - fee1-dead-contrib:push-xqlkumzurkus, r=petrochenkov
avoid `&mut P<T>` in `visit_expr` etc methods

trying a different way than rust-lang/rust#141636
r? ghost
2025-06-17 23:19:34 +02:00
Nicholas Nethercote
376cbc3787 Introduce -Zmacro-stats.
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-12 21:17:17 +10:00
Deadbeef
5f0dd44b3b avoid &mut P<T> in visit_expr etc methods 2025-06-12 17:36:03 +08:00
Guillaume Gomez
93ca0af08c Rollup merge of #141603 - nnethercote:reduce-P, r=fee1-dead
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-06-06 23:53:16 +02:00
Matthias Krüger
a87bc9d9fe Rollup merge of #141430 - fee1-dead-contrib:push-nmzoprvtsvww, r=petrochenkov
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-30 07:01:29 +02:00
Deadbeef
367a877147 avoid some usages of &mut P<T> in AST visitors 2025-05-29 12:54:55 +08:00
Deadbeef
5e7185583f 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-29 12:46:26 +08:00
bohan
e9080948c6 consider glob imports in cfg suggestion 2025-05-28 00:59:47 +08:00
Nicholas Nethercote
991c91fdaa Reduce P<T> to a typedef of Box<T>.
Keep the `P` constructor function for now, to minimize immediate churn.

All the `into_inner` calls are removed, which is nice.
2025-05-27 13:29:24 +10:00
Nicholas Nethercote
d22461c9b7 Remove associated type InvocationCollectorNode::AttrsTy
It's always equal to `ast::AttrVec`, so just use that directly.
2025-05-08 19:59:48 +10:00
Urgau
f4e1ec111c Report the unsafe_attr_outside_unsafe lint at the closest node 2025-05-03 16:10:25 +02:00
bors
fae7785b60 Auto merge of #139897 - nnethercote:rm-OpenDelim-CloseDelim, r=petrochenkov
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-22 01:15:06 +00:00
Nicholas Nethercote
bf8ce32558 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 {
```
2025-04-21 07:35:56 +10:00
Nicholas Nethercote
2fef0a30ae Replace infallible name_or_empty methods with fallible name methods.
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-17 09:50:52 +10:00
Nicholas Nethercote
663a317c20 Address review comments. 2025-04-10 09:39:21 +10:00
Nicholas Nethercote
1b3fc585cb Rename some name variables as ident.
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-10 09:30:55 +10:00
Nicholas Nethercote
ec10833609 Address review comments. 2025-04-01 16:07:23 +11:00
Nicholas Nethercote
df247968f2 Move ast::Item::ident into ast::ItemKind.
`ast::Item` has an `ident` field.

- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
  `Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
  `Trait`, `TraitAlias`, `MacroDef`, `Delegation`.

- It's always empty for these item kinds: `Use`, `ForeignMod`,
  `GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.

There is a similar story for `AssocItemKind` and `ForeignItemKind`.

Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.

The commit is large but it's mostly obvious plumbing work. Some notable
things.

- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
  fields within some of the `ast::ItemKind` variants (specifically:
  `Struct`, `Union`, `Enum`). I might do that in a follow-up; this
  commit is big enough already.

- For the visitors: `FnKind` no longer needs an `ident` field because
  the `Fn` within how has one.

- In the parser, the `ItemInfo` typedef is no longer needed. It was used
  in various places to return an `Ident` alongside an `ItemKind`, but
  now the `Ident` (if present) is within the `ItemKind`.

- In a few places I renamed identifier variables called `name` (or
  `foo_name`) as `ident` (or `foo_ident`), to better match the type, and
  because `name` is normally used for `Symbol`s. It's confusing to see
  something like `foo_name.name`.
2025-04-01 14:08:57 +11:00
Vadim Petrochenkov
92d802eda6 expand: Leave traces when expanding cfg attributes 2025-03-26 15:30:12 +03:00
Oli Scherer
7cdc456727 Track whether an assoc item is in a trait impl or an inherent impl 2025-03-25 10:12:07 +00:00
Vadim Petrochenkov
0ac2801f25 expand: Do not report cfg_attr traces on macros as unused attributes 2025-03-21 18:25:29 +03:00
Oli Scherer
43e39260f9 Keep items around even if builtin macros on them fail to parse 2025-03-11 12:05:02 +00:00
Frank King
42f51d4fd4 Implment #[cfg] and #[cfg_attr] in where clauses 2025-03-01 22:02:46 +08:00