RPIT allows defining use with invalid args · Issue #111935 · rust-lang/rust (original) (raw)

Note: All examples in this post was fixed in #112842. However the issue persists for lifetime arguments. See this comment for more.


The following compiles since v1.62:

fn foo() -> impl Sized { let _: () = foo::(); }

While the equivalent TAIT version doesn't compile because Opaque<u8> == u8 is not a valid defining use for Opaque (because it is ambiguous whether Opaque<T> = T or Opaque<T> = u8):

#![feature(type_alias_impl_trait)]

type Opaque = impl Sized; fn foo() -> Opaque { let _: () = foo::(); //~^ ERROR expected generic type parameter, found u8 }

I believe that TAIT behavior is the correct one because it's maximally compatible with future changes. Keeping this behavior for RPIT can also result in some surprising errors:

fn foo(val: T) -> impl Sized { let _: u8 = foo(0u8); val //~^ ERROR concrete type differs from previous defining opaque type use }

This was stabilized (most likely unintentionally) in #94081. Cc @oli-obk.

See related code:

fn check_opaque_type_parameter_valid(