简体   繁体   中英

Rust generics - traits, structs and associated types

I am from C++ community, switching to Rust... and playing with Rust generics, can anyone please explain why I am getting this error in this dummy example?

struct FF<T1, T2>(T1, T2);

trait FFt<T1, T2> {
    type t1 = T1;
    type t2 = T2;
    fn call<t1, t2>(&self, t_1: Self::t1, t_2: Self::t2);
};

impl<T1, T2> FFt<T1, T2> for FF<T1, T1> {
    fn call<T1, T2>(&self, t_1: Self::t1, t_2: Self::t2) {
        t_1.a = 1;
        t_2.b = 1;
    }
}

struct AA {
    a: i32,
    b: i32,
}
let fff: FF<AA, AA> = FF(AA { a: 0, b: 0 }, AA { a: 0, b: 0 });

fff.call(AA { a: 0, b: 0 }, AA { a: 0, b: 0 }); // <----- ERROR LINE !!!

Error:

error[E0609]: no field `a` on type `T1`
   --> p2p/./src/lib.rs:172:17
    |
170 |     impl<T1,T2> FFt<T1,T2> for FF<T1,T1> {
    |          -- type parameter 'T1' declared here
171 |         fn call<T1,T2>(&self,t_1 : Self::t1,t_2 : Self::t2) {
172 |             t_1.a = 1;
    |                 ^

error[E0609]: no field `b` on type `T2`
   --> p2p/./src/lib.rs:173:17
    |
170 |     impl<T1,T2> FFt<T1,T2> for FF<T1,T1> {
    |             -- type parameter 'T2' declared here
...
173 |             t_2.b = 1;
    |                 ^

You may want to read the rust book, because you're off to a not-great start.

can anyone please explain why I am getting this error in this dummy example?

Because C++ generics and Rust generics work off of completely different principles.

C++ templates will be type-substituted then checked, so as long as you pass a type which fits into what's being used it'll work.

Rust generics are based around constraints , they are typechecked independent of instantiation, and work solely off of what the constraints allow. Constraints are specified trough traits . I've heard C++ Concepts work similarly though I've no experience there.

Here, your generic types are unconstrained, so as far as the compiler is concerned they're incapable , the compiler will pretty much only assume that they're Sized . Furthermore, traits don't support fields.

Also

trait FFt<T1,T2>{
        type t1 = T1;
        type t2 = T2;

this doesn't make much sense, the point of a generic type parameter is that the caller decides what it is, the point of an associated type is that the implementor decides what it is (but there can be only one per implementation).

And then

        fn call<t1,t2>(&self, Self::t1, Self::t2);

This means call has two generic parameters t1 and t2 (incorrect naming conventions), which are also unconstrained, and completely independent from both T1 / T2 and FFt::t1 / FFt::t2 . So you've got 6 different unknown, unconstrained, and unrelated types at this point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM