Call not possible if trait anotation is not used


#1

Hello,

I have this problem:

I have two traits. The second trait (Meow) has a function(callB) that has the first trait(MyMarker) as argument. and asecond function(call) that only takes self. The calles to callB work fine. But all calls to call do not work.

rust wants to infer the type of M and failes. even through M it is not used in this function.
how do i provide provide the type for the call to call?

pub struct Cat;

pub trait MyMarker {
    fn cry(&self);
}

pub trait Meow<M> where M:MyMarker {
    fn call(&self);
    fn callB(&self, other: Box<M>);
}

impl<M: 'static> Meow<M> for Cat where M:MyMarker{
    fn call(&self) {
        println!("i want to get called");
    }
    
    fn callB(&self, other: Box<M>){
        other.cry();
        println!("i want to get called");
    }
}

struct Food;
impl MyMarker for Food{
    fn cry(&self) {
        println!("i got eaten");
    }
}

fn main() {
    let cat = Cat{};
    let f = Box::new(Food{});
    
    // works fine
    cat.callB(f);
    
    //does not work
    cat.call();
    
}
 Compiling playground v0.0.1 (file:///playground)
error[E0282]: type annotations needed
  --> src/main.rs:38:9
   |
38 |     cat.call();
   |         ^^^^ cannot infer type for `M`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0282`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

http://play.rust-lang.org/?gist=b8de7ad1b775957289a76e901b9f1c92&version=stable&mode=debug


#2

Ok i know now how to make it work:

    Meow::<Food>::call(&cat);

what i do not know is why i need to provide a type even if it is not used.


#3

It is because Meow is generic (i.e. it has a type variable), and thus each impl for it is as well.
When calling call(), Rust needs to know which of the impls to use, so that’s why you need to specify the type parameter.


#4

Perhaps you want callB to be generic but not the trait:

pub trait Meow {
    fn call(&self);
    fn callB<M>(&self, other: Box<M>) where M: MyMarker;
}

Note this will make callB uncallable via a Meow trait object - don’t know if you’re planning on using them.