简体   繁体   中英

How to provide a proper type for use of generic impl?

I'm trying to build up my intuition for associated types in Rust. In my experiments I build this (nonsensical) combination of generics and impl.

struct MyStruct<T>{
    t:T
}

trait MyTrait {
    type T1;
    fn tt(x:Self::T1) -> MyStruct<Self::T1>;
}

impl<T> MyTrait for MyStruct<T> {
    type T1=T;
    fn tt(a:Self::T1) -> MyStruct<Self::T1> {
        MyStruct{t:a}
    }

}

It compiles, but the problem is that I can't use 'tt' function.


fn main() {
    let x = MyTrait::tt(1);
}

causing an error: cannot infer type .

I've tried my options to provide type hints for Rust, but more I try the less audible (for me) error messages become.

Can someone provide me with example of use MyTrait::tt function from above, or is this a dead end? If so, why?

The trouble with using something like MyTrait::tt(1) is that the actual type that implements MyTrait can't be deduced from the argument 1 . You could, for example, implement MyTrait for String , but make T1 be i32 . With that setup, MyTrait::tt(1) could refer to <String as MyTrait>::tt (using the fully qualified method call syntax). On the other hand, you could also implement MyTrait for i32 with T1 = i32 . Then MyTrait::tt(1) could also refer to <i32 as MyTrait>::tt .

impl MyTrait for String {
    type T1 = i32;
    fn tt(x: i32) -> MyStruct<i32> {
        MyStruct { t: x }
    }
}

impl MyTrait for i32 {
    type T1 = i32;
    fn tt(x: i32) -> MyStruct<i32> {
        MyStruct { t: x }
    }
}

fn main() {
    let x = 47_i32;

    // let y = MyTrait::tt(x);
    // That could refer to either of the following
    let y = <String as MyTrait>::tt(x);
    let z = <i32 as MyTrait>::tt(x);

    // Of course, you don't need the fully qualified syntax
    // all the time.
    let y2 = String::tt(x);
    let z2 = i32::tt(x);
}

(playground)

This behavior might be improved with smarter trait solvers since in your particular case, the only applicable implementation is the one on MyStruct<i32> . But for now, I'd just use <MyStruct<i32> as MyTrait>::tt(1) or simply MyStruct::tt(1) .

fn main() {
    let x = <MyStruct<i32> as MyTrait>::tt(1);
    let x = MyStruct::tt(1);
}

(playground)

To learn more about traits and fully qualified syntax take a look in The Book's chapter on advanced traits.

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