55

I have the following code:

extern crate futures; // 0.1.24 use futures::Future; use std::io; struct Context; pub trait MyTrait { fn receive(context: Context) -> Future<Item = (), Error = io::Error>; } pub struct MyStruct { my_trait: MyTrait, } 

When I try to compile it I get the error message:

error[E0038]: the trait `MyTrait` cannot be made into an object --> src/lib.rs:13:5 | 13 | my_trait: MyTrait, | ^^^^^^^^^^^^^^^^^ the trait `MyTrait` cannot be made into an object | = note: method `receive` has no receiver 

I think I know why it happens, but how do I refer to the trait from the struct? Is it possible? Maybe there are other ways to implement the same behavior?

2 Answers 2

46

You can either add a type parameter to your struct, as in Zernike's answer, or use a trait object.

Using the type parameter is better for performance because each value of T will create a specialized copy of the struct, which allows for static dispatch. A trait object uses dynamic dispatch so it lets you swap the concrete type at runtime.

The trait object approach looks like this:

pub struct MyStruct<'a> { my_trait: &'a dyn MyTrait, } 

Or this:

pub struct MyStruct { my_trait: Box<dyn MyTrait>, } 

However, in your case, MyStruct cannot be made into an object because receive is a static method. You'd need to change it to take &self or &mut self as its first argument for this to work. There are also other restrictions.

Sign up to request clarification or add additional context in comments.

Comments

18
pub struct MyStruct<T> where T: MyTrait, { my_trait: T, } 

or

pub struct MyStruct<T: MyTrait> { my_trait: T, } 

https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#trait-bounds

1 Comment

I don't like such kind of variant because then I can't substitute T with another instance later.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.