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

Rust confused by associated types in default generic #87682

Open uzytkownik opened 3 years ago

uzytkownik commented 3 years ago

I tried this code:

pub trait Foo {
    type Assoc;
}

pub trait Bar {

}

pub struct FooBar<T> {}

impl<T> Bar for FooBar<T>
{
}

pub struct Baz<F: Foo, B: Bar = FooBar<F::Assoc>> {}

I expected to see this happen: Code compiles or provide a readable error

Instead, this happened:

   Compiling playground v0.0.1 (/playground)
error[E0220]: associated type `Assoc` not found for `F`
  --> src/lib.rs:16:43
   |
16 | pub struct Baz<F: Foo, B: Bar = FooBar<F::Assoc>> {}
   |                                           ^^^^^ associated type `Assoc` not found

error: aborting due to previous error

For more information about this error, try `rustc --explain E0220`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

Meta

It also happens on stable based on play.rust-lang.org.

rustc --version --verbose:

rustc 1.56.0-nightly (4e282795d 2021-07-31)
binary: rustc
commit-hash: 4e282795d7d1d28a4c6c1c6521045ae2b59f3519
commit-date: 2021-07-31
host: x86_64-pc-windows-msvc
release: 1.56.0-nightly
LLVM version: 12.0.1
jackh726 commented 3 years ago

So, you're trying to impl Bar, but Bar doesn't have an associated type? Only Foo

uzytkownik commented 3 years ago

@jackh726 Fixed (sorry - I have large app so I try to create minimal repo but sometimes I make errors when I simplify)

fmease commented 9 months ago

Minimized:

pub trait Foo {
    type Assoc;
}

pub struct Baz<F: Foo, B = F::Assoc>(F, B);

Current output:

error[E0220]: associated type `Assoc` not found for `F`
 --> src/lib.rs:5:31
  |
5 | pub struct Baz<F: Foo, B = F::Assoc>(F, B);
  |                               ^^^^^ there is an associated type `Assoc` in the trait `Foo`
  |
help: change the associated type name to use `Assoc` from `Foo`
  |
5 | pub struct Baz<F: Foo, B = F::Assoc>(F, B);
  |                               ~~~~~
fmease commented 9 months ago

Of course, it compiles if fully qualified (B = <F as Foo>::Assoc). Apparently, we don't pass the candidate <F as Foo> to one_bound_for_assoc_item.

juliuskunze commented 3 months ago

+1. Just ran into this with an example that seems to highlight that this is a bug, namely that you can't replace the qualifier <C as T> with C here:

trait T {
    type A;
}

struct S<
    C: T,
    F: Fn(C::A) = fn(<C as T>::A)
>(C, F);
Veetaha commented 2 months ago

I created https://github.com/rust-lang/rust/issues/129701 with a smaller reproduction of this:

trait Trait {
    type Assoc;
}

struct Struct<A: Trait, B = A::Assoc> {
    field_1: A,
    field_2: B,
}
fmease commented 2 months ago

(that's basically https://github.com/rust-lang/rust/issues/87682#issuecomment-1907098685)

Veetaha commented 2 months ago

Ah, right, I somehow missed it.