Rework upcasting confirmation to support upcasting to fewer projections in target bounds
This PR implements a modified trait upcasting algorithm that is resilient to changes in the number of associated types in the bounds of the source and target trait objects.
It does this by equating each bound of the target trait ref individually against the bounds of the source trait ref, rather than doing them all together by constructing a new trait object.
#### The new way we do trait upcasting confirmation
1. Equate the target trait object's principal trait ref with one of the supertraits of the source trait object's principal.
fdcab310b2/compiler/rustc_trait_selection/src/traits/select/mod.rs (L2509-L2525)
2. Make sure that every auto trait in the *target* trait object is present in the source trait ref's bounds.
fdcab310b2/compiler/rustc_trait_selection/src/traits/select/mod.rs (L2559-L2562)
3. For each projection in the *target* trait object, make sure there is exactly one projection that equates with it in the source trait ref's bound. If there is more than one, bail with ambiguity.
fdcab310b2/compiler/rustc_trait_selection/src/traits/select/mod.rs (L2526-L2557)
* Since there may be more than one that applies, we probe first to check that there is exactly one, then we equate it outside of a probe once we know that it's unique.
4. Make sure the lifetime of the source trait object outlives the lifetime of the target.
<details>
<summary>Meanwhile, this is how we used to do upcasting:</summary>
1. For each supertrait of the source trait object, take that supertrait, append the source object's projection bounds, and the *target* trait object's auto trait bounds, and make this into a new object type:
d12c6e947c/compiler/rustc_trait_selection/src/traits/select/confirmation.rs (L915-L929)
2. Then equate it with the target trait object:
d12c6e947c/compiler/rustc_trait_selection/src/traits/select/confirmation.rs (L936)
This will be a type mismatch if the target trait object has fewer projection bounds, since we compare the bounds structurally in relate:
d12c6e947c/compiler/rustc_middle/src/ty/relate.rs (L696-L698)
</details>
Fixes#114035
Also fixes#114113, because I added a normalize call in the old solver.
r? types
resolve before canonicalization in new solver, ICE if unresolved
Fold the values with a resolver before canonicalization instead of making it happen within canonicalization.
This allows us to filter trivial region constraints from the external constraints.
r? ``@lcnr``
Don't check unnecessarily that impl trait is RPIT
We have this random `return_type_impl_trait` function to detect if a function returns an RPIT which is used in outlives suggestions, but removing it doesn't actually change any diagnostics. Let's just remove it.
Also, suppress a spurious outlives error from a ReError.
Fixes#114274
Map RPITIT's opaque type bounds back from projections to opaques
An RPITIT in a program's AST is eventually translated into both a projection GAT and an opaque. The opaque is used for default trait methods, like:
```
trait Foo {
fn bar() -> impl Sized { 0i32 }
}
```
The item bounds for both the projection and opaque are identical, and both have a *projection* self ty. This is mostly okay, since we can normalize this projection within the default trait method body to the opaque, but it does two things:
1. it leads to bugs in places where we don't normalize item bounds, like `deduce_future_output_from_obligations`
2. it leads to extra match arms that are both suspicious looking and also easy to miss
This PR maps the opaque type bounds of the RPITIT's *opaque* back to the opaque's self type to avoid this quirk. Then we can fix the UI test for #108304 (1.) and also remove a bunch of match arms (2.).
Fixes#108304
r? `@spastorino`
Rollup of 7 pull requests
Successful merges:
- #114099 (privacy: no nominal visibility for assoc fns )
- #114128 (When flushing delayed span bugs, write to the ICE dump file even if it doesn't exist)
- #114138 (Adjust spans correctly for fn -> method suggestion)
- #114146 (Skip reporting item name when checking RPITIT GAT's associated type bounds hold)
- #114147 (Insert RPITITs that were shadowed by missing ADTs that resolve to [type error])
- #114155 (Replace a lazy `RefCell<Option<T>>` with `OnceCell<T>`)
- #114164 (Add regression test for `--cap-lints allow` and trait bounds warning)
r? `@ghost`
`@rustbot` modify labels: rollup
Skip reporting item name when checking RPITIT GAT's associated type bounds hold
Doesn't really make sense to label an item that has a name that users can't really mention. Fixes#114145. Also fixes#113794.
r? `@spastorino`
Introduce `trait DebugWithInfcx` to debug format types with universe info
Seeing universes of infer vars is valuable for debugging but currently we have no way of easily debug formatting a type with the universes of all the infer vars shown. In the future I hope to augment the new solver's proof tree output with a `DebugWithInfcx` impl so that it can show universes but I left that out of this PR as it would be non trivial and this is already large and complex enough.
The goal here is to make the various abstractions taking `T: Debug` able to use the codepath for printing out universes, that way we can do `debug!("{:?}", my_x)` and have `my_x` have universes shown, same for the `write!` macro. It's not possible to put the `Infcx: InferCtxtLike<I>` into the formatter argument to `Debug::fmt` so it has to go into the self ty. For this we introduce the type `OptWithInfcx<I: Interner, Infcx: InferCtxtLike<I>, T>` which has the data `T` optionally coupled with the infcx (more on why it's optional later).
Because of coherence/orphan rules it's not possible to write the impl `Debug for OptWithInfcx<..., MyType>` when `OptWithInfcx` is in a upstream crate. This necessitates a blanket impl in the crate defining `OptWithInfcx` like so: `impl<T: DebugWithInfcx> Debug for OptWithInfcx<..., T>`. It is not intended for people to manually call `DebugWithInfcx::fmt`, the `Debug` impl for `OptWithInfcx` should be preferred.
The infcx has to be optional in `OptWithInfcx` as otherwise we would end up with a large amount of code duplication. Almost all types that want to be used with `OptWithInfcx` do not themselves need access to the infcx so if we were to not optional we would end up with large `Debug` and `DebugWithInfcx` impls that were practically identical other than that when formatting their fields we wrap the field in `OptWithInfcx` instead of formatting it alone.
The only types that need access to the infcx themselves are ty/const/region infer vars, everything else is implemented by having the `Debug` impl defer to `OptWithInfcx` with no infcx available. The `DebugWithInfcx` impl is pretty much just the standard `Debug` impl except that instead of recursively formatting fields with `write!(f, "{x:?}")` we must do `write!(f, "{:?}", opt_infcx.wrap(x))`. This is some pretty rough boilerplate but I could not think of an alternative unfortunately.
`OptWithInfcx::wrap` is an eager `Option::map` because 99% of callsites were discarding the existing data in `OptWithInfcx` and did not need lazy evaluation.
A trait `InferCtxtLike` was added instead of using `InferCtxt<'tcx>` as we need to implement `DebugWithInfcx` for types living in `rustc_type_ir` which are generic over an interner and do not have access to `InferCtxt` since it lives in `rustc_infer`. Additionally I suspect that adding universe info to new solver proof tree output will require an implementation of `InferCtxtLike` for something that is not an `InferCtxt` although this is not the primary motivaton.
---
To summarize:
- There is a type `OptWithInfcx` which bundles some data optionally with an infcx with allows us to pass an infcx into a `Debug` impl. It's optional instead of being there unconditionally so that we can share code for `Debug` and `DebugWithInfcx` impls that don't care about whether there is an infcx available but have fields that might care.
- There is a trait `DebugWithInfcx` which allows downstream crates to add impls of the form `Debug for OptWithInfcx<...>` which would normally be forbidden by orphan rules/coherence.
- There is a trait `InferCtxtLike` to allow us to implement `DebugWithInfcx` for types that live in `rustc_type_ir`
This allows debug formatting various `ty::*` structures with universes shown by using the `Debug` impl for `OptWithInfcx::new(ty, infcx)`
---
This PR does not add `DebugWithInfcx` impls to absolutely _everything_ that should realistically have them, for example you cannot use `OptWithInfcx<Obligation<Predicate>>`. I am leaving this to a future PR to do so as it would likely be a lot more work to do.
Rollup of 8 pull requests
Successful merges:
- #113413 (Add needs-triage to all new issues)
- #113426 (Don't ICE in `resolve_bound_vars` when associated return-type bounds are in bad positions)
- #113427 (Remove `variances_of` on RPITIT GATs, remove its one use-case)
- #113441 (miri: check that assignments do not self-overlap)
- #113453 (Remove unused from_method from rustc_on_unimplemented)
- #113456 (Avoid calling report_forbidden_specialization for RPITITs)
- #113466 (Update cargo)
- #113467 (Fix comment of `fn_can_unwind`)
r? `@ghost`
`@rustbot` modify labels: rollup
Remove `variances_of` on RPITIT GATs, remove its one use-case
It doesn't make sense to implement variances on a GAT anyways, since we don't relate GATs with variance:
85bf07972a/compiler/rustc_middle/src/ty/relate.rs (L569-L579)
r? ``@spastorino``
Split `SelectionContext::select` into fns that take a binder and don't
*most* usages of `SelectionContext::select` don't need to use a binder, but wrap them in a dummy because of the signature. Let's split this out into `SelectionContext::{select,poly_select}` and limit the usages of the latter.
Right now, we only have 3 places where we're calling `poly_select` -- fulfillment, internally within the old solver, and the auto-trait finder.
r? `@lcnr`
`TypeParameterDefinition` always require a `DefId`
the `None` case never actually reaches diagnostics so it feels better for diagnostics to be able to rely on the `DefId` being there, cc #113310
Remove chalk support from the compiler
Removes chalk (`-Ztrait-solver=chalk`) from the compiler and prunes any dead code resulting from this, mainly:
* Remove the chalk compatibility layer in `compiler/rustc_traits/src/chalk`
* Remove the chalk flag `-Ztrait-solver=chalk` and its `TraitEngine` implementation
* Remove `TypeWellFormedFromEnv` (and its many `bug!()` match arms)
* Remove the chalk migration mode from compiletest
* Remove the `chalkify` UI tests (do we want to keep any of these, but migrate them to `-Ztrait-solver=next`??)
Fulfills rust-lang/types-team#93.
r? `@jackh726`
Make RPITITs assume/require their parent method's predicates
Removes a FIXME from the `param_env` query where we were manually adding the parent function's predicates to the RPITIT's assumptions.
r? `@spastorino`
[-Ztrait-solver=next, mir-typeck] instantiate hidden types in the root universe
Fixes an ICE in the test `member-constraints-in-root-universe`.
Main motivation is to make #112691 pass under the new solver.
r? ``@compiler-errors``
Various impl trait in assoc tys cleanups
r? `@compiler-errors`
All commits except for the last are pure refactorings. 274dab5bd658c97886a8987340bf50ae57900c39 allows struct fields to participate in deciding whether a function has an opaque in its signature.
best reviewed commit by commit
Add a fully fledged `Clause` type, rename old `Clause` to `ClauseKind`
Does two basic things before I put up a more delicate set of PRs (along the lines of #112714, but hopefully much cleaner) that migrate existing usages of `ty::Predicate` to `ty::Clause` (`predicates_of`/`item_bounds`/`ParamEnv::caller_bounds`).
1. Rename `Clause` to `ClauseKind`, so it's parallel with `PredicateKind`.
2. Add a new `Clause` type which is parallel to `Predicate`.
* This type exposes `Clause::kind(self) -> Binder<'tcx, ClauseKind<'tcx>>` which is parallel to `Predicate::kind` 😸
The new `Clause` type essentially acts as a newtype wrapper around `Predicate` that asserts that it is specifically a `PredicateKind::Clause`. Turns out from experimentation[^1] that this is not negative performance-wise, which is wonderful, since this a much simpler design than something that requires encoding the discriminant into the alignment bits of a predicate kind, or something else like that...
r? ``@lcnr`` or ``@oli-obk``
[^1]: https://github.com/rust-lang/rust/pull/112714#issuecomment-1595653910
Don't consider TAIT normalizable to hidden ty if it would result in impossible item bounds
See test for example where we shouldn't consider it possible to alias-relate a TAIT and hidden type.
r? `@lcnr`
Dont compute `opt_suggest_box_span` span for TAIT
Fixes#112434
Also a couple more commits on top, pruning some dead code and fixing another weird suggestion encountered in the above issue.
Add `-Ztrait-solver=next-coherence`
Flag that conditionally uses the trait solver *only* during coherence, for more testing and/or eventual partial-migration onto the trait solver (in the medium- to long-term).
* This still uses the selection context in some of the coherence methods I think, so it's not "complete". Putting this up for review and/or for further work in-tree.
* I probably need to spend a bit more time making sure that we don't sneakily create any other infcx's during coherence that also need the new solver enabled.
r? `@lcnr`
Emit an error when return-type-notation is used with type/const params
These are not intended to be supported initially, even though the compiler supports them internally...
we can otherwise assign a hidden type to the opaque which
causes ICE if we don't use `take_opaque_types` during
coherence. This is annoying so I didn't bother. Added a test
showing the behavior this prevents.
Each of `{D,Subd}iagnosticMessage::{Str,Eager}` has a comment:
```
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
```
This commit answers that question in the affirmative. It's not the most
compelling change ever, but it might be worth merging.
This requires changing the `impl<'a> From<&'a str>` impls to `impl
From<&'static str>`, which involves a bunch of knock-on changes that
require/result in call sites being a little more precise about exactly
what kind of string they use to create errors, and not just `&str`. This
will result in fewer unnecessary allocations, though this will not have
any notable perf effects given that these are error paths.
Note that I was lazy within Clippy, using `to_string` in a few places to
preserve the existing string imprecision. I could have used `impl
Into<{D,Subd}iagnosticMessage>` in various places as is done in the
compiler, but that would have required changes to *many* call sites
(mostly changing `&format("...")` to `format!("...")`) which didn't seem
worthwhile.
Suppress "erroneous constant used" for constants tainted by errors
When constant evaluation fails because its MIR is tainted by errors,
suppress note indicating that erroneous constant was used, since those
errors have to be fixed regardless of the constant being used or not.
Fixes#110891.
Rename const error methods for consistency
renames `ty::Const`'s methods for creating a `ConstKind::Error` to be in the same naming style as `ty::Ty`'s equivalent methods.
r? `@BoxyUwU`
When constant evaluation fails because its MIR is tainted by errors,
suppress note indicating that erroneous constant was used, since those
errors have to be fixed regardless of the constant being used or not.
Require impl Trait in associated types to appear in method signatures
This implements the limited version of TAIT that was proposed in https://github.com/rust-lang/rust/issues/107645#issuecomment-1477899536
Similar to `impl Trait` in return types, `impl Trait` in associated types may only be used within the impl block which it is a part of. To make everything simpler and forward compatible to getting desugared to a plain type alias impl trait in the future, we're requiring that any associated functions or constants that want to register hidden types must be using the associated type in their signature (type of the constant or argument/return type of the associated method. Where bounds mentioning the associated type are ignored).
We have preexisting tests checking that this works transitively across multiple associated types in situations like
```rust
impl Foo for Bar {
type A = impl Trait;
type B = impl Iterator<Item = Self::A>;
fn foo() -> Self::B { ...... }
}
```
Uplift `clippy::{drop,forget}_{ref,copy}` lints
This PR aims at uplifting the `clippy::drop_ref`, `clippy::drop_copy`, `clippy::forget_ref` and `clippy::forget_copy` lints.
Those lints are/were declared in the correctness category of clippy because they lint on useless and most probably is not what the developer wanted.
## `drop_ref` and `forget_ref`
The `drop_ref` and `forget_ref` lint checks for calls to `std::mem::drop` or `std::mem::forget` with a reference instead of an owned value.
### Example
```rust
let mut lock_guard = mutex.lock();
std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex
// still locked
operation_that_requires_mutex_to_be_unlocked();
```
### Explanation
Calling `drop` or `forget` on a reference will only drop the reference itself, which is a no-op. It will not call the `drop` or `forget` method on the underlying referenced value, which is likely what was intended.
## `drop_copy` and `forget_copy`
The `drop_copy` and `forget_copy` lint checks for calls to `std::mem::forget` or `std::mem::drop` with a value that derives the Copy trait.
### Example
```rust
let x: i32 = 42; // i32 implements Copy
std::mem::forget(x) // A copy of x is passed to the function, leaving the
// original unaffected
```
### Explanation
Calling `std::mem::forget` [does nothing for types that implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the value will be copied and moved into the function on invocation.
-----
Followed the instructions for uplift a clippy describe here: https://github.com/rust-lang/rust/pull/99696#pullrequestreview-1134072751
cc `@m-ou-se` (as T-libs-api leader because the uplifting was discussed in a recent meeting)
Introduce `AliasKind::Inherent` for inherent associated types
Allows us to check (possibly generic) inherent associated types for well-formedness.
Type inference now also works properly.
Follow-up to #105961. Supersedes #108430.
Fixes#106722.
Fixes#108957.
Fixes#109768.
Fixes#109789.
Fixes#109790.
~Not to be merged before #108860 (`AliasKind::Weak`).~
CC `@jackh726`
r? `@compiler-errors`
`@rustbot` label T-types F-inherent_associated_types
enable `rust_2018_idioms` lint group for doctests
With this change, `rust_2018_idioms` lint group will be enabled for compiler/libstd doctests.
Resolves#106086Resolves#99144
Signed-off-by: ozkanonur <work@onurozkan.dev>
Support return-type bounds on associated methods from supertraits
Support `T: Trait<method(): Bound>` when `method` comes from a supertrait, aligning it with the behavior of associated type bounds (both equality and trait bounds).
The only wrinkle is that I have to extend `super_predicates_that_define_assoc_type` to look for *all* items, not just `AssocKind::Ty`. This will also be needed to support `feature(associated_const_equality)` as well, which is subtly broken when it comes to supertraits, though this PR does not fix those yet. There's a slight chance there's a perf regression here, in which case I guess I could split it out into a separate query.
Use fulfillment to check `Drop` impl compatibility
Use an `ObligationCtxt` to ensure that a `Drop` impl does not have stricter requirements than the ADT that it's implemented for, rather than using a `SimpleEqRelation` to (more or less) syntactically equate predicates on an ADT with predicates on an impl.
r? types
### Some background
The old code reads:
```rust
// An earlier version of this code attempted to do this checking
// via the traits::fulfill machinery. However, it ran into trouble
// since the fulfill machinery merely turns outlives-predicates
// 'a:'b and T:'b into region inference constraints. It is simpler
// just to look for all the predicates directly.
```
I'm not sure what this means, but perhaps in the 8 years since that this comment was written (cc #23638) it's gotten easier to process region constraints after doing fulfillment? I don't know how this logic differs from anything we do in the `compare_impl_item` module. Ironically, later on it says:
```rust
// However, it may be more efficient in the future to batch
// the analysis together via the fulfill (see comment above regarding
// the usage of the fulfill machinery), rather than the
// repeated `.iter().any(..)` calls.
```
Also:
* Removes `SimpleEqRelation` which was far too syntactical in its relation.
* Fixes#110557
Implement negative bounds for internal testing purposes
Implements partial support the `!` negative polarity on trait bounds. This is incomplete, but should allow us to at least be able to play with the feature.
Not even gonna consider them as a public-facing feature, but I'm implementing them because would've been nice to have in UI tests, for example in #110671.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
Switch to `EarlyBinder` for `explicit_item_bounds`
Part of the work to finish https://github.com/rust-lang/rust/issues/105779.
This PR adds `EarlyBinder` to the return type of the `explicit_item_bounds` query and removes `bound_explicit_item_bounds`.
r? `@compiler-errors` (hope it's okay to request you, since you reviewed #110299 and #110498😃)
Break up long function in trait selection error reporting + clean up nearby code
- Move blocks of code into their own functions
- Replace a few function argument types with their type aliases
- Create "AppendConstMessage" enum to replace a nested `Option`.