Associated type in supertrait, unable to bound generic parameter by trait

Hey all,

I want to create a Channel<Item> trait which represents an asynchronous point-to-point communication channel for messages of a generic type Item.

My current definition of Channel is:

/// Represents a point-to-point two-way communication channel
trait Channel<Item>: Sink<Item> + Stream<Item = Result<Item, Self::StreamErr>> {
    type StreamErr;
}

I don't want the Channel to be generic over the error of the Stream, as that leads to additional bounds for downstream code and every channel type has a concrete error type.

However, when I'm actually trying to use this trait, e.g. like this:

#[async_trait]
trait Sender {
    type Msg;

    async fn send<Ch>(channel: Ch)
    where
        Ch: Channel<Self::Msg> + Send;
}

struct FooSender;

#[async_trait]
impl Sender for FooSender {
    type Msg = ();

    async fn send<Ch>(channel: Ch)
    where
        Ch: Channel<Self::Msg> + Send,
    {
    }
}

I get the very unhelpful compile error that the trait bound Ch: Channel<()> is not satisfied

Full Error
   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Ch: Channel<()>` is not satisfied
  --> src/lib.rs:24:5
   |
24 |     async fn send<Ch>(channel: Ch)
   |     ^^^^^^^^^^^^^ the trait `Channel<()>` is not implemented for `Ch`
   |
help: consider further restricting this bound
   |
26 |         Ch: Channel<Self::Msg> + Send + Channel<()>,
   |                                       +++++++++++++

error[E0277]: the trait bound `Ch: Channel<()>` is not satisfied
  --> src/lib.rs:26:13
   |
26 |         Ch: Channel<Self::Msg> + Send,
   |             ^^^^^^^^^^^^^^^^^^ the trait `Channel<()>` is not implemented for `Ch`
   |
help: consider further restricting this bound
   |
26 |         Ch: Channel<Self::Msg> + Send + Channel<()>,
   |                                       +++++++++++++

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to 2 previous errors

If I change the error in the trait definition to a concrete type, the code compiles.

I assume this is at least a diagnostics bug? If yes, and this is not already known, I can create an issue.
But maybe I'm also hitting a current limitation of the compiler? I'd be happy if someone could tell me, whether what I'm trying to do is possible.

I tried to minimise the issue a little bit which made it look very similar to Trait bound on associated type causes confusing compilation error · Issue #58231 · rust-lang/rust · GitHub

trait GenericTrait<T> {}

trait Channel<I>: GenericTrait<Self::T> {
    type T;
}

trait Sender {
    type Msg;

    fn send<C>()
    where
        C: Channel<Self::Msg>;
}

impl<T> Sender for T {
    type Msg = ();

    fn send<C>()
    where
        C: Channel<Self::Msg>,
    {
    }
}
   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `C: Channel<()>` is not satisfied
  --> src/lib.rs:18:5
   |
18 | /     fn send<C>()
19 | |     where
20 | |         C: Channel<Self::Msg>,
   | |______________________________^ the trait `Channel<()>` is not implemented for `C`
   |
help: consider further restricting this bound
   |
20 |         C: Channel<Self::Msg> + Channel<()>,
   |                               +++++++++++++

error[E0277]: the trait bound `C: Channel<()>` is not satisfied
  --> src/lib.rs:20:12
   |
20 |         C: Channel<Self::Msg>,
   |            ^^^^^^^^^^^^^^^^^^ the trait `Channel<()>` is not implemented for `C`
   |
help: consider further restricting this bound
   |
20 |         C: Channel<Self::Msg> + Channel<()>,
   |                               +++++++++++++

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to 2 previous errors
1 Like

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.