Search code examples
genericsrust

Rust trait and generics


I'm just learning in Rust, so sorry if it's a newbie question...

I should implement the following trait (with generics) for a struct, but the struct has not a generic type, so I get E0282 errors...

trait MyTrait<T> {
    fn function(&self) -> Option<T>;
}

struct MyStruct {}
impl<T> MyTrait<T> for MyStruct {
    fn function(&self) -> Option<T>{
        None
    }
}
fn main() {
    println!("Ciao!");
    let my_struct = MyStruct{};

    //let _ = my_struct.function(); // doesn't work, error[E0282]: type annotations needed
    //let _: Option<_> = my_struct.function(); // doesn't work, error[E0282]: type annotations needed
    //let _: Option<_> = <MyStruct as MyTrait<_>>::function(&my_struct);// doesn't work, error[E0282]: type annotations needed

}

Any idea how to solve it?

The trait implementation for my struct it's not mandatory but recommended, so I'm also thinking to skip it if I don't find a solution :(

Thanks in advance for your help


Solution

  • Original answer: The type annotation is needed in your implementation of the trait, not where the function is being called. Without type information, there's no way for the non-generic MyStruct to know which generic type to use when implementing MyTrait. Providing the type for the generic parameter in the implementation of the trait will fix these errors. I've chosen i32 for this example, but you should use whatever fits your needs.

    trait MyTrait<T> {
        fn function(&self) -> Option<T>;
    }
    
    struct MyStruct {}
    impl MyTrait<i32> for MyStruct {
        fn function(&self) -> Option<i32>{
            None
        }
    }
    
    fn main() {
        println!("Ciao!");
        let my_struct = MyStruct{};
    
        let _ = my_struct.function();
    }
    

    Update: In response to @jjthulhu's comment: Specifying the type in the implementation is not strictly necessary. After some experimentation I found the following does work, but if the generic type is known I would still prefer to specify it in the implementation.

    trait MyTrait<T> {
        fn function(&self) -> Option<T>;
    }
    
    struct MyStruct {}
    impl<T> MyTrait<T> for MyStruct {
        fn function(&self) -> Option<T>{
            None
        }
    }
    
    fn main() {
        println!("Ciao!");
        let my_struct = MyStruct{};
    
        let _ : Option<i32> = MyStruct::function(&my_struct);
    }