Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disambiguate generic trait method call?

Tags:

rust

I have the following code:

struct X { i: i32 }

trait MyTrait<T> {
    fn hello(&self);
}

impl MyTrait<i32> for X {
    fn hello(&self) { println!("I'm an i32") }
}

impl MyTrait<String> for X {
    fn hello(&self) { println!("I'm a String") }
}

fn main() {
    let f = X { i: 0 };
    f.hello();
}

which obviously does not compile as the compiler cannot disambiguate to which trait the f.hello() belongs. So I'm getting the error

error[E0282]: type annotations needed
  --> src\main.rs:17:7
   |
17 |     f.hello();
   |       ^^^^^ cannot infer type for type parameter `T` declared on the trait `MyTrait`

Is there any way to annotate the type of hello so I can tell the compiler to e.g. invoke MyTrait<String>::hello on f?

like image 816
vsoftco Avatar asked Dec 18 '22 13:12

vsoftco


2 Answers

After some digging in I bumped into the "Fully Qualified Syntax for Disambiguation: Calling Methods with the Same Name" from the Rust Book. The situation can be adapted to mine, and one can use f as a receiver for the corresponding trait method

<X as MyTrait<String>>::hello(&f);

This compiles and works as intended.

Or even

<MyTrait<String>>::hello(&f);

works.

like image 96
vsoftco Avatar answered Dec 20 '22 03:12

vsoftco


You can use fully qualified function call syntax:

fn main() {
    let f: X;

    // shorthand form
    MyTrait::<String>::hello(&f);

    // expanded form, with deduced type
    <_ as MyTrait<String>>::hello(&f);

    // expanded form, with explicit type
    <X as MyTrait<String>>::hello(&f);
}

Run in Playground

like image 37
Frxstrem Avatar answered Dec 20 '22 02:12

Frxstrem