【问题标题】:How to require that the associated types from two traits are the same? [duplicate]如何要求两个特征的关联类型相同? [复制]
【发布时间】:2019-03-13 06:24:26
【问题描述】:

我有以下两个特点:

trait Filter {
    type Message;
    fn is_valid(&self, message: &Self::Message) -> bool;
}

trait Client {
    type Message;
    fn send(&self, message: &Self::Message) -> Result<(), Error>;
}

我希望FilterClient 的实现使用相同的Message 类型。

struct ClientWithFilter<C: Client, F: Filter> {
    filter: F,
    client: C,
}

impl<C: Client, F: Filter> ClientWithFilter<C, F> {
    /// C::Message or F::Message???
    fn check_and_send(&self, message: &C::Message) -> Result<(), Error> {
        if self.filter.is_valid(message) {
            self.client.send(message)
        } else {
            Err(Error::MessageInvalid)
        }
    }
}

这不会编译:

if self.filter.is_valid(message) {
    |                   ^^^^^^^ expected client::Filter::Message, found client::Client::Message
    |
    = note: expected type `&<F as client::Filter>::Message`
               found type `&<C as client::Client>::Message`

编译器会看到 2 种不同的类型,我希望其中有一种。 如何以正确的方式在 Rust 中编写这个?

【问题讨论】:

  • "This doesn't compile":如果无法编译,请添加错误消息,以便我们轻松重现您的问题..
  • 能否包含错误信息?除非您这样做,否则我们无法帮助您。

标签: rust associated-types


【解决方案1】:

您需要适当地约束类型参数:

struct ClientWithFilter<C, F>
where
    C: Client,
    F: Filter<Message = C::Message>,
{
    filter: F,
    client: C,
}

impl<C, F> ClientWithFilter<C, F>
where
    C: Client,
    F: Filter<Message = C::Message>,
{
    fn check_and_send(&self, message: &C::Message) -> Result<(), Error> {
        if self.filter.is_valid(message) {
            self.client.send(message)
        } else {
            Err(Error::MessageInvalid)
        }
    }
}

playground

我认为现在有必要对 impl 进行重复的约束。我相信有一个 RFC 可以让 impls 从结构定义中继承约束。

【讨论】:

  • 你也可以直接写&lt;C: Client, F: Filter&lt;Message = C::Message&gt;&gt;(在我看来where在这里增加了很多可读性)。我想要where C::Message = F::Message 更多,但还不行:github.com/rust-lang/rust/issues/20041
  • 为避免重复 trait bound,您可以简单地从结构本身中删除 trait bound,只将它们留在 impl 上。如果结构只能由私有构造函数创建,则最终结果是相同的。如果您需要在结构定义中使用关联类型,则只需要结构上的特征边界,但这里不是这种情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-15
  • 1970-01-01
  • 2015-09-23
  • 1970-01-01
  • 2022-08-12
  • 1970-01-01
相关资源
最近更新 更多