TAIT defining uses may not be fully general due to additional where-bounds
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Consider the following two examples:
#![feature(type_alias_impl_trait)]
trait Trait {
type Assoc;
}
type Tait<T: Trait> = impl Sized;
#[define_opaque(Tait)]
fn foo<T: Trait<Assoc = u32>, U: Trait<Assoc = i32>>() {
let _: Tait<T> = 1u32;
let _: Tait<U> = 1i32;
}
error: concrete type differs from previous defining opaque type use
--> src/lib.rs:9:22
|
9 | let _: Tait<U> = 1i32;
| ^^^^ expected `u32`, got `i32`
|
note: previous use here
--> src/lib.rs:8:22
|
8 | let _: Tait<T> = 1u32;
| ^^^^
#![feature(type_alias_impl_trait)]
trait Trait {
type Assoc;
}
trait IsAssoc<T> {}
impl<T: Trait> IsAssoc<T::Assoc> for T {}
struct ReqAssoc<T: Trait + IsAssoc<U>, U = <T as Trait>::Assoc> {
field: Option<(T, U)>,
}
type Tait<T: Trait> = impl Sized;
#[define_opaque(Tait)]
fn define<T: Trait<Assoc = u32>>() -> Tait<T> {
ReqAssoc::<T> { field: None }
}
error[E0271]: type mismatch resolving `<T as Trait>::Assoc == u32`
--> src/lib.rs:15:5
|
15 | ReqAssoc::<T> { field: None }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type
|
= note: expected type `u32`
found associated type `<T as Trait>::Assoc`
= help: consider constraining the associated type `<T as Trait>::Assoc` to `u32`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
note: required by a bound in `ReqAssoc`
--> src/lib.rs:9:28
|
9 | struct ReqAssoc<T: Trait + IsAssoc<U>, U = <T as Trait>::Assoc> {
| ^^^^^^^^^^ required by this bound in `ReqAssoc`
This happens because a fully general use of an opaque type - what we require for a use to be defining - may not actually be fully general if one were to explicitly track dictionaries/where-bounds.
In the first example one could imagine the Tait as an fn tait(T: Type, trait_dict: Trait (t)) -> Type. In this example the defining use Tait<T> is actually tait(T, Trait { assoc: u32 }) = u32. While it takes a variable for T, the trait dictionary actually contains relevant information about the associated type. This means there are now multiple valid function bodies for which the constraint tait(T, Trait { assoc: u32 }) = u32 holds:
type Tait<T: Trait> = T::Assoctype Tait<T: Trait> = u32type Tait<T: Trait> = SomeEntirelyDifferentAliasType<T::Assoc>
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce both examples in src/lib.rs with the type_alias_impl_trait and define_opaque features enabled. Start by tracing how fully general defining uses and associated-type where-bounds are handled, then compare the observed behavior with the intended opaque-type rules. Done means establishing the correct semantics and implementing or documenting a resolution for these cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100