rust-lang / rust

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

Incorrect type inference with generic associated types? #107273

Open s-arash opened 1 year ago

s-arash commented 1 year ago

Playing around with generic associated types, I encountered what looks like a compiler bug:

trait Monad {
    type M<T>;
    fn bind<T, U, F: Fn(T) -> Self::M<U>>(m: Self::M<T>, f: F) -> Self::M<U>;
    fn unit<T>(x: T) -> Self::M<T>;

    fn map<T, U, F: Fn(T) -> U>(m: Self::M<T>, f: F) -> Self::M<U> {
        Self::bind(m, |x| Self::unit(f(x)))
    }

    /// applicative operator `<*>`
    fn app<T, U, F: Fn(T) -> U>(f: Self::M<F>, m: Self::M<T>) -> Self::M<U> where Self::M<T>: Clone {
        Self::bind(f, |f| Self::map(m.clone(), f)) // this fails with: 
        //                ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found type parameter `U`
        // Self::bind::<_, U, _>(f, |f| Self::map(m.clone(), f)) // this compiles
    }
}

The app implementation fails with the error above, which looks to me like type inference is inferring the wrong types (and not failing to infer types).

Meta

rustc --version --verbose:

rustc 1.66.1 (90743e729 2023-01-10)
binary: rustc
commit-hash: 90743e7298aca107ddaa0c202a4d3604e29bfeb6
commit-date: 2023-01-10
host: x86_64-pc-windows-msvc
release: 1.66.1
LLVM version: 15.0.2

Also tried on nightly, same error.

rustc 1.69.0-nightly (c8e6a9e8b 2023-01-23)
binary: rustc
commit-hash: c8e6a9e8b6251bbc8276cb78cabe1998deecbed7
commit-date: 2023-01-23
host: x86_64-pc-windows-msvc
release: 1.69.0-nightly
LLVM version: 15.0.7
Compiler Output

``` error[E0308]: mismatched types --> src\monad.rs:12:27 | 11 | fn app U>(f: Self::M, m: Self::M) -> Self::M where Self::M: Clone { | - - found type parameter | | | expected type parameter 12 | Self::bind(f, |f| Self::map(m.clone(), f)) // this fails | ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found type parameter `U` | = note: expected associated type `::M` found associated type `::M` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error[E0308]: mismatched types --> src\monad.rs:12:9 | 11 | fn app U>(f: Self::M, m: Self::M) -> Self::M where Self::M: Clone { | - - expected type parameter ---------- expected `::M` because of return type | | | found type parameter 12 | Self::bind(f, |f| Self::map(m.clone(), f)) // this fails | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `U`, found type parameter `T` | = note: expected associated type `::M` found associated type `::M` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters For more information about this error, try `rustc --explain E0308`. error: could not compile `misc` due to 2 previous errors ```

jackh726 commented 1 year ago

It does look a little fishy.