Compiler is nightly...
Im trying to make a change in my lib so it uses a generic trait Message instead of an associated type. However, I have a trait impl that no longer compiles.
I have a problem where I implement a generic trait on a generic struct. In the following code we can see that the trait does not know of parameter A. It only knows M and R, however the Receiver is generic over A. We can see from the global trait bounds that R == R, so if Message<()>, then A must impl Handler<M, ()>. However the send method, which should only be available for Message<()> (eg. no return value from handler), can not be implemented:
impl<A, M, R> Recipient<M, R> for Receiver<A>
where A: Handler<M, R> ,
M: Message<R> ,
R: 'static ,
{
fn send( &mut self, msg: M ) -> Response< ThesRes<()> >
where M: Message<()>,
{
self.addr.send( msg )
}
fn call( &mut self, msg: M ) -> Response< ThesRes<R> >
{
self.addr.call( msg )
}
...
rustc complains:
error[E0277]: the trait bound `A: thespis::handler::Handler<_, ()>` is not satisfied
--> src/single_thread/address.rs:247:13
|
247 | self.addr.send( msg )
| ^^^^ the trait `thespis::handler::Handler<_, ()>` is not implemented for `A`
The type of self.addr obviously requires that before sending a message, the actor implements the right handler:
impl<A> Address<A> for Addr<A>
where A: Actor,
{
fn send<M>( &mut self, msg: M ) -> Response< ThesRes<()> >
where A: Handler<M, ()>,
M: Message<()>,
...
This makes a whole lot of sense and I don't feel like it's a good idea to remove this trait bound.
So I tried to add the bound:
A: Handler<M, ()>
to the send method on Recipient, but that's not allowed, since it would make the implementation stricter than the trait:
error[E0276]: impl has stricter requirements than trait
--> src/single_thread/address.rs:241:2
|
241 | fn send( &mut self, msg: M ) -> Response< ThesRes<()> >
| _____^
242 | |
243 | | where A: Handler<M, ()>,
244 | | M: Message<()>,
... |
247 | | self.addr.send( msg )
248 | | }
| |_____^ impl has extra requirement `A: thespis::handler::Handler<M, ()>`
The call to self.addr is obviously sound, because the impl is only valid for an A which has the same R
in Handler<M, R>
than Message<R>
.
I would have thought that with chalkification and the constraint propagation of prolog, such simple deductions would be a piece of cake, but it seems not.
Is there a way to get around this, or do I start undoing everything and going back to an associated type?
Is this intended behavior or would it be worth filing an issue for this?