Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to require that the associated types from two traits are the same? [duplicate]

I have the 2 following traits:

trait Filter {
    type Message;
    fn is_valid(&self, message: &Self::Message) -> bool;
}

trait Client {
    type Message;
    fn send(&self, message: &Self::Message) -> Result<(), Error>;
}

I would like an implementation of Filter and Client to use the same Message type.

struct ClientWithFilter<C: Client, F: Filter> {
    filter: F,
    client: C,
}

impl<C: Client, F: Filter> ClientWithFilter<C, F> {
    /// C::Message or F::Message???
    fn check_and_send(&self, message: &C::Message) -> Result<(), Error> {
        if self.filter.is_valid(message) {
            self.client.send(message)
        } else {
            Err(Error::MessageInvalid)
        }
    }
}

This does not compile:

if self.filter.is_valid(message) {
    |                   ^^^^^^^ expected client::Filter::Message, found client::Client::Message
    |
    = note: expected type `&<F as client::Filter>::Message`
               found type `&<C as client::Client>::Message`

The compiler sees 2 distinct types where I would like to have a single one. How can I write this in Rust in a correct way?

like image 826
bm842 Avatar asked Jan 20 '26 22:01

bm842


1 Answers

You need to constrain the type parameters appropriately:

struct ClientWithFilter<C, F>
where
    C: Client,
    F: Filter<Message = C::Message>,
{
    filter: F,
    client: C,
}

impl<C, F> ClientWithFilter<C, F>
where
    C: Client,
    F: Filter<Message = C::Message>,
{
    fn check_and_send(&self, message: &C::Message) -> Result<(), Error> {
        if self.filter.is_valid(message) {
            self.client.send(message)
        } else {
            Err(Error::MessageInvalid)
        }
    }
}

playground

The redundant duplication of the constraints on the impl is necessary for now, I think. I believe there's an RFC to let impls inherit constraints from the struct definition.

like image 88
Sebastian Redl Avatar answered Jan 23 '26 06:01

Sebastian Redl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!