cglue icon indicating copy to clipboard operation
cglue copied to clipboard

`#[cglue_trait]` macro panicking when trait has multiple `type`s

Open ppom0 opened this issue 2 months ago • 0 comments

Hi! I'm trying to define a plugin API that permits to define multiple implementations of the same trait. (Actually multiple implementations of 2 different traits, be let's keep it simple)

So here's the business logic trait:

#[cglue_trait]
#[cglue_forward]
pub trait StreamImpl {
    fn start(&mut self) -> RResult<(), RString>;
    fn next(&mut self) -> RResult<ROption<RString>, RString>;
    fn close(&mut self) -> RResult<(), RString>;
}

I'm writing a PluginRoot trait, which compiles:

#[cglue_trait]
pub trait PluginRoot {
    type StreamImpl0: StreamImpl + 'static;

    /// Return all stream types that should be made available to reaction users
    fn stream_impls(&self) -> RVec<RString>;

    /// Return one instance of the first type
    fn stream_impl0(
        &mut self,
        config: RValue,
    ) -> ROption<Self::StreamImpl0>;
}

Ideally I'd just have one stream_impl function that returns a Box<dyn StreamImpl>, but I understand I can't do this, so I try to explicitly write that multiple implementations of my trait can be provided.

But if I want to add a second implementation of this trait, the macro panics:

#[cglue_trait]
pub trait PluginRoot {
    type StreamImpl0: StreamImpl + 'static;
    type StreamImpl1: StreamImpl + 'static;

    /// Return all stream types that should be made available to reaction users
    fn stream_impls(&self) -> RVec<RString>;

    /// Return one instance of a given type.
    fn stream_impl0(
        &mut self,
        config: RValue,
    ) -> ROption<Self::StreamImpl0>;

    /// Return one instance of a given type.
    fn stream_impl1(
        &mut self,
        config: RValue,
    ) -> ROption<Self::StreamImpl1>;

I also tried writing 2 traits:

#[cglue_trait]
pub trait PluginRootStream0 {
    type StreamImpl0: StreamImpl + 'static;
    fn stream_impl0_name(&self) -> ROption<RString>;
    fn stream_impl0(
        &mut self,
        config: RValue,
    ) -> ROption<Self::StreamImpl0>;
}

#[cglue_trait]
pub trait PluginRootStream1 {
    type StreamImpl1: StreamImpl + 'static;
    fn stream_impl1_name(&self) -> ROption<RString>;
    fn stream_impl1(
        &mut self,
        config: RValue,
    ) -> ROption<Self::StreamImpl1>;
}

But then I can't group them, both of those macro invocations fail:

// error: struct takes 2 generic arguments but 1 generic argument was supplied
cglue_trait_group!(PluginRoot, {}, { PluginRootStream0, PluginRootStream1 });

// error: trait takes 0 generic arguments but 1 generic argument was supplied
cglue_trait_group!(
    PluginRoot<S0: StreamImpl + 'static, S1: StreamImpl + 'static>,
    {},
    { PluginRootStream0<S0>, PluginRootStream1<S1> }
);


I wonder if my case is supported at all, or if I'm just misinterpreting the doc and going in a wrong direction.

Thank you for this library, can't wait to unlock its potential :)

ppom0 avatar Oct 01 '25 10:10 ppom0