Generic type constraint on `impl<T: ?> SomeStruct {...}`

Implementing on a simple struct a method that uses some generic type functionality, i.e.

struct A;
impl<T: ??> A {
    fn method() {
        T::func();  // ...e.g.
    }
}

Put the generic type on the method.

struct A;
impl A {
    fn method<T>() {
        
    }
}

What are you trying to do

@RustyYato Sorry, I hit accidentially the send button (I'm an emacs guy...) and was still editing it. Thanks for your answer, I'm going to try it out, otherwise I'll come back.

No problem! Let me know if it was helpful.

@RustyYato The problem with

struct A;
impl A {
    fn method<T: TConstraint>() {
        T::func();  // ...e.g.
    }
}

is I then have to call self.method::<T>() where I'd hoped to have a generic implementation for each T.

What are you trying to do, not this minimized example, your actual code? Why is it bad to call it like A::method::<T>()? This is generic over T, so I'm a bit confused about what you are asking.

1 Like

@RustyYato Ok, your method works, thanks! The overall code is quite involved, I'll show a simple example what I was/am trying to achieve:

pub trait AsyncEvent<'de> = Serialize + Deserialize<'de> + Sync + Send;

#[async_trait]
pub trait SerdeEvent
<'de, E: AsyncEvent<'de> + 'de> {
    ...
    /// Shorthand for bincode::serialize(event).
    #[inline]
    fn bin_ser(e: &E) -> EventBuffer {
        bincode::serialize(e)
            .expect("Cannot serialize event into buffer.")
    }
    /// Shorthand for bincode::deserialize(buf).
    #[inline]
    fn bin_des(buf: &'de [u8]) -> E {
        bincode::deserialize(&buf[..])
            .expect("Cannot deserialize buffer into event.")
    }
    ...
}

pub struct Connection {
    connection: IpcConnection,
    buffer: EventBuffer,
}
impl<'de> Connection {

   ....

    pub async fn send<
        S: SerdeEvent<'de, A> + 'de,
        // A: AyncEvent<'de> + 'de,  // TODO 0: why can't alias be used here?
        A: Serialize + Deserialize<'de> + Sync + Send + 'de,
    >
    (&mut self, event: &'de A)
    {
        // let v_am = bincode::serialize(event)
        //     .unwrap();
        let v_am = S::bin_ser(event);  // see _TODO above
        self.connection.write_all(&v_am).await
            .expect("Unable to write event to client");

    }

    pub async fn read<
        S: SerdeEvent<'de, A> + 'de,
        // A: AyncEvent<'de> + 'de,  // TODO 0: why can't alias be used here?
        A: Serialize + Deserialize<'de> + Sync + Send + 'de,
    >
    (&'de mut self) -> A {
        self.connection.read(&mut self.buffer[..]).await
            .expect("Unable to read buffer");
        let event = S::bin_des(&self.buffer[..]);
        event
    }

    ....

}

This now works but I have to call it as

   some_connection.send::<AMEvent, AMEvent>(&AMEvent::Ping).await;

Notice the duplicate <AMEvent, AMEvent> which I haven't found how to reduce to one...

Anyway, it now works. Frankly, I'd hoped I would have been able to specify the generics at the constructor level.

Your suggestion as to (1) simplify the generic call, and (2) how to reuse the trait alias would be appreciated.

BTW, as regards (2) the error msg I get is:

error[E0405]: cannot find trait `AyncEvent` in this scope
   --> src/fw/control/events.rs:190:12
    |
36  | pub trait AsyncEvent<'de> = Serialize + Deserialize<'de> + Sync + Send;
    | ----------------------------------------------------------------------- similarly named trait alias `AsyncEvent` defined here
...
190 |         A: AyncEvent<'de> + 'de,  // TODO 0: why can't alias be used here?
    |            ^^^^^^^^^ help: a trait alias with a similar name exists: `AsyncEvent`

If you're OK with forcing all callers to specify the same type for both - does this not work?

    pub async fn send<
        S: SerdeEvent<'de, S> + Sync + Send + 'de,
    >
    (&mut self, event: &'de S)
    {
        // let v_am = bincode::serialize(event)
        //     .unwrap();
        let v_am = S::bin_ser(event);  // see _TODO above
        self.connection.write_all(&v_am).await
            .expect("Unable to write event to client");
    }
1 Like

One way would be to do

#[async_trait]
pub trait SerdeEvent<'de>: Serialize + Deserialize<'de> + Sync + Send {
    ...
    /// Shorthand for bincode::serialize(event).
    #[inline]
    fn bin_ser(e: &Self) -> EventBuffer {
        bincode::serialize(e)
            .expect("Cannot serialize event into buffer.")
    }
    /// Shorthand for bincode::deserialize(buf).
    #[inline]
    fn bin_des(buf: &'de [u8]) -> Self {
        bincode::deserialize(&buf[..])
            .expect("Cannot deserialize buffer into event.")
    }
    ...
}

Then this

    pub async fn send<
        S: SerdeEvent<'de>
    >
    (&mut self, event: &S)
    { ... }

Doesn't require any annotations to call, or the unstable trait aliases feature.

1 Like

@RustyYato & @daboross Excellent! Thanks a lot!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.