This commit partly undoes #104863, which combined the builtin lints pass
with other lints. This caused a slowdown, because often there are no
other lints, and it's faster to do a pass with a single lint directly
than it is to do a combined pass with a `passes` vector containing a
single lint.
I removed these in #105291, and subsequently learned they are necessary
for performance.
This commit reinstates them with the new and more descriptive names
`RuntimeCombined{Early,Late}LintPass`, similar to the existing passes
like `BuiltinCombinedEarlyLintPass`. It also adds some comments,
particularly emphasising how we have ways to combine passes at both
compile-time and runtime. And it moves some comments around.
compiler: remove unnecessary imports and qualified paths
Some of these imports were necessary before Edition 2021, others were already in the prelude.
I hope it's fine that this PR is so spread-out across files :/
Make `missing_copy_implementations` more cautious
- Fixes https://github.com/rust-lang/rust/issues/98348
- Also makes the lint not fire on large types and types containing raw pointers. Thoughts?
Remove `{Early,Late}LintPassObjects`.
`EarlyContextAndPass` wraps a single early lint pass. We aggregate multiple passes into that single pass by using `EarlyLintPassObjects`.
This commit removes `EarlyLintPassObjects` by changing `EarlyContextAndPass` into `EarlyContextAndPasses`. I.e. it just removes a level of indirection. This makes the code simpler and slightly faster.
The commit does likewise for late lints.
r? `@cjgillot`
Put all cached values into a central struct instead of just the stable hash
cc `@nnethercote`
this allows re-use of the type for Predicate without duplicating all the logic for the non-hash cached fields
`EarlyContextAndPass` wraps a single early lint pass. We aggregate
multiple passes into that single pass by using `EarlyLintPassObjects`.
This commit removes `EarlyLintPassObjects` by changing
`EarlyContextAndPass` into `EarlyContextAndPasses`. I.e. it just removes
a level of indirection. This makes the code simpler and slightly faster.
The commit does likewise for late lints.
This avoids calling `early_lint_node` twice.
Note: one `early_lint_node` call had `!pre_expansion` for the second
argument and the other had `false`. The new single call just has
`!pre_expansion`. This results in a reduction of duplicate error
messages in some `ui-fulldeps` tests. The order of some `ui-fulldeps`
output also changes, but that doesn't matter.
The lint definitions use macros heavily. This commit merges some of them
that are split unnecessarily. I find the reduced indirection makes it
easier to imagine what the generated code will look like.
Lower them into a single item with multiple resolutions instead.
This also allows to remove additional `NodId`s and `DefId`s related to those additional items.
Prefer doc comments over `//`-comments in compiler
Doc comments are generally nicer: they show up in the documentation, they are shown in IDEs when you hover other mentions of items, etc. Thus it makes sense to use them instead of `//`-comments.
Separate lifetime ident from lifetime resolution in HIR
Drive-by: change how suggested generic args are computed.
Fixes https://github.com/rust-lang/rust/issues/103815
I recommend reviewing commit-by-commit.
Make rustc_target usable outside of rustc
I'm working on showing type size in rust-analyzer (https://github.com/rust-lang/rust-analyzer/pull/13490) and I currently copied rustc code inside rust-analyzer, which works, but is bad. With this change, I would become able to use `rustc_target` and `rustc_index` directly in r-a, reducing the amount of copy needed.
This PR contains some feature flag to put nightly features behind them to make crates buildable on the stable compiler + makes layout related types generic over index type + removes interning of nested layouts.
Avoid `GenFuture` shim when compiling async constructs
Previously, async constructs would be lowered to "normal" generators, with an additional `from_generator` / `GenFuture` shim in between to convert from `Generator` to `Future`.
The compiler will now special-case these generators internally so that async constructs will *directly* implement `Future` without the need to go through the `from_generator` / `GenFuture` shim.
The primary motivation for this change was hiding this implementation detail in stack traces and debuginfo, but it can in theory also help the optimizer as there is less abstractions to see through.
---
Given this demo code:
```rust
pub async fn a(arg: u32) -> Backtrace {
let bt = b().await;
let _arg = arg;
bt
}
pub async fn b() -> Backtrace {
Backtrace::force_capture()
}
```
I would get the following with the latest stable compiler (on Windows):
```
4: async_codegen:🅱️:async_fn$0
at .\src\lib.rs:10
5: core::future::from_generator::impl$1::poll<enum2$<async_codegen:🅱️:async_fn_env$0> >
at /rustc/897e37553bba8b42751c67658967889d11ecd120\library\core\src\future\mod.rs:91
6: async_codegen:🅰️:async_fn$0
at .\src\lib.rs:4
7: core::future::from_generator::impl$1::poll<enum2$<async_codegen:🅰️:async_fn_env$0> >
at /rustc/897e37553bba8b42751c67658967889d11ecd120\library\core\src\future\mod.rs:91
```
whereas now I get a much cleaner stack trace:
```
3: async_codegen:🅱️:async_fn$0
at .\src\lib.rs:10
4: async_codegen:🅰️:async_fn$0
at .\src\lib.rs:4
```
Previously, async constructs would be lowered to "normal" generators,
with an additional `from_generator` / `GenFuture` shim in between to
convert from `Generator` to `Future`.
The compiler will now special-case these generators internally so that
async constructs will *directly* implement `Future` without the need
to go through the `from_generator` / `GenFuture` shim.
The primary motivation for this change was hiding this implementation
detail in stack traces and debuginfo, but it can in theory also help
the optimizer as there is less abstractions to see through.
Refactor must_use lint into two parts
Before, the lint did the checking for `must_use` and pretty printing the types in a special format in one pass, causing quite complex and untranslatable code.
Now the collection and printing is split in two. That should also make it easier to translate or extract the type pretty printing in the future.
Also fixes an integer overflow in the array length pluralization
calculation.
fixes#104352
Rollup of 11 pull requests
Successful merges:
- #103396 (Pin::new_unchecked: discuss pinning closure captures)
- #104416 (Fix using `include_bytes` in pattern position)
- #104557 (Add a test case for async dyn* traits)
- #104559 (Split `MacArgs` in two.)
- #104597 (Probe + better error messsage for `need_migrate_deref_output_trait_object`)
- #104656 (Move tests)
- #104657 (Do not check transmute if has non region infer)
- #104663 (rustdoc: factor out common button CSS)
- #104666 (Migrate alias search result to CSS variables)
- #104674 (Make negative_impl and negative_impl_exists take the right types)
- #104692 (Update test's cfg-if dependency to 1.0)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
`MacArgs` is an enum with three variants: `Empty`, `Delimited`, and `Eq`. It's
used in two ways:
- For representing attribute macro arguments (e.g. in `AttrItem`), where all
three variants are used.
- For representing function-like macros (e.g. in `MacCall` and `MacroDef`),
where only the `Delimited` variant is used.
In other words, `MacArgs` is used in two quite different places due to them
having partial overlap. I find this makes the code hard to read. It also leads
to various unreachable code paths, and allows invalid values (such as
accidentally using `MacArgs::Empty` in a `MacCall`).
This commit splits `MacArgs` in two:
- `DelimArgs` is a new struct just for the "delimited arguments" case. It is
now used in `MacCall` and `MacroDef`.
- `AttrArgs` is a renaming of the old `MacArgs` enum for the attribute macro
case. Its `Delimited` variant now contains a `DelimArgs`.
Various other related things are renamed as well.
These changes make the code clearer, avoids several unreachable paths, and
disallows the invalid values.
Add `PolyExistentialPredicate` type alias
Wrapping `ExistentialPredicate`s in a binder is very common, and this alias already exists for the `PolyExistential{TraitRef,Projection}` types.
Before, the lint did the checking for `must_use` and pretty printing the
types in a special format in one pass, causing quite complex and
untranslatable code.
Now the collection and printing is split in two. That should also make
it easier to translate or extract the type pretty printing in the
future.
Also fixes an integer overflow in the array length pluralization
calculation.
Convert predicates into Predicate in the Obligation constructor
instead of having almost all callers do that.
This reduces a bit of boilerplate, and also paves the way for my work towards https://github.com/rust-lang/compiler-team/issues/531 (as it makes it easier to accept both goals and clauses where right now it only accepts predicates).
Record `LocalDefId` in HIR nodes instead of a side table
This is part of an attempt to remove the `HirId -> LocalDefId` table from HIR.
This attempt is a prerequisite to creation of `LocalDefId` after HIR lowering (https://github.com/rust-lang/rust/pull/96840), by controlling how `def_id` information is accessed.
This first part adds the information to HIR nodes themselves instead of a table.
The second part is https://github.com/rust-lang/rust/pull/103902
The third part will be to make `hir::Visitor::visit_fn` take a `LocalDefId` as last parameter.
The fourth part will be to completely remove the side table.
Use `token::Lit` in `ast::ExprKind::Lit`.
Instead of `ast::Lit`.
Literal lowering now happens at two different times. Expression literals are lowered when HIR is crated. Attribute literals are lowered during parsing.
r? `@petrochenkov`
Instead of `ast::Lit`.
Literal lowering now happens at two different times. Expression literals
are lowered when HIR is crated. Attribute literals are lowered during
parsing.
This commit changes the language very slightly. Some programs that used
to not compile now will compile. This is because some invalid literals
that are removed by `cfg` or attribute macros will no longer trigger
errors. See this comment for more details:
https://github.com/rust-lang/rust/pull/102944#issuecomment-1277476773
Walk types more carefully in `ProhibitOpaqueTypes` visitor
The visitor didn't account for the case where you could have `<TAIT as Trait>::Assoc` normalize to itself, in the case of a `type TAIT = impl Trait` with an unconstrained associated type. That causes the visitor to loop on the same type over and over.
Fixes#104291
Resolve lifetimes independently for each item-like.
Now that the heavy-lifting is done on the AST and during lowering, we do not need to perform HIR lifetime resolution on a full item at once. Instead, we can treat each item-like independently, and look at `generics_of` the parent exceptionally for associated items.
No longer lint against `#[must_use] async fn foo()`.
When encountering a statement that awaits on a `Future`, check if the
`Future`'s parent item is annotated with `#[must_use]` and emit a lint
if so. This effectively makes `must_use` an annotation on the
`Future::Output` instead of only the `Future` itself.
Fix#78149.
fix: lint against the functions `LintContext::{lookup_with_diagnostics,lookup,struct_span_lint,lint}`, `TyCtxt::struct_lint_node`, `LintLevelsBuilder::struct_lint`.
Change #[suggestion_*] attributes to use style="..."
As discussed [on Zulip](https://rust-lang.zulipchat.com/#narrow/stream/336883-i18n/topic/.23100717.20tool_only_span_suggestion), this changes `#[(multipart_)suggestion_{short,verbose,hidden}(...)]` attributes to plain `#[(multipart_)suggestion(...)]` attributes with a `style = "{short,verbose,hidden}"` parameter.
It also adds a new style, `tool-only`, that corresponds to `tool_only_span_suggestion`/`tool_only_multipart_suggestion` and causes the suggestion to not be shown in human-readable output at all.
Best reviewed commit-by-commit, there's a bit of noise in there.
cc #100717 `@compiler-errors`
r? `@davidtwco`
Accept `TyCtxt` instead of `TyCtxtAt` in `Ty::is_*` functions
Functions in answer:
- `Ty::is_freeze`
- `Ty::is_sized`
- `Ty::is_unpin`
- `Ty::is_copy_modulo_regions`
This allows to remove a lot of useless `.at(DUMMY_SP)`, making the code a bit nicer :3
r? `@compiler-errors`
spastorino noticed some silly expressions like `item_id.def_id.def_id`.
This commit renames several `def_id: OwnerId` fields as `owner_id`, so
those expressions become `item_id.owner_id.def_id`.
`item_id.owner_id.local_def_id` would be even clearer, but the use of
`def_id` for values of type `LocalDefId` is *very* widespread, so I left
that alone.
Fix wrapped valid-range handling in ty_find_init_error
Rust's niche handling allows for wrapping valid ranges with end < start;
for instance, a valid range with start=43 and end=41 means a niche of
42. Most places in the compiler handle this correctly, but
`ty_find_init_error` assumed that `lo > 0` means the type cannot contain a
zero.
Fix it to handle wrapping ranges.
Flatten diagnostic slug modules
This makes it easier to grep for the slugs in the code.
See https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Localization.20infra.20interferes.20with.20grepping.20for.20error for more discussion about it.
This was mostly done with a few regexes and a bunch of manual work. This also exposes a pretty annoying inconsistency for the extra labels. Some of the extra labels are defined as additional properties in the fluent message (which makes them not prefixed with the crate name) and some of them are new fluent messages themselves (which makes them prefixed with the crate name). I don't know whether we want to clean this up at some point but it's useful to know.
r? `@davidtwco`
Change `unknown_lint` applicability to `MaybeIncorrect`
This small PR changes the applicability of `unknown_lint` to `MaybeIncorrect`, because the suggested lint might not be the correct one.
Here is one example where the current applicability causes a problem. Clippy has a set of internal lints guarded by a feature called `internal`. If the feature is not enabled, then the internal lints are "unknown." In that case, running `cargo clippy --fix ...` on `clippy_utils` causes lines such as the followig
26c96e3416/src/tools/clippy/clippy_utils/src/paths.rs (L51-L52)
to be changed to
```rust
#[expect(clippy::invalid_regex)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
```
which is not correct.
Introduce `subst_iter` and `subst_iter_copied` on `EarlyBinder`
Makes working with bounds lists a bit easier, which I seem to do a lot.
Specifically, means that we don't need to do `.transpose_iter().map(|(pred, _)| *pred)` every time we want to iterate through an `EarlyBinder<&'tcx [(Predicate, Span)]>` (and even then, still have to call `subst` later), which was a very awkward idiom imo.
Rust's niche handling allows for wrapping valid ranges with end < start;
for instance, a valid range with start=43 and end=41 means a niche of
42. Most places in the compiler handle this correctly, but
ty_find_init_error assumed that `lo > 0` means the type cannot contain a
zero.
Fix it to handle wrapping ranges.
Add a test to cover this case.
Slightly tweak comments wrt `lint_overflowing_range_endpoint`
From the review: https://github.com/rust-lang/rust/pull/101986#discussion_r975610611
It _seemed_ that the lint was not emitted when the `if` check failed, but _actually_ this happens already in a special case and the lint is emitted outside of this function, if this function doesn't. I've cleared up the code/comments a bit, so it's more obvious :)
r? ```@estebank```
translation: doc comments with derives, subdiagnostic-less enum variants, more derive use
- Adds support for `doc` attributes in the diagnostic derives so that documentation comments don't result in the derive failing.
- Adds support for enum variants in the subdiagnostic derive to not actually correspond to an addition to a diagnostic.
- Made use of the derive in more places in the `rustc_ast_lowering`, `rustc_ast_passes`, `rustc_lint`, `rustc_session`, `rustc_infer` - taking advantage of recent additions like eager subdiagnostics, multispan suggestions, etc.
cc #100717
`AddToDiagnostic::add_to_diagnostic_with` is similar to the previous
`AddToDiagnostic::add_to_diagnostic` but takes a function that can be
used by the caller to modify diagnostic messages originating from the
subdiagnostic (such as performing translation eagerly).
`add_to_diagnostic` now just calls `add_to_diagnostic_with` with an
empty closure.
Signed-off-by: David Wood <david.wood@huawei.com>
I refactored the code:
- Removed handling of methods, as it felt entirely unnecessary
- Removed clippy utils (obviously...)
- Used some shiny compiler features
(let-else is very handy for lints 👀)
- I also renamed the lint to `for_loop_over_fallibles` (note: no `s`).
I'm not sure what's the naming convention here, so maybe I'm wrong.
Remove `-Ztime`
Because it has a lot of overlap with `-Ztime-passes` but is generally less useful. Plus some related cleanups.
Best reviewed one commit at a time.
r? `@davidtwco`
The compiler currently has `-Ztime` and `-Ztime-passes`. I've used
`-Ztime-passes` for years but only recently learned about `-Ztime`.
What's the difference? Let's look at the `-Zhelp` output:
```
-Z time=val -- measure time of rustc processes (default: no)
-Z time-passes=val -- measure time of each rustc pass (default: no)
```
The `-Ztime-passes` description is clear, but the `-Ztime` one is less so.
Sounds like it measures the time for the entire process?
No. The real difference is that `-Ztime-passes` prints out info about passes,
and `-Ztime` does the same, but only for a subset of those passes. More
specifically, there is a distinction in the profiling code between a "verbose
generic activity" and an "extra verbose generic activity". `-Ztime-passes`
prints both kinds, while `-Ztime` only prints the first one. (It took me
a close reading of the source code to determine this difference.)
In practice this distinction has low value. Perhaps in the past the "extra
verbose" output was more voluminous, but now that we only print stats for a
pass if it exceeds 5ms or alters the RSS, `-Ztime-passes` is less spammy. Also,
a lot of the "extra verbose" cases are for individual lint passes, and you need
to also use `-Zno-interleave-lints` to see those anyway.
Therefore, this commit removes `-Ztime` and the associated machinery. One thing
to note is that the existing "extra verbose" activities all have an extra
string argument, so the commit adds the ability to accept an extra argument to
the "verbose" activities.
Lint against nested opaque types that don't satisfy associated type bounds
See the test failures for examples of places where this lint would fire.
r? `@oli-obk`
Move lint level source explanation to the bottom
So, uhhhhh
r? `@estebank`
## User-facing change
"note: `#[warn(...)]` on by default" and such are moved to the bottom of the diagnostic:
```diff
- = note: `#[warn(unsupported_calling_conventions)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+ = note: `#[warn(unsupported_calling_conventions)]` on by default
```
Why warning is enabled is the least important thing, so it shouldn't be the first note the user reads, IMO.
## Developer-facing change
`struct_span_lint` and similar methods have a different signature.
Before: `..., impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>)`
After: `..., impl Into<DiagnosticMessage>, impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>) -> &'b mut DiagnosticBuilder<'a, ()>`
The reason for this is that `struct_span_lint` needs to edit the diagnostic _after_ `decorate` closure is called. This also makes lint code a little bit nicer in my opinion.
Another option is to use `impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) -> DiagnosticBuilder<'a, ()>` altough I don't _really_ see reasons to do `let lint = lint.build(message)` everywhere.
## Subtle problem
By moving the message outside of the closure (that may not be called if the lint is disabled) `format!(...)` is executed earlier, possibly formatting `Ty` which may call a query that trims paths that crashes the compiler if there were no warnings...
I don't think it's that big of a deal, considering that we move from `format!(...)` to `fluent` (which is lazy by-default) anyway, however this required adding a workaround which is unfortunate.
## P.S.
I'm sorry, I do not how to make this PR smaller/easier to review. Changes to the lint API affect SO MUCH 😢
`Res::SelfTy` currently has two `Option`s. When the second one is `Some`
the first one is never consulted. So we can split it into two variants,
`Res::SelfTyParam` and `Res::SelfTyAlias`, reducing the size of `Res`
from 24 bytes to 12. This then shrinks `hir::Path` and
`hir::PathSegment`, which are the HIR types that take up the most space.