Auto merge of #107507 - BoxyUwU:deferred_projection_equality, r=lcnr

Implement `deferred_projection_equality` for erica solver

Somewhat of a revival of #96912. When relating projections now emit an `AliasEq` obligation instead of attempting to determine equality of projections that may not be as normalized as possible (i.e. because of lazy norm, or just containing inference variables that prevent us from resolving an impl). Only do this when the new solver is enabled
This commit is contained in:
bors 2023-02-11 05:46:24 +00:00
commit 1623ab0246
46 changed files with 585 additions and 163 deletions

View file

@ -0,0 +1,29 @@
// check-pass
// compile-flags: -Ztrait-solver=next
// check that a goal such as `alias-eq(<T as TraitB>::Assoc<bool>, <T as TraitB>::Assoc<?0>)`
// succeeds with a constraint that `?0 = bool`
// FIXME(deferred_projection_equality): add a test that this is true during coherence
trait TraitA {}
trait TraitB {
type Assoc<T: ?Sized>;
}
impl<T: TraitB> TraitA for (T, T::Assoc<bool>) {}
impl TraitB for i32 {
type Assoc<T: ?Sized> = u32;
}
fn needs_a<T: TraitA>() {}
fn bar<T: TraitB>() {
needs_a::<(T, <T as TraitB>::Assoc<_>)>();
}
fn main() {
bar::<i32>();
}

View file

@ -0,0 +1,45 @@
// compile-flags: -Ztrait-solver=next
// check that when computing `alias-eq(<() as Foo<u16, T>>::Assoc, <() as Foo<?0, T>>::Assoc)`
// we do not infer `?0 = u8` via the `for<STOP> (): Foo<u8, STOP>` impl or `?0 = u16` by
// relating substs as either could be a valid solution.
trait Foo<T, STOP> {
type Assoc;
}
impl<STOP> Foo<u8, STOP> for ()
where
(): Foo<u16, STOP>,
{
type Assoc = <() as Foo<u16, STOP>>::Assoc;
}
impl Foo<u16, i8> for () {
type Assoc = u8;
}
impl Foo<u16, i16> for () {
type Assoc = u16;
}
fn output<T, U>() -> <() as Foo<T, U>>::Assoc
where
(): Foo<T, U>,
{
todo!()
}
fn incomplete<T>()
where
(): Foo<u16, T>,
{
// `<() as Foo<u16, STOP>>::Assoc == <() as Foo<_, STOP>>::Assoc`
let _: <() as Foo<u16, T>>::Assoc = output::<_, T>();
//~^ error: type annotations needed
// let _: <() as Foo<u16, T>>::Assoc = output::<u8, T>(); // OK
// let _: <() as Foo<u16, T>>::Assoc = output::<u16, T>(); // OK
}
fn main() {}

View file

@ -0,0 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/alias_eq_dont_use_normalizes_to_if_substs_eq.rs:38:41
|
LL | let _: <() as Foo<u16, T>>::Assoc = output::<_, T>();
| ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `output`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.

View file

@ -0,0 +1,22 @@
// check-pass
// compile-flags: -Ztrait-solver=next
// test that the new solver can handle `alias-eq(<i32 as TraitB>::Assoc, u32)`
trait TraitA {}
trait TraitB {
type Assoc;
}
impl<T: TraitB> TraitA for (T, T::Assoc) {}
impl TraitB for i32 {
type Assoc = u32;
}
fn needs_a<T: TraitA>() {}
fn main() {
needs_a::<(i32, u32)>();
}

View file

@ -0,0 +1,20 @@
// compile-flags: -Ztrait-solver=next
// check that a `alias-eq(<?0 as TraitB>::Assoc, <T as TraitB>::Assoc)` goal fails.
// FIXME(deferred_projection_equality): add a test that this is true during coherence
trait TraitB {
type Assoc;
}
fn needs_a<T: TraitB>() -> T::Assoc {
unimplemented!()
}
fn bar<T: TraitB>() {
let _: <_ as TraitB>::Assoc = needs_a::<T>();
//~^ error: type annotations needed
}
fn main() {}

View file

@ -0,0 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/alias_eq_substs_eq_not_intercrate.rs:16:12
|
LL | let _: <_ as TraitB>::Assoc = needs_a::<T>();
| ^^^^^^^^^^^^^^^^^^^^ cannot infer type for associated type `<_ as TraitB>::Assoc`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.

View file

@ -0,0 +1,40 @@
// [no_self_infer] check-pass
// compile-flags: -Ztrait-solver=next
// revisions: self_infer no_self_infer
// checks that the new solver is smart enough to infer `?0 = U` when solving:
// `normalizes-to(<Vec<?0> as Trait>::Assoc, u8)`
// with `normalizes-to(<Vec<U> as Trait>::Assoc, u8)` in the paramenv even when
// there is a separate `Vec<T>: Trait` bound in the paramenv.
//
// FIXME(-Ztrait-solver=next)
// This could also compile for `normalizes-to(<?0 as Trait>::Assoc, u8)` but
// we currently immediately consider a goal ambiguous if the self type is an
// inference variable.
trait Trait {
type Assoc;
}
fn foo<T: Trait<Assoc = u8>>(x: T) {}
#[cfg(self_infer)]
fn unconstrained<T>() -> T {
todo!()
}
#[cfg(no_self_infer)]
fn unconstrained<T>() -> Vec<T> {
todo!()
}
fn bar<T, U>()
where
Vec<T>: Trait,
Vec<U>: Trait<Assoc = u8>,
{
foo(unconstrained())
//[self_infer]~^ ERROR type annotations needed
}
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0282]: type annotations needed
--> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:36:5
|
LL | foo(unconstrained())
| ^^^ cannot infer type of the type parameter `T` declared on the function `foo`
|
help: consider specifying the generic argument
|
LL | foo::<T>(unconstrained())
| +++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.