Fix associated item removal suggestion
We were previously telling people to write what was already there, instead of removal (treating it as a `help`). We now properly suggest to remove the code that needs to be removed.
```
error[E0229]: associated item constraints are not allowed here
--> $DIR/E0229.rs:13:25
|
LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ^^^^^^^ associated item constraint not allowed here
|
help: consider removing this associated item binding
|
LL - fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
LL + fn baz<I>(x: &<I as Foo>::A) {}
|
```
We were previously telling people to write what was already there, instead of removal.
```
error[E0229]: associated item constraints are not allowed here
--> $DIR/E0229.rs:13:25
|
LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ^^^^^^^ associated item constraint not allowed here
|
help: consider removing this associated item binding
|
LL - fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
LL + fn baz<I>(x: &<I as Foo>::A) {}
|
```
Silence follow-up errors directly based on error types and regions
During type_of, we used to just return an error type if there were any errors encountered. This is problematic, because it means a struct declared as `struct Foo<'static>` will end up not finding any inherent or trait impls because those impl blocks' `Self` type will be `{type error}` instead of `Foo<'re_error>`. Now it's the latter, silencing nonsensical follow-up errors about `Foo` not having any methods.
Unfortunately that now allows for new follow-up errors, because borrowck treats `'re_error` as `'static`, causing nonsensical errors about non-error lifetimes not outliving `'static`. So what I also did was to just strip all outlives bounds that borrowck found, thus never letting it check them. There are probably more nuanced ways to do this, but I worried there would be other nonsensical errors if some outlives bounds were missing. Also from the test changes, it looked like an improvement everywhere.
Use parenthetical notation for `Fn` traits
Always use the `Fn(T) -> R` format when printing closure traits instead of `Fn<(T,), Output = R>`.
Address #67100:
```
error[E0277]: expected a `Fn()` closure, found `F`
--> file.rs:6:13
|
6 | call_fn(f)
| ------- ^ expected an `Fn()` closure, found `F`
| |
| required by a bound introduced by this call
|
= note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `call_fn`
--> file.rs:1:15
|
1 | fn call_fn<F: Fn() -> ()>(f: &F) {
| ^^^^^^^^^^ required by this bound in `call_fn`
help: consider further restricting this bound
|
5 | fn call_any<F: std::any::Any + Fn()>(f: &F) {
| ++++++
```
Fold item bounds before proving them in `check_type_bounds` in new solver
Vaguely confident that this is sufficient to prevent rust-lang/trait-system-refactor-initiative#46 and rust-lang/trait-system-refactor-initiative#62.
This is not the "correct" solution, but will probably suffice until coinduction, at which point we implement the right solution (`check_type_bounds` must prove `Assoc<...> alias-eq ConcreteType`, normalizing requires proving item bounds).
r? lcnr
Always use the `Fn(T) -> R` format when printing closure traits instead of `Fn<(T,), Output = R>`.
Fix#67100:
```
error[E0277]: expected a `Fn()` closure, found `F`
--> file.rs:6:13
|
6 | call_fn(f)
| ------- ^ expected an `Fn()` closure, found `F`
| |
| required by a bound introduced by this call
|
= note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `call_fn`
--> file.rs:1:15
|
1 | fn call_fn<F: Fn() -> ()>(f: &F) {
| ^^^^^^^^^^ required by this bound in `call_fn`
help: consider further restricting this bound
|
5 | fn call_any<F: std::any::Any + Fn()>(f: &F) {
| ++++++
```
Rollup of 7 pull requests
Successful merges:
- #120929 (Wrap dyn type with parentheses in suggestion)
- #122591 (Suggest using type args directly instead of equality constraint)
- #122598 (deref patterns: lower deref patterns to MIR)
- #123048 (alloc::Layout: explicitly document size invariant on the type level)
- #123993 (Do `check_coroutine_obligations` once per typeck root)
- #124218 (Allow nesting subdiagnostics in #[derive(Subdiagnostic)])
- #124285 (Mark ``@RUSTC_BUILTIN`` search path usage as unstable)
r? `@ghost`
`@rustbot` modify labels: rollup
Suggest using type args directly instead of equality constraint
When type arguments are written erroneously using an equality constraint we suggest specifying them directly without the equality constraint.
Fixes#122162
Changes the diagnostic in the issue from:
```rust
error[E0229]: associated type bindings are not allowed here
9 | impl std::cmp::PartialEq<Rhs = T> for S {
| ^^^^^^^ associated type not allowed here
|
```
to
```rust
error[E0229]: associated type bindings are not allowed here
9 | impl std::cmp::PartialEq<Rhs = T> for S {
| ^^^^^^^ associated type not allowed here
|
help: to use `T` as a generic argument specify it directly
|
| impl std::cmp::PartialEq<T> for S {
| ~
```
Split an item bounds and an item's super predicates
This is the moral equivalent of #107614, but instead for predicates this applies to **item bounds**. This PR splits out the item bounds (i.e. *all* predicates that are assumed to hold for the alias) from the item *super predicates*, which are the subset of item bounds which share the same self type as the alias.
## Why?
Much like #107614, there are places in the compiler where we *only* care about super-predicates, and considering predicates that possibly don't have anything to do with the alias is problematic. This includes things like closure signature inference (which is at its core searching for `Self: Fn(..)` style bounds), but also lints like `#[must_use]`, error reporting for aliases, computing type outlives predicates.
Even in cases where considering all of the `item_bounds` doesn't lead to bugs, unnecessarily considering irrelevant bounds does lead to a regression (#121121) due to doing extra work in the solver.
## Example 1 - Trait Aliases
This is best explored via an example:
```
type TAIT<T> = impl TraitAlias<T>;
trait TraitAlias<T> = A + B where T: C;
```
The item bounds list for `Tait<T>` will include:
* `Tait<T>: A`
* `Tait<T>: B`
* `T: C`
While `item_super_predicates` query will include just the first two predicates.
Side-note: You may wonder why `T: C` is included in the item bounds for `TAIT`? This is because when we elaborate `TraitAlias<T>`, we will also elaborate all the predicates on the trait.
## Example 2 - Associated Type Bounds
```
type TAIT<T> = impl Iterator<Item: A>;
```
The `item_bounds` list for `TAIT<T>` will include:
* `Tait<T>: Iterator`
* `<Tait<T> as Iterator>::Item: A`
But the `item_super_predicates` will just include the first bound, since that's the only bound that is relevant to the *alias* itself.
## So what
This leads to some diagnostics duplication just like #107614, but none of it will be user-facing. We only see it in the UI test suite because we explicitly disable diagnostic deduplication.
Regarding naming, I went with `super_predicates` kind of arbitrarily; this can easily be changed, but I'd consider better names as long as we don't block this PR in perpetuity.
clean up `Sized` checking
This PR cleans up `sized_constraint` and related functions to make them simpler and faster. This should not make more or less code compile, but it can change error output in some rare cases.
## enums and unions are `Sized`, even if they are not WF
The previous code has some special handling for enums, which made them sized if and only if the last field of each variant is sized. For example given this definition (which is not WF)
```rust
enum E<T1: ?Sized, T2: ?Sized, U1: ?Sized, U2: ?Sized> {
A(T1, T2),
B(U1, U2),
}
```
the enum was sized if and only if `T2` and `U2` are sized, while `T1` and `T2` were ignored for `Sized` checking. After this PR this enum will always be sized.
Unsized enums are not a thing in Rust and removing this special case allows us to return an `Option<Ty>` from `sized_constraint`, rather than a `List<Ty>`.
Similarly, the old code made an union defined like this
```rust
union Union<T: ?Sized, U: ?Sized> {
head: T,
tail: U,
}
```
sized if and only if `U` is sized, completely ignoring `T`. This just makes no sense at all and now this union is always sized.
## apply the "perf hack" to all (non-error) types, instead of just type parameters
This "perf hack" skips evaluating `sized_constraint(adt): Sized` if `sized_constraint(adt): Sized` exactly matches a predicate defined on `adt`, for example:
```rust
// `Foo<T>: Sized` iff `T: Sized`, but we know `T: Sized` from a predicate of `Foo`
struct Foo<T /*: Sized */>(T);
```
Previously this was only applied to type parameters and now it is applied to every type. This means that for example this type is now always sized:
```rust
// Note that this definition is WF, but the type `S<T>` not WF in the global/empty ParamEnv
struct S<T>([T]) where [T]: Sized;
```
I don't anticipate this to affect compile time of any real-world program, but it makes the code a bit nicer and it also makes error messages a bit more consistent if someone does write such a cursed type.
## tuples are sized if the last type is sized
The old solver already has this behavior and this PR also implements it for the new solver and `is_trivially_sized`. This makes it so that tuples work more like a struct defined like this:
```rust
struct TupleN<T1, T2, /* ... */ Tn: ?Sized>(T1, T2, /* ... */ Tn);
```
This might improve the compile time of programs with large tuples a little, but is mostly also a consistency fix.
## `is_trivially_sized` for more types
This function is used post-typeck code (borrowck, const eval, codegen) to skip evaluating `T: Sized` in some cases. It will now return `true` in more cases, most notably `UnsafeCell<T>` and `ManuallyDrop<T>` where `T.is_trivially_sized`.
I'm anticipating that this change will improve compile time for some real world programs.
Revert "Auto merge of #122140 - oli-obk:track_errors13, r=davidtwco"
This reverts commit 65cd843ae06ad00123c131a431ed5304e4cd577a, reversing changes made to d255c6a57c393db6221b1ff700daea478436f1cd.
reverts https://github.com/rust-lang/rust/pull/122140
It was a large regression in wall time due to trashing CPU caches
Make `DefiningAnchor::Bind` only store the opaque types that may be constrained, instead of the current infcx root item.
This makes `Bind` almost always be empty, so we can start forwarding it to queries, allowing us to remove `Bubble` entirely (not done in this PR)
The only behaviour change is in diagnostics.
r? `@lcnr` `@compiler-errors`
Rollup of 15 pull requests
Successful merges:
- #116791 (Allow codegen backends to opt-out of parallel codegen)
- #116793 (Allow targets to override default codegen backend)
- #117458 (LLVM Bitcode Linker: A self contained linker for nvptx and other targets)
- #119385 (Fix type resolution of associated const equality bounds (take 2))
- #121438 (std support for wasm32 panic=unwind)
- #121893 (Add tests (and a bit of cleanup) for interior mut handling in promotion and const-checking)
- #122080 (Clarity improvements to `DropTree`)
- #122152 (Improve diagnostics for parenthesized type arguments)
- #122166 (Remove the unused `field_remapping` field from `TypeLowering`)
- #122249 (interpret: do not call machine read hooks during validation)
- #122299 (Store backtrace for `must_produce_diag`)
- #122318 (Revision-related tweaks for next-solver tests)
- #122320 (Use ptradd for vtable indexing)
- #122328 (unix_sigpipe: Replace `inherit` with `sig_dfl` in syntax tests)
- #122330 (bootstrap readme: fix, improve, update)
r? `@ghost`
`@rustbot` modify labels: rollup
This improves parallel rustc parallelism by avoiding the bottleneck after each individual `par_body_owners` (because it needs to wait for queries to finish, so if there is one long running one, a lot of cores will be idle while waiting for the single query).