Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matching a generic parameter to an associated type in an impl

Tags:

I have a trait with an associated type and a generic struct::

trait Generator {     type Foo;     fn generate(&self) -> Self::Foo; }  struct Baz<A, B> where     A: Generator, {     generator: A, // will be some struct implementing Generator, but the exact type will vary     vec: Vec<B>,  // Each element will be A::Foo } 

I want to generate and put it into my vector:

impl<A: Generator, B> Baz<A, B> {     fn addFoo(&mut self) {         self.vec.push(self.generator.generate());     } } 

Uh-oh! Compile error:

error[E0308]: mismatched types   --> src/main.rs:16:27    | 16 |             self.vec.push(self.generator.generate());    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found associated type    |    = note: expected type `B`               found type `<A as Generator>::Foo` 

Fair enough, I must explain to the compiler that B is the same as A::Foo; let's try with where:

impl<A: Generator, B> Baz<A, B> where     A::Foo = B, { 

which doesn't help:

error: equality constraints are not yet supported in where clauses (#20041)   --> src/main.rs:16:5    | 16 |     A::Foo = B,    |     ^^^^^^^^^^ 

Hmm, no equals. Maybe I can do this with the colon operator instead?

impl<A: Generator, B> Baz<A, B> where     B: A::Foo, { 
error[E0405]: cannot find trait `Foo` in `A`   --> src/main.rs:16:11    | 16 |     B: A::Foo,    |           ^^^ not found in `A` 

Nope, now it's complaining about A. Maybe I should say Generator?

impl<A: Generator, B> Baz<A, B> where     B: Generator::Foo, { 
error[E0404]: expected trait, found associated type `Generator::Foo`   --> src/main.rs:16:8    | 16 |     B: Generator::Foo,    |        ^^^^^^^^^^^^^^ not a trait 

Well good work, compiler — it's not a trait; it's an associated type, but that doesn't tell me how to write a where clause that matches it.

like image 214
Drew Avatar asked Mar 30 '15 12:03

Drew


People also ask

What is an associated type?

What is an associated type? An associated type can be seen as a replacement of a specific type within a protocol definition. In other words: it's a placeholder name of a type to use until the protocol is adopted and the exact type is specified.

Can associated types be defined implicitly?

If you declare an associated type in a protocol, that type will become generic over different implementations of the protocol, but each conforming class will need to assign a concrete type to that associate type as a typealias (which can be done implicitly by declaring all variables/functions using the associated type ...

What are generic associated types?

GATs (generic associated types) were originally proposed in RFC 1598. As said before, they allow you to define type, lifetime, or const generics on associated types. If you're familiar with languages that have "higher-kinded types", then you could call GATs type constructors on traits.

What is generic function Swift?

Swift Generics allows us to create a single function and class (or any other types) that can be used with different data types. This helps us to reuse our code.


1 Answers

I must explain to the compiler that B is the same as A::Foo

There is a special syntax for it:

impl<A, B> Baz<A, B> where     A: Generator<Foo = B>, {     fn add_foo(&mut self) {         self.vec.push(self.generator.generate());     } } 
like image 127
swizard Avatar answered Sep 27 '22 22:09

swizard