根据类型参数选择了错误的特征

时间:2018-11-02 20:21:59

标签: rust

(我无法拿出好标题,请随时对其进行纠正)。

我具有二进制特征resolve

pub trait Resolve<RHS = Self> {
    type Output;
    fn resolve(self, rhs: RHS) -> Self::Output;
}

我为诸如struct Foo这样的琐碎事物实现了特征。

struct Foo;

impl <'a, 'b> Resolve<&'b Foo> for &'a Foo {
    type Output = Foo;
    fn resolve(self, rhs: &'b Foo) -> Self::Output {
        unimplemented!()
    }
}

如您所见,两个参数都是引用(self&'a Foo,而rhs&'b Foo)。

如果我现在写

fn main() {
    let a: &Foo = &Foo;
    let b = Foo;
    a.resolve(&b);
}

它可以正常编译,但是如果我尝试在结构Signal上实现它,它将无法正常工作。

pub struct Signal<'a, T> {
    ps: Vec<&'a T>,
}

impl<'a, T: Resolve<&'a T, Output = T> + 'a> Signal<'a, T> {
    pub fn foo(&mut self) {
        let a: &T = &self.ps[0];
        let b = &self.ps[1];
        a.resolve(b);
    }
}
error[E0507]: cannot move out of borrowed content
  --> src/main.rs:25:9
   |
25 |         a.resolve(b);
   |         ^ cannot move out of borrowed content

如何使此示例正常工作? (playground

2 个答案:

答案 0 :(得分:4)

绑定到foo的特征仅表示T实现Resolve,但是您尝试对类型为.resolve()的值调用&T

相反,要说对T引用必须实现Resolve,则需要一个higher-ranked trait bound

impl<'a, T> Signal<'a, T>
where
    for<'b> &'b T: Resolve<&'a T, Output = T>,
{
    pub fn foo(&mut self) { ... }
}

答案 1 :(得分:1)

考虑了这一点,我想出了一个不依赖HRTB的简单解决方案。

impl<'a, T> Signal<'a, T>
where
    &'a T: Resolve<&'a T, Output = T> + 'a,
{
    pub fn foo(&mut self) {
        let a: &T = &self.ps[0];
        let b = &self.ps[1];
        a.resolve(b);
    }
}

这与&T实现Resolve的作用相同,即描述,但是不需要HRTB。
为此,您必须使用where clause,但除此之外,这是一个很好的解决方案。