## Candidate selection can define opaques
the following compiles defining `Op = u8`:
```rust
#![feature(type_alias_impl_trait)]
type Op = impl Sized;
trait Trait {}
impl Trait for Box<u8> {}
fn impl_trait<T: Trait>() {}
fn test() -> Option<Op> {
impl_trait::<Box<Op>>;
None
}
```
another one:
```rust
#![feature(type_alias_impl_trait)]
trait Equate {}
impl<T: Sized> Equate for (T, T) {}
fn equate<X: Equate>() {}
type Op = impl Sized;
fn test(p: Op) {
let _: u8 = p;
equate::<(Op, u8)>;
}
```
## Selection is aware of hidden types
We normalize the opaque to the hidden type during selection if we're in a defining scope. The following passes typeck but ICEs mir-typeck because we don't populate the hidden types from typeck in mir-typeck early enough. More specifically, `check_user_type_annnotations` is called before we register the hidden types.
```rust
#![feature(type_alias_impl_trait)]
type Op = impl Sized;
trait Trait {}
impl Trait for u16 {}
impl Trait for u32 {}
fn impl_trait<T: Trait>() {}
fn test() -> Op {
impl_trait::<Op>;
0u32
}
```
## Normalize Self in a non-defining function
This fails with an ambiguity rather than a hard error. With the goal `Op: Trait`, `Op` is normalized to a fresh inference variable because we're inside a defining scope for `Op` but the hidden type will never be constrained in the function body.
```rust
#![feature(type_alias_impl_trait)]
trait Trait {}
impl Trait for () {}
type Op = impl Sized;
fn get() -> Op {}
fn impl_trait<T: Trait>() {}
fn test() -> Op {
impl_trait::<Op>;
//~^ ERROR type annotations needed: cannot satisfy `Op: Trait`
get()
}
```
## Inference order-dependence
Given `?0 = u8 && ?0 = impl Sized`, does `?0: Copy` hold? The old behviour is order-dependent.
This is not an issue in the new solver but it would be if we were to remove the lazy normalization of opaques.
```rust
#![feature(type_alias_impl_trait)]
type Opaque = impl Sized;
fn is_copy<T: Copy>(_: T, _: T) {}
fn test(p: Opaque) {
is_copy(p, 0u8); // FAIL!
is_copy(0u8, p); // PASS!
}
```