rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.25k stars 12.57k forks source link

Invalid inference in associated types #116613

Open jflatow opened 11 months ago

jflatow commented 11 months ago

I tried this code:

pub trait Po: Sized {
    type A: MA<Self>;
}

pub trait MA<P: Po>: Sized {}

pub trait Mr<P: Po>: Sized {
    type As: IntoIterator<Item = P::A>; // shouldn't be necessary?

    fn a(&self) -> Self::As; // impl IntoIterator<Item = P::A>;
}

pub trait BM<'a, P: Po<A = BMA<'a, P, Self>>>: Mr<P> + 'a {}

pub enum BMA<'a, P: Po<A = Self>, M: BM<'a, P>> {
    V(&'a M, P),
}

impl<'a, P: Po<A = Self>, M: BM<'a, P>> MA<P> for BMA<'a, P, M> {}

impl<'a, P: Po<A = BMA<'a, P, M>>, M: BM<'a, P>> Mr<P> for M {
    type As = Vec<P::A>; // shouldn't be necessary?

    fn a(&self) -> Self::As { // impl IntoIterator<Item = P::A> {
        Vec::<P::A>::new()
    }
}

I expected to see this compile.

Instead, I got the following error:

error[E0308]: mismatched types
  --> impltrait.rs:25:9
   |
24 |     fn a(&self) -> Self::As { // impl IntoIterator<Item = P::A> {
   |                    -------- expected `<M as Mr<P>>::As` because of return type
25 |         Vec::<P::A>::new()
   |         ^^^^^^^^^^^^^^^^^^ expected associated type, found `Vec<BMA<'_, P, M>>`
   |
   = note: expected associated type `<M as Mr<P>>::As`
                       found struct `Vec<BMA<'a, P, M>>`
   = help: consider constraining the associated type `<M as Mr<P>>::As` to `Vec<BMA<'a, P, M>>` or calling a method that returns `<M as Mr<P>>::As`
   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

Meta

The issue happens both on stable and nightly.

$ rustc +stable --version --verbose
rustc 1.72.1 (d5c2e9c34 2023-09-13)
binary: rustc
commit-hash: d5c2e9c342b358556da91d61ed4133f6f50fc0c3
commit-date: 2023-09-13
host: x86_64-apple-darwin
release: 1.72.1
LLVM version: 16.0.5
$ rustc +nightly --version --verbose
rustc 1.75.0-nightly (187b8131d 2023-10-03)
binary: rustc
commit-hash: 187b8131d4f760f856b214fce34534903276f2ef
commit-date: 2023-10-03
host: x86_64-apple-darwin
release: 1.75.0-nightly
LLVM version: 17.0.2
Backtrace

``` $ RUST_BACKTRACE=1 rustc +stable --crate-type lib impltrait.rs error[E0308]: mismatched types --> impltrait.rs:25:9 | 24 | fn a(&self) -> Self::As where Self::As: IntoIterator { // impl IntoIterator { | -------- expected `>::As` because of return type 25 | Vec::::new() | ^^^^^^^^^^^^^^^^^^ expected associated type, found `Vec>` | = note: expected associated type `>::As` found struct `Vec>` = help: consider constraining the associated type `>::As` to `Vec>` or calling a method that returns `>::As` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. ```

jflatow commented 11 months ago

The references / lifetimes aren't necessary, here's a slightly simpler version:

pub trait Po: Sized {
    type A: MA<Self>;
}

pub trait MA<P: Po>: Sized {}

pub trait Mr<P: Po>: Sized {
    type As: IntoIterator<Item = P::A>; // shouldn't be necessary?

    fn a(&self) -> Self::As; // impl IntoIterator<Item = P::A>;
}

pub trait BM<P: Po<A = BMA<P, Self>>>: Mr<P> {}

pub enum BMA<P: Po<A = Self>, M: BM<P>> {
    V(M, P),
}

impl<P: Po<A = Self>, M: BM<P>> MA<P> for BMA<P, M> {}

impl<P: Po<A = BMA<P, M>>, M: BM<P>> Mr<P> for M {
    type As = Vec<P::A>; // shouldn't be necessary?

    fn a(&self) -> Self::As { // impl IntoIterator<Item = P::A> {
        Vec::<P::A>::new()
    }
}