Here's an isolated testcase which doesn't compile and I can't see why: Rust Playground
The type variable is set to be TheEvent, so it should be the same. Moreover, the error goes away if one seemingly unrelated restriction is relaxed (see top)
Here's an isolated testcase which doesn't compile and I can't see why: Rust Playground
The type variable is set to be TheEvent, so it should be the same. Moreover, the error goes away if one seemingly unrelated restriction is relaxed (see top)
After looking at it a little more, I'm not entirely sure why the code doesn't compile. However I noticed that it is a little weird.
CanSubscribe
has AsyncEventMachine
as a supertrait. So every struct that implements CanSubscribe
also implements AsyncEventMachine
. The definition of AsyncEventMachine::new_subscription
specifies that Self: CanSubscribe
. This means, that the method new_subscription
in the supertrait is only available for types implementing CanSubscribe
.
I think it would be better to put new_subscription
into CanSubscriber
as the Self: CanSubscribe
bound is then explicit, and you can still access the functionality offered by AsyncEventMachine
as it's a supertrait.
pub trait CanSubscribe<Producer: AsyncEventMachine>: AsyncEventMachine {
fn new_subscription(&self) -> ();
}
pub struct SimpleTokioMachine<TheEvent> {
pair_out_sender: TheEvent,
}
pub trait AsyncEventMachine {
type InEvent;
}
impl<TheEvent> AsyncEventMachine for SimpleTokioMachine<TheEvent> {
type InEvent = TheEvent;
}
impl<TheEvent, Producer: AsyncEventMachine> CanSubscribe<Producer> for SimpleTokioMachine<TheEvent> {
fn new_subscription(&self) -> ()
{
// These two types should be the same, as InEvent=TheEvent
let ev: &<SimpleTokioMachine<TheEvent> as AsyncEventMachine>::InEvent = &self.pair_out_sender;
()
}
}
It's outside the testcase, but I want AsyncEventMachine to implement event transport, once in new_subscription, and implement event conversion only for every CanSubscribe. So I don't see a way to do this without a generic trait method.
I'm not quite sure I understand what you mean. If you want to have the new_subscription
method be generic instead of the trait, that is possible like so.
My guess is that, because rustc
prefers to use where
clauses for trait resolution, it is somehow looking through CanSubscribe<Producers>
to the AsyncEventMachine
supertrait instead of consulting the implementation currently being defined, and then fails to normalize.
Perhaps this illustrates my guess better than English.
See Issue 24066 and the various issues it links to.
I'm also wondering if this is yet another manifestation of the various guises of the projection-and-normalization family of bugs…?
It's certainly related, or at least a shortcoming around handling cycles in normalization and/or trait resolution... I also tried threading the associated type through ala IntoIterator
:
pub trait CanSubscribe<Producer: AsyncEventMachine>
where
Self: AsyncEventMachine<InEvent = <Self as CanSubscribe<Producer>>::CsEvent>
{
type CsEvent;
}
However, that still results in a normalization failure on its own when using
let ev: &<Self as CanSubscribe<Producer>>::CsEvent = &self.pair_out_sender;
And attempting to add this
fn new_subscription<Producer: AsyncEventMachine>(&self) -> ()
where
Self: CanSubscribe<Producer, CsEvent=Self::InEvent>,
;
says
error[E0391]: cycle detected when computing the bounds for type parameter `Self`
Which is probably a valid complaint in the general case, but we're really just trying to get the compiler to see a type equivalence indirectly.
Writing that out gave me a couple other ideas for work-arounds though.
The first idea was to move the associated type into a separate trait that was a supertrait for the other two. But it still failed to normalize.
The second idea was to put the problematic method in its own trait, where the bounds were on the trait not the method. That also still failed to normalize.
These two are less ambiguously normalization bugs IMO.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.