| Age | Commit message (Collapse) | Author | Lines |
|
|
|
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
|
|
proof tree nits
r? `@BoxyUwU`
|
|
|
|
|
|
|
|
Add `implement_via_object` to `rustc_deny_explicit_impl` to control object candidate assembly
Some built-in traits are special, since they are used to prove facts about the program that are important for later phases of compilation such as codegen and CTFE. For example, the `Unsize` trait is used to assert to the compiler that we are able to unsize a type into another type. It doesn't have any methods because it doesn't actually *instruct* the compiler how to do this unsizing, but this is later used (alongside an exhaustive match of combinations of unsizeable types) during codegen to generate unsize coercion code.
Due to this, these built-in traits are incompatible with the type erasure provided by object types. For example, the existence of `dyn Unsize<T>` does not mean that the compiler is able to unsize `Box<dyn Unsize<T>>` into `Box<T>`, since `Unsize` is a *witness* to the fact that a type can be unsized, and it doesn't actually encode that unsizing operation in its vtable as mentioned above.
The old trait solver gets around this fact by having complex control flow that never considers object bounds for certain built-in traits:
https://github.com/rust-lang/rust/blob/2f896da247e0ee8f0bef7cd7c54cfbea255b9f68/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs#L61-L132
However, candidate assembly in the new solver is much more lovely, and I'd hate to add this list of opt-out cases into the new solver. Instead of maintaining this complex and hard-coded control flow, instead we can make this a property of the trait via a built-in attribute. We already have such a build attribute that's applied to every single trait that we care about: `rustc_deny_explicit_impl`. This PR adds `implement_via_object` as a meta-item to that attribute that allows us to opt a trait out of object-bound candidate assembly as well.
r? `@lcnr`
|
|
|
|
|
|
|
|
impossible item bounds
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Add `AliasKind::Weak` for type aliases.
`type Foo<T: Debug> = Bar<T>;` does not check `T: Debug` at use sites of `Foo<NotDebug>`, because in contrast to a
```rust
trait Identity {
type Identity;
}
impl<T: Debug> Identity for T {
type Identity = T;
}
<NotDebug as Identity>::Identity
```
type aliases do not exist in the type system, but are expanded to their aliased type immediately when going from HIR to the type layer.
Similarly:
* a private type alias for a public type is a completely fine thing, even though it makes it a bit hard to write out complex times sometimes
* rustdoc expands the type alias, even though often times users use them for documentation purposes
* diagnostics show the expanded type, which is confusing if the user wrote a type alias and the diagnostic talks about another type that they don't know about.
For type alias impl trait, these issues do not actually apply in most cases, but sometimes you have a type alias impl trait like `type Foo<T: Debug> = (impl Debug, Bar<T>);`, which only really checks it for `impl Debug`, but by accident prevents `Bar<T>` from only being instantiated after proving `T: Debug`. This PR makes sure that we always check these bounds explicitly and don't rely on an implementation accident.
To not break all the type aliases out there, we only use it when the type alias contains an opaque type. We can decide to do this for all type aliases over an edition.
Or we can later extend this to more types if we figure out the back-compat concerns with suddenly checking such bounds.
As a side effect, easily allows fixing https://github.com/rust-lang/rust/issues/108617, which I did.
fixes https://github.com/rust-lang/rust/issues/108617
|
|
Make assumption functions in new solver take `Binder<'tcx, Clause<'tcx>>`
We just use an if-let to match on an optional clause at all the places where we transition from `Predicate` -> `Clause`, but I assume that when things like item-bounds and param-env start to only store `Clause`s then those can just be trivially dropped.
r? ``@lcnr``
|
|
Only use it when the type alias contains an opaque type.
Also does wf-checking on such type aliases.
|
|
compiler-errors:next-solver-opportunistically-resolve-regions, r=lcnr
Opportunistically resolve regions in new solver
Use `opportunistic_resolve_var` during canonicalization to collapse some regions.
We have to start using `CanonicalVarValues::is_identity_modulo_regions`. We also have to modify that function to consider responses like `['static, ^0, '^1, ^2]` to be an "identity" response, since because we opportunistically resolve regions, there's no longer a 1:1 mapping between canonical var values and bound var indices in the response...
There's one nasty side-effect -- one test (`tests/ui/dyn-star/param-env-infer.rs`) starts to ICE because the certainty goes from `Yes` to `Maybe(Overflow)`... Not exactly sure why, though? Putting this up for discussion/investigation.
r? ```@lcnr```
|
|
|
|
r=compiler-errors
Safe Transmute: Enable handling references
This patch enables support for references in Safe Transmute, by generating nested obligations during trait selection. Specifically, when we call `confirm_transmutability_candidate(...)`, we now recursively traverse the `rustc_transmute::Answer` tree and create obligations for all the `Answer` variants, some of which include multiple nested `Answer`s.
|
|
|
|
- Create `Answer` type that is not just a type alias of `Result`
- Remove a usage of `map_layouts` to make the code easier to read
- Don't hide errors related to Unknown Layout when computing transmutability
|
|
|
|
opaque type cleanup
the commits are pretty self-contained.
r? `@compiler-errors` cc `@oli-obk`
|
|
be more explicit in where we only add new hidden types
and where we also have to deal with item bounds.
|
|
|
|
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`
|
|
|
|
|
|
|
|
Don't ICE in new solver when auto traits have associated types
People can write malformed auto traits, and that shouldn't cause the new solver to ICE
|
|
don't partially support const projection for impls
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|