【问题标题】:How to solve this unconstrained type parameter error in Rust如何解决 Rust 中这种不受约束的类型参数错误
【发布时间】:2021-03-15 15:49:59
【问题描述】:

我有一个消息传递系统,想通用地解决所有问题。 消息可以发送给实体,实体可以处理消息。

// There are many messages that implement this trait
trait Message {
    type Response;
}

// Messages can be sent to 'entities'
trait Entity {
    type Error;
}

// Entities can implement handlers for specific messages
trait MessageHandler<M: Message>: Entity {
    fn handle(
        &mut self,
        message: M,
    ) -> Result<M::Response, Self::Error>;
}

这将像这样实现:

struct SimpleEntity;
impl Entity for SimpleEntity {
    type Error = ();
}

struct SimpleMessage;
impl Message for SimpleMessage {
    type Response = ();
}

impl MessageHandler<SimpleMessage> for SimpleEntity {
    fn handle(
        &mut self,
        message: SimpleMessage,
    ) -> Result<(), ()> {
        Ok(())
    }
}

所有实体都存储在一个系统中。系统只能存储一种类型的实体。对于该类型具有的每个消息处理程序,都应该有一个 send_message 函数来一般地接收消息。

我想它可能看起来像这样:

// A message system for one type of entity. This is an example. Normally there's all kinds of async multithreaded stuff here
struct MessageSystem<E: Entity> {
    handlers: Vec<E>,
}

// For every message handler, we want to implement the send_message function
impl<M: Message, MH: MessageHandler<M>> MessageSystem<MH> {
    pub fn send_message(&mut self, entity_id: (), message: M) -> Result<M::Response, MH::Error> {
        unimplemented!();
    }
}

然后可以这样使用:

// Example usage
fn main() {
    let mut system = MessageSystem { handlers: vec![SimpleEntity] };
    system.send_message((), SimpleMessage).unwrap();
}

但是,这会在 send_message 函数的 impl 块中产生编译错误:

error[E0207]: the type parameter `M` is not constrained by the impl trait, self type, or predicates
  --> src/lib.rs:25:6
   |
25 | impl<M: Message, MH: MessageHandler<M>> MessageSystem<MH> {
   |      ^ unconstrained type parameter

error: aborting due to previous error

For more information about this error, try `rustc --explain E0207`.

Link to playground

我怎样才能做到这一点?

目标是拥有这些不同的消息结构,让它们由实体可以实现的处理程序处理,并通过系统结构将消息发送到实体。

一个明显的事情是让消息成为MessageHandler trait 中的关联类型,但是你不能为一个实体实现它的多个版本。

【问题讨论】:

    标签: rust


    【解决方案1】:

    由于Msend_message 的泛型,而不是MessageSystem 本身的泛型,因此将其移至send_message 函数,并将绑定到方法的特征移至方法。

    impl<MH: Entity> MessageSystem<MH> {
        pub fn send_message<M>(&mut self, entity_id: (), message: M) -> Result<M::Response, MH::Error>
        where
            M: Message,
            MH: MessageHandler<M>,
        {
            unimplemented!();
        }
    }
    

    Playground link

    您最初的错误发生是因为您有一个 trait 不使用的通用参数,这意味着它是模糊的并且无法选择正确的 impl。

    【讨论】:

    • impl 泛型中的 MH: MessageHandler&lt;M&gt; 不知道 send_message 中的 M,这不应该引发错误吗?
    • @Mihir 我没有注意到这一点,但我已经编辑了帖子,所以现在可以使用了。
    • 是的,效果很好!出于某种原因,我认为这不适用于函数本身的边界。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    相关资源
    最近更新 更多