Returning a pointer to method from within trait impl


#1

I’m trying to return a list of methods bound to their names (RPC implementation):

struct Stub {
    fn method_a(&self, args: u8) -> u8 { ... }
    fn method_b(&self, args: u8) -> u8 { ... }
}

impl RPCStub for Stub {
    fn methods(&self) -> Vec<(String, Box<Fn(&Self, u8) -> u8>)> {
        vec!(
            ("a".to_owned(), Box::new(Self::method_a)),
            ("b".to_owned(), Box::new(Self::method_b)),
        )
    }
}

where RPCStub is defined as:

pub trait RPCStub {
    fn methods(&self) -> Vec<(String, Box<Fn(&Self, u8) -> u8>)> where Self: Sized;
}

it all works fine (i.e. compiles) but I can’t actually call the methods() method:

let s = Stub::new();
let m = s.methods();
for (n, _) in m {
    println!("{}", n);
}

fails with:

error: the trait `core::marker::Sized` is not implemented for the type `RPCStub + 'static`

any ideas how can I sort this out? I’d really prefer not to get down to match over string names.


#2

It usually is a good idea to post the code that can be pasted into the playground. I’ve copied the pieces from here and can’t reproduce the error.


#3

Sorry. I copied enough code to make it fail: http://is.gd/v2hkma


#4

This is an object safety issue. I’m not sure where the official explanation is but this applies to your case: http://huonw.github.io/blog/2015/01/object-safety/#references-self
As explained in the article, adding a where Self: Sized to the method sidesteps the whole trait not being object safe but this method still isn’t available on the trait object.


#5

Well, but where Self: Sized is in your code too and I suppose that

pub struct GreeterService<S: GreeterServiceImpl> {
    inner: Box<S>,
}

is sized. Any ways to overcome the problem?


#6

The simple example used a concrete type (Stub), not a trait object (Box<Service>).