接收错误[E0276]:impl比泛型具有更严格的要求

时间:2017-10-25 10:03:34

标签: rust

我正在尝试定义一个特征来比较两个给定的参数,并根据实现返回Result。它有两个泛型,但是当我们实现它时它们可以是任何东西:

pub trait Assert<L: Any + Debug> {
    fn compare<R: Any + Debug>(self, target: R) -> AssertResult;
}

现在,当我想实现平等时,我会这样做:

pub struct Equal<L> {
    expected: L,
}

impl<L> Equal<L> {
    pub fn new(expected: L) -> Equal<L> {
        Equal { expected: expected }
    }
}

impl<L: 'static + fmt::Debug> Assert<L> for Equal<L> {
    fn compare<R: PartialEq<L> + fmt::Debug>(self, target: R) -> AssertResult {
        if target == self.expected {
            Ok(())
        } else {
            Err(format!(
                "Expected {:?}, received {:?}",
                self.expected,
                target
            ))
        }
    }
}

链接到playground

我希望能够接受LR之类的内容,但在实施中限制它们。我不确定这是否是正确的方法。

1 个答案:

答案 0 :(得分:3)

L中的Assert<L>未被特征使用,因此没有用处;我会忽略它。没有这种复杂性,这就是你写的:

pub trait Assert {
    fn compare<R: Any + Debug>(self, target: R) -> AssertResult;
}

这是一个合同,上面写着“当一个类型实现Assert时,它应该提供一个方法compare,可以使用任何类型的参数调用Any和{{ 1}}。“

Debug

这是实施impl<L: 'static + fmt::Debug> Assert for Equal<L> { Assert合同的协议,其中Equal<L>是任何类型L并实施'static

Debug

这违反了 fn compare<R: PartialEq<L> + fmt::Debug>(self, target: R) -> AssertResult { 合同,其中说:“应提供一种方法Assert,可以使用任何类型的参数调用compareAny “。您提供的Debug方法不满足这些条件,但只能使用实现comparePartialEq<L>的类型的参数调用。

或者,更简洁:你签了一份合同说Debug并试图提供一个实际上compare<R: Any + Debug>的产品,并且编译器生气了,因为你没有坚持你的结束合同。

如何解决?

一种可能的纠正(您已经知道)如下所示:

compare<R: PartialEq<L> + fmt::Debug>

一个合同,上面写着“实现pub trait Assert<R> { fn compare(self, target: R) -> AssertResult; } 的类型(其中Assert<R>是任何类型)”应该提供一个方法R,可以使用{{1}类型的参数调用}}“。

compare

只要R实施impl<L: fmt::Debug, R: PartialEq<L> + fmt::Debug> Assert<R> for Equal<L> { Assert<R>实施Equal<L>L,就Debug实施R的协议

PartialEq<L>

履行Debug合同:可以在 fn compare(self, target: R) -> AssertResult { 类型的参数上调用的方法Assert。这种方法的主体可能取决于compare的知识,因为这是“合同”的条款。

RR: PartialEq<L>的组合确定了trait必须履行的合同条款。您编写的第一件事建立了一组特定的术语,然后尝试提供不满足这些术语的产品(impl方法)。上面概述的修补程序修改了术语以包含编写impl方法所需的所有条件。