Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The trait cannot be made into an object

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?

like image 957
Alexander Avatar asked Jul 15 '17 10:07

Alexander


People also ask

Can a trait be an object?

A trait object is an opaque value of another type that implements a set of traits. The set of traits is made up of an object safe base trait plus any number of auto traits. Trait objects implement the base trait, its auto traits, and any supertraits of the base trait.

What is dyn rust?

dyn is a prefix of a trait object's type. The dyn keyword is used to highlight that calls to methods on the associated Trait are dynamically dispatched. To use the trait this way, it must be 'object safe'. Unlike generic parameters or impl Trait , the compiler does not know the concrete type that is being passed.

What is sized in Rust?

The Sized trait in Rust is an auto trait and a marker trait. Auto traits are traits that get automatically implemented for a type if it passes certain conditions. Marker traits are traits that mark a type as having a certain property.


Video Answer


2 Answers

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.

like image 157
Peter Hall Avatar answered Sep 23 '22 20:09

Peter Hall


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

like image 39
Zernike Avatar answered Sep 20 '22 20:09

Zernike