rust-lang / rust

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

Rustc Confuses Associated Types on Type Inference #82513

Open apopiak opened 3 years ago

apopiak commented 3 years ago

The following code does not compile (playground link):

pub trait Trait {
    type Value;
    type AccountId: Default;
}

pub enum A<T: Trait> {
    _C(
        (T::AccountId, T::AccountId),
    ),
}

impl<T: Trait> A<T>
where
    (T::Value, T::Value): Default,
{
    fn foo() -> Self {
        A::_C(Default::default())
    }
}

I expected to see this happen: Successful compilation

Instead, this happened: I get E0271

error[E0271]: type mismatch resolving `<T as Trait>::AccountId == <T as Trait>::Value`
  --> src/lib.rs:17:3
   |
17 |         A::_C(Default::default())
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected Trait::AccountId, found Trait::Value
   |
   = note: expected associated type `<T as Trait>::AccountId`
              found associated type `<T as Trait>::Value`

Ways to get this to compile (that shouldn't matter/don't change the semantics):

Meta

rustc --version --verbose:

rustc 1.50.0 (cb75ad5db 2021-02-10)
binary: rustc
commit-hash: cb75ad5db02783e8b0222fee363c5f63f7e2cf5b
commit-date: 2021-02-10
host: x86_64-unknown-linux-gnu
release: 1.50.0

(also happens on 1.52-nightly)

b-naber commented 3 years ago

Didn't you mean to write?

impl<T: Trait> A<T>
where
    (T::AccountId, T::AccountId): Default,
{
    fn foo() -> Self {
        A::_C(Default::default())
    }
}

That seems more like what was intended here and it compiles.

kadiwa4 commented 6 months ago

This appears to be fixed-by-next-solver, but I don't think I can add that label.

apopiak commented 5 months ago

Didn't you mean to write?

impl<T: Trait> A<T>
where
  (T::AccountId, T::AccountId): Default,
{
  fn foo() -> Self {
      A::_C(Default::default())
  }
}

Nope, the bug is specifically about the compiler getting confused by the useless/superfluous (at least with this particular simplified code example) where clause that should not have any impact on the compilation. It is a reduced version of real life code IIRC (it's been a while 😅 ) that might be generated.