Refactor lint buffering to avoid requiring a giant enum
Lint buffering currently relies on a giant enum `BuiltinLintDiag` containing all the lints that might potentially get buffered. In addition to being an unwieldy enum in a central crate, this also makes `rustc_lint_defs` a build bottleneck: it depends on various types from various crates (with a steady pressure to add more), and many crates depend on it.
Having all of these variants in a separate crate also prevents detecting when a variant becomes unused, which we can do with a dedicated type defined and used in the same crate.
Refactor this to use a dyn trait, to allow using `LintDiagnostic` types directly.
Because the existing `BuiltinLintDiag` requires some additional types in order to decorate some variants, which are only available later in `rustc_lint`, use an enum `DecorateDiagCompat` to handle both the `dyn LintDiagnostic` case and the `BuiltinLintDiag` case.
---
With the infrastructure in place, use it to migrate three of the enum variants to use `LintDiagnostic` directly, as a proof of concept and to demonstrate that the net result is a reduction in code size and a removal of a boilerplate-heavy layer of indirection.
Also remove an unused `BuiltinLintDiag` variant.
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
Lint buffering currently relies on a giant enum `BuiltinLintDiag`
containing all the lints that might potentially get buffered. In
addition to being an unwieldy enum in a central crate, this also makes
`rustc_lint_defs` a build bottleneck: it depends on various types from
various crates (with a steady pressure to add more), and many crates
depend on it.
Having all of these variants in a separate crate also prevents detecting
when a variant becomes unused, which we can do with a dedicated type
defined and used in the same crate.
Refactor this to use a dyn trait, to allow using `LintDiagnostic` types
directly.
This requires boxing, but all of this is already on the slow path
(emitting an error).
Because the existing `BuiltinLintDiag` requires some additional types in
order to decorate some variants, which are only available later in
`rustc_lint`, use an enum `DecorateDiagCompat` to handle both the `dyn
LintDiagnostic` case and the `BuiltinLintDiag` case.
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.
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```
`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(_)`.
Extend `QueryStability` to handle `IntoIterator` implementations
This PR extends the `rustc::potential_query_instability` lint to check values passed as `IntoIterator` implementations.
Full disclosure: I want the lint to warn about this line (please see #138871 for why): aa8f0fd716/src/librustdoc/json/mod.rs (L261)
However, the lint warns about several other lines as well.
Final note: the functions `get_callee_generic_args_and_args` and `get_input_traits_and_projections` were copied directly from [Clippy's source code](4fd8c04da0/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs (L445-L496)).
Fix adjacent code
Fix duplicate warning; merge test into `tests/ui-fulldeps/internal-lints`
Use `rustc_middle::ty::FnSig::inputs`
Address two review comments
- https://github.com/rust-lang/rust/pull/139345#discussion_r2109006991
- https://github.com/rust-lang/rust/pull/139345#discussion_r2109058588
Use `Instance::try_resolve`
Import `rustc_middle::ty::Ty` as `Ty` rather than `MiddleTy`
Simplify predicate handling
Add more `#[allow(rustc::potential_query_instability)]` following rebase
Remove two `#[allow(rustc::potential_query_instability)]` following rebase
Address review comment
Update compiler/rustc_lint/src/internal.rs
Co-authored-by: lcnr <rust@lcnr.de>
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.
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.
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````````
The use of `Not` to describe the `!` in `macro_rules!` reads
confusingly, and also results in search collisions with the diagnostic
structure `MacroRulesNot` elsewhere in the compiler. Rename it to use
the more conventional `Bang` for `!`.
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.
Expand test coverage to include all of these cases.
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.
Revert "Port `#[allow_internal_unsafe]` to the new attribute system"
This reverts commit 4f7a6ace9e2f2192af7b5d32f4b1664189e0e143 (PR: https://github.com/rust-lang/rust/pull/144857)
r? `@Kobzol`
cc: `@scrabsha`
clean revert it seems :3
Implement declarative (`macro_rules!`) attribute macros (RFC 3697)
This implements [RFC 3697](https://github.com/rust-lang/rust/issues/143547), "Declarative (`macro_rules!`) attribute macros".
I would suggest reading this commit-by-commit. This first introduces the
feature gate, then adds parsing for attribute rules (doing nothing with them),
then adds the ability to look up and apply `macro_rules!` attributes by path,
then adds support for local attributes, then adds a test, and finally makes
various improvements to errors.
Add infrastructure to apply an attribute macro given argument tokens and
body tokens.
Teach the resolver to consider `macro_rules` macros when looking for an
attribute via a path.
This does not yet handle local `macro_rules` attributes.
Detect more `cfg`d 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)))]
| ^^^^^^^^^^
```
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)))]
| ^^^^^^^^^^
```
Port the proc macro attributes to the new attribute parsing infrastructure
Ports `#[proc_macro]`, `#[proc_macro_attribute]`, `#[proc_macro_derive]` and `#[rustc_builtin_macro]` to the new attribute parsing infrastructure for https://github.com/rust-lang/rust/issues/131229#issuecomment-2971351163
I've split this PR into commits for reviewability, and left some comments to clarify things
I did 4 related attributes in one PR because they share a lot of their code and logic, and doing them separately is kind of annoying as I need to leave both the old and new parsing in place then.
r? ``@oli-obk``
cc ``@jdonszelmann``
Rather than adding `get_unused_rule` to the `TTMacroExpander` trait, put
it on the concrete `MacroRulesMacroExpander`, and downcast to that type
via `Any` in order to call it.
Suggested-by: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Make slice comparisons const
This needed a fix for `derive_const`, too, as it wasn't usable in libcore anymore as trait impls need const stability attributes. I think we can't use the same system as normal trait impls while `const_trait_impl` is still unstable.
r? ```@fee1-dead```
cc rust-lang/rust#143800
Fix ice for feature-gated `cfg` attributes applied to the crate
This PR fixes two fixes:
1. When a feature gated option of the `cfg` attribute is applied to the crate, an ICE would occur because features are not yet available at that stage. This is fixed by ignoring the feature gate at that point, the attribute will later be re-checked (this was already done) when the feature gate is available. Fixes https://github.com/rust-lang/rust/issues/143977
2. Errors and lints on the `cfg` attribute applied to the crate would be produced twice, because of the re-checking. This is fixed by not producing any errors and lints during the first run.
The added regression test checks both problems.
r? ``@jdonszelmann``