HELP! What's the code wrong? Dear friends@


#![feature(box_syntax)]
use std::sync::Arc;

pub struct Session<K, V> {
  key: K,
  store: Arc<Box<SessionStore<K, V>>>
}

impl<K, V> Session<K, V> {
  fn new(key: K, store: Box<SessionStore<K, V>>) -> Session<K, V> {
    Session {
      key: key,
      store: Arc::new(store)
    }
  }
}

trait SessionStore<K, V>: Clone + Copy + Sync {
  fn select_session(&mut self, key: K) -> Session<K, V> {
    Session::new(key, box self.clone())
  }
}

fn main() {
  println!("Hello, world!");
}

This is the error message.

:13:20: 13:28 error: the trait SessionStore cannot be made into an object [E0038]
:13 store: Arc::new(store)
^~~~~~~~
:13:20: 13:28 help: see the detailed explanation for E0038
:13:20: 13:28 note: the trait cannot require that Self : Sized
:13 store: Arc::new(store)
^~~~~~~~
:13:20: 13:28 note: the trait cannot require that Self : Sized
:13 store: Arc::new(store)
^~~~~~~~
:13:20: 13:28 note: the trait cannot require that Self : Sized
:13 store: Arc::new(store)
^~~~~~~~
:13:20: 13:28 note: the trait cannot require that Self : Sized
:13 store: Arc::new(store)
^~~~~~~~
:20:27: 20:43 error: the trait SessionStore cannot be made into an object [E0038]
:20 Session::new(key, box self.clone())
^~~~~~~~~~~~~~~~
:20:27: 20:43 help: see the detailed explanation for E0038
:20:27: 20:43 note: the trait cannot require that Self : Sized
:20 Session::new(key, box self.clone())
^~~~~~~~~~~~~~~~
:20:27: 20:43 note: the trait cannot require that Self : Sized
:20 Session::new(key, box self.clone())
^~~~~~~~~~~~~~~~
:20:27: 20:43 note: the trait cannot require that Self : Sized
:20 Session::new(key, box self.clone())
^~~~~~~~~~~~~~~~
:20:27: 20:43 note: the trait cannot require that Self : Sized
:20 Session::new(key, box self.clone())
^~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
playpen: application terminated with error code 101

I found an explanation of the error and what caused it in this StackOverflow answer. Rust has a concept called object safety that, basically, means that some traits are not suitable for being trait objects (i.e. Box<Trait> or &Trait) and it happens that requiring the Self type of the trait to be Sized (having a known size at compile time) prevents the trait from being used as a trait object. An other thing is having methods with generics.

Now you may wonder how this applies to your trait. Well, you have never actually specified that it requires Sized (as in trait MyTrait: Sized) so it must be something in Sync, Copy or Clone. Looking at their definitions in core, where they originates (the std docs happens to hide their requirements), reveals that Sync is totally independent and doesn't require Sized, Copy requires only Clone, but Clone does require Sized. Aha!

So, what can we do to solve this problem? Well, it does depend on how your actual code works, but I think that your best bet may be to only require Clone for select_session, like this:

trait SessionStore<K, V>: Sync {
  fn select_session(&mut self, key: K) -> Session<K, V> where Self: Clone + 'static {
    Session::new(key, box self.clone())
  }
}

The trait itself will only require Sync, but the where clause limits the use of select_session to only be allowed if Clone is also implemented. The 'static bound is required because Box<T> is Box<T + 'static> by default and I didn't include the Copy bound because it wasn't actually use, but you can change it however you want.

An other alternative is maybe to redefine Session to avoid the boxed trait, but it depends on your actual situation. It could look something like this:

pub struct Session<K, S> {
  key: K,
  store: Arc<S>
}

impl<K, S: SessionStore<K>> Session<K, S> {
  fn new(key: K, store: S) -> Session<K, S> {
    Session {
      key: key,
      store: Arc::new(store)
    }
  }
}

trait SessionStore<K>: Sync + Clone {
  fn select_session(&mut self, key: K) -> Session<K, Self> {
    Session::new(key, self.clone())
  }
}

There we go! I hope this gives you some help in solving your problem.

5 Likes

thnx, a lot!!!

1 Like