特征实现其父特征的任何替代方法?

Any alternative way for trait to implement its parent trait?

我正在为 Rust 构建一个 Raft 共识算法中间件,其架构与 copycat 相似。我为开发人员编写了一个宏来定义命令方案。宏为用户定义的命令生成一个特征 A 和一个 dispatch 函数,这需要开发人员为其行为实现一个结构和一个与本主题无关的 encoder/decoder。

特征对象向 Server 对象注册以使其工作。因为特征 A 是动态生成的,所以我必须定义另一个特征 B 作为 A 的父特征。 ServerB 一起调用在 A.

中定义的 dispatch 函数

我尝试了不同的组合,但其中 none 个有效。

trait B {
    fn dispatch(&mut self, fn_id: u64) -> Vec<u8>;
}

// macro generated trait
trait A: B {
    fn a(&self) -> Vec<u8>;
    fn b(&self) -> Vec<u8>;
    fn dispatch(&mut self, fn_id: u64) -> Vec<u8> {
        match fn_id {
            1 => a(),
            2 => b(),
            _ => {}
        }
    }
}

不幸的是,A 中的 dispatch 函数不会在 B 中实现 dispatch。当我为 A 实现结构时,编译器仍然要求为 B 实现 dispatch

我还尝试将特征 B 中的 dispatch 移动到另一个特征作为 B 的父特征,但该特征无法实现 A.

我也评论了https://github.com/rust-lang/rfcs/issues/1024。似乎这个问题是开放的,但已被抛弃。有没有其他方法可以使这种模式起作用?

你根本不需要 B 成为 A 的超级特质。您可以为任何 T: A 添加 B 的全面实施。我认为这更接近意图。

解释 Rust 代码:

trait A: B {

"You can implement A, but only if you've implemented B."

trait A {
    //...
}
impl<T: A> B for T {

"If you implement A, here's a free implementation of B."

完整版如下:

trait B {
    fn dispatch(&mut self, fn_id: u64) -> Vec<u8>;
}

// macro generated trait
trait A {
    fn a(&self) -> Vec<u8>;  // added &self
    fn b(&self) -> Vec<u8>;
}

impl<T: A> B for T {
    fn dispatch(&mut self, fn_id: u64) -> Vec<u8> {
        match fn_id {
            1 => self.a(),
            2 => self.b(),
            _ => panic!(),   // Needed so that match cases are exhaustive
        }
    }
}

struct S {}

impl A for S {
    fn a(&self) -> Vec<u8> {
        unimplemented!()
    }
    fn b(&self) -> Vec<u8> {
        unimplemented!()
    }
}

Playground