Optimize canonicalizer flag checks.
The most important change here relates to type folding: we now check the flags up front, instead of doing it in `inner_fold_ty` after checking the cache and doing a match. This is a small perf win, and matches other similar folders (e.g. `CanonicalInstantiator`).
Likewise for const folding, we now check the flags first. (There is no cache for const folding.)
Elsewhere we don't check flags before folding a predicate (unnecessary, because `fold_predicate` already checks the flags itself before doing anything else), and invert the flag checks in a couple of methods to match the standard order.
r? @lcnr
- Remove the vacuous `Types`, which provides extremely little value.
- Make sure `src` comes before `dst` in all transmute-related functions.
(Currently it's a mix: sometimes `src` is first, sometimes it is
second`.)
The most important change here relates to type folding: we now check the
flags up front, instead of doing it in `inner_fold_ty` after checking
the cache and doing a match. This is a small perf win, and matches other
similar folders (e.g. `CanonicalInstantiator`).
Likewise for const folding, we now check the flags first. (There is no
cache for const folding.)
Elsewhere we don't check flags before folding a predicate (unnecessary,
because `fold_predicate` already checks the flags itself before doing
anything else), and invert the flag checks in a couple of methods to
match the standard order.
Currently it's a mutable reference, but it doesn't need to be, because
what's passed in is always a mutable reference to an empty `Vec`. This
requires returning variables in a few extra places, which is fine. It
makes the handling of `variables` the same as the handling of
`var_kinds` and `variable_lookup_table`.
Variables that are collections of `CanonicalVarKind` are sometimes
called `var_kinds` and sometimes called `variables`. The former is much
better, because `variables` is (a) non-descript, and (b) often used
nearby for collections of `I::GenericArg`. I found the inconsistency
made the canonicalization code harder to understand.
This commit renames various `variables` things as `var_kinds`.
This removes `associated_const_equality` as a separate feature gate and makes it part of `min_generic_const_args` (mgca).
Key changes:
- Remove `associated_const_equality` from unstable features, add to removed
- Update all test files to use `min_generic_const_args` instead
- Preserve the original "associated const equality is incomplete" error message by specially handling `sym::associated_const_equality` spans in `feature_gate.rs`
- Rename FIXME(associated_const_equality) to FIXME(mgca)
Deny const auto traits
closerust-lang/rust#149285
The AST validation now detects and rejects const auto traits. Additionally, I updated an existing test that was using `const unsafe auto trait`.
r? fmease
mgca: Add ConstArg representation for const items
tracking issue: rust-lang/rust#132980fixesrust-lang/rust#131046fixesrust-lang/rust#134641
As part of implementing `min_generic_const_args`, we need to distinguish const items that can be used in the type system, such as in associated const equality projections, from const items containing arbitrary const code, which must be kept out of the type system. Specifically, all "type consts" must be either concrete (no generics) or generic with a trivial expression like `N` or a path to another type const item.
To syntactically distinguish these cases, we require, for now at least, that users annotate all type consts with the `#[type_const]` attribute. Then, we validate that the const's right-hand side is indeed eligible to be a type const and represent it differently in the HIR.
We accomplish this representation using a new `ConstItemRhs` enum in the HIR, and a similar but simpler enum in the AST. When `#[type_const]` is **not** applied to a const (e.g. on stable), we represent const item right-hand sides (rhs's) as HIR bodies, like before. However, when the attribute is applied, we instead lower to a `hir::ConstArg`. This syntactically distinguishes between trivial const args (paths) and arbitrary expressions, which are represented using `AnonConst`s. Then in `generics_of`, we can take advantage of the existing machinery to bar the `AnonConst` rhs's from using parent generics.
Constify trait aliases
Allow `const trait Foo = Bar + [const] Baz;` trait alias declarations. Their rules are the same as with super traits of const traits. So `[const] Baz` or `const Baz` is only required for `[const] Foo` or `const Foo` bounds respectively.
tracking issue rust-lang/rust#41517 (part of the general trait alias feature gate, but I can split it out into a separate const trait alias feature gate. I just assumed that const traits would stabilize before trait aliases, and we'd want to stabilize trait aliases together with const trait aliases at the same time)
r? ``@compiler-errors`` ``@fee1-dead``
`-Znext-solver` instantiate predicate binder without recanonicalizing goal
This strengthens the leak check to match the old trait solver. The new trait solver now also instantiates higher ranked goals in the same scope as candidate selection, so the leak check in each candidate detects placeholder errors involving this higher ranked goal.
E.g. let's look at tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs
```rust
trait Trait<T, U> {}
impl<'a> Trait<&'a str, &'a str> for () {}
impl<'a> Trait<&'a str, String> for () {}
fn impls_trait<T: for<'a> Trait<&'a str, U>, U>() {}
fn main() {
impls_trait::<(), _>();
}
```
Here proving `(): for<'a> Trait<&'a str, ?u>` via `impl<'a> Trait<&'a str, &'a str> for ()` equates `?u` with `&'!a str` which results in a leak check error as `?u` cannot name `'a`. If this leak check error happens while considering candidates we drop the first impl and infer `?u` to `String`. If not, this remains ambiguous.
This behavior is a bit iffy, see the FCP proposal in rust-lang/rust#119820 for more details on why this current behavior is somewhat undesirable. However, considering placeholders from higher-ranked goals for candidate selection does allow more code to compile and a lot of the code *feels like it should compile*. **This caused us to revert the change of rust-lang/rust#119820 in rust-lang/rust#127568.**
I originally expected that we can avoid breakage with the new solver differently here, e.g. by considering OR-region constraints. However, doing so is a significant change and I don't have a great idea for how that should work. Matching the old solver behavior for now should not make this cleaner approach any more difficult in the future, so let's just go with what actually allows us to stabilize the new solver for now.
This PR changing the new solver to match the behavior of the old one wrt the leak check. As the new solver is already used by default in coherence, this allows more code to compile, see `tests/ui/higher-ranked/leak-check/leak-check-in-selection-7-coherence.rs`:
```rust
struct W<T, U>(T, U);
trait Trait<T> {}
// using this impl results in a higher-ranked region error.
impl<'a> Trait<W<&'a str, &'a str>> for () {}
impl<'a> Trait<W<&'a str, String>> for () {}
trait NotString {}
impl NotString for &str {}
impl NotString for u32 {}
trait Overlap<U> {}
impl<T: for<'a> Trait<W<&'a str, U>>, U> Overlap<U> for T {}
impl<U: NotString> Overlap<U> for () {}
fn main() {}
```
This behavior is quite arbitrary and not something I expect users to rely on in practice, however, it should still go through an FCP imo.
r? `@BoxyUwU` originally implemented by `@compiler-errors` in https://github.com/rust-lang/rust/pull/136997. Closes https://github.com/rust-lang/trait-system-refactor-initiative/issues/120.
For sizedness, default and auto trait predicates, now prefer non-param
candidates if any exist. As these traits do not have generic parameters,
it never makes sense to prefer an non-alias candidate, as there can
never be a more permissive candidate.
fix 2 search graph bugs
wooooooooops, i should really run the fuzzer even when not changing the structure of the search graph as a whole :3 fixes the `ml-kem` ICE in the next-solver crater run
r? ````@BoxyUwU````
fix rebasing cycle heads when not reaching a fixpoint
fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/232
annoyingly subtle, imagine the following proof tree
- A (no cycle head usages, final result Y)
- *ignored* B (depends on A with provisional result X)
- A (cycle, provisional result X)
- B (using the cache entry here incorrectly assumes A has final result X)
r? ``@BoxyUwU``