I had this code:
pub trait MiddlewareHandler: Clone + Send {
//...probably unimportant for the question
}
#[deriving(Clone)]
pub struct Middleware {
handlers: Vec<Box<MiddlewareHandler>>
}
#[deriving(Clone)]
pub struct Server{
middleware: Middleware
}
This left me with the compiler yelling at me with:
src/server.rs:20:31: 20:37 error: the type `server::Server', which does not fulfill `Send`, cannot implement this trait
src/server.rs:20 impl http::server::Server for Server {
^~~~~~
src/server.rs:20:31: 20:37 note: types implementing this trait must fulfill `Send+Sized`
src/server.rs:20 impl http::server::Server for Server {
It took me ages to figure out I had to change Vec<Box<MiddlewareHandler>>
to Vec<Box<MiddlewareHandler + Send>>
so that the final code looks like this:
pub trait MiddlewareHandler: Clone + Send {
//...probably unimportant for the question
}
#[deriving(Clone)]
pub struct Middleware {
handlers: Vec<Box<MiddlewareHandler + Send>>
}
#[deriving(Clone)]
pub struct Server{
middleware: Middleware
}
The code compiles now but I quite don't understand what exactly was the problem here. Why +Send
in the Vec
definition? I mean, the MiddlewareHandler
trait does already implement Send + Clone
. It looks rather superfluous to me.
Can someone share his wisdom with me why I had to change the code like that?
Seems like a bug, I filed #15155 .
The "problem" is the Send
restriction on the http::server::Server
. The definition is
pub trait Server: Send + Clone {
meaning the implementee needs to be both Clone
(which is satisfied because you have implemented Clone
via #[deriving(Clone)]
) and Send
. The compiler automatically implements Send
for types where the contents satisfies Send
(this detail will be changing with opt-in built-in traits : they will require explicit implementations too), unfortunately the original type is something like
pub struct Middleware {
handlers: Vec<Box<Trait>>
}
which does not implement Send
in general: there's no way for the compiler to know that the erased type in the Box<Trait>
is Send
able, eg it could contain an Rc
, and so be unsafe to transfer into a different task.
The compiler needs to know more information, that is, it needs to have a guarantee that the internal type is Send
, which can be provided by adding more bounds to the trait object: Box<Trait + Send>
...
However, in this case, the MiddlewareHandler
trait already has this Send
bound as a supertrait (meaning the contents of the trait object have to satisfy Send
already), so it's weird that the compiler isn't working out that Box<MiddlewareHandler>
is Send
(hence filing the bug).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.