如何在此结构定义中避免使用PhantomData?

Ste*_*sky 5 traits rust

我有一个看起来像这样的特征:

trait Handler<C> {
    fn handle(&self, msg: &Message, connection: &mut C);
}
Run Code Online (Sandbox Code Playgroud)

实例应该像链接HTTP处理程序的中间件一样被链接:

let handler = FirstHandler {
     next: SecondHandler {
         next: FinalHandler {},
     },
};
Run Code Online (Sandbox Code Playgroud)

每种处理程序类型都可以对类型施加额外的约束C:

trait ConnectionThatWorksWithFirstHandler {
    ...
}

struct FirstHandler<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> {
    next: H,
    _phantom: PhantomData<C>,
}
Run Code Online (Sandbox Code Playgroud)

正如你在这里看到的,我需要一个PhantomData<C>避免错误E0392(parameter C is never used).但是,PhantomData在语义上是错误的,因为处理程序没有持有实例C.这很难看.例如,我手动必须提供正确的同步/发送特征实现:

unsafe impl<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> Send for Handler<C, H> where H: Send {}
unsafe impl<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> Sync for Handler<C, H> where H: Sync {}
Run Code Online (Sandbox Code Playgroud)

自动特征实现会有一个额外的where C: Send/Sync界限,这在这里是不合适的.

有没有PhantomData的替代方案,允许我编码之间的关系,FirstHandler<C>以及CRust编译器很高兴,我不需要更多的unsafe代码?

我不是在寻找相关的类型.处理程序trait及其实现者是在库中定义的,具体类型C是在使用库的应用程序C中定义的,因此处理程序的trait实现无法定义具体类型.

这种设计的想法是允许处理程序链累积C处理程序链中所需的所有特征边界,这样当我有handler第二个代码片段中显示的变量时,隐含的特征限制就是C: ConnectionThatWorksWithFirstHandler + ConnectionThatWorksWithSecondHandler + ConnectionThatWorksWithFinalHandler.

Mar*_*ein 7

无需在结构定义处对内部处理程序强制执行约束.您可以延迟它们,直到您实现Handler特征为止FirstHandler.

trait Handler<C> {
    fn handle(&self, msg: &Message, connection: &mut C);
}

struct FirstHandler<H> {
    next: H
}

impl<C, H> Handler<C> for FirstHandler<H>
where
    H: Handler<C>,
    C: ConnectionThatWorksWithFirstHandler,
{
    fn handle(&self, msg: &Message, connection: &mut C) {
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)