我一直在尝试编写一个特征,它需要一个类型来实现Add
(以及向下空间的其他操作)以及它自己以及它的引用。以下是一个小例子,说明我遇到的问题:
use std::ops::Add;
#[derive(Debug)]
struct MyVec<T>(Vec<T>);
impl<'a, 'b, T: Copy + Add> Add<&'a MyVec<T>> for &'b MyVec<T> {
type Output = MyVec<T::Output>;
fn add(self, other: &'a MyVec<T>) -> Self::Output {
/* ... */
}
}
impl<'a, T: Copy + Add> Add<MyVec<T>> for &'a MyVec<T> {
/* ... */
}
impl<'a, T: Copy + Add> Add<&'a MyVec<T>> for MyVec<T> {
/* ... */
}
impl<T: Copy + Add> Add<MyVec<T>> for MyVec<T> {
/* ... */
}
trait Addable: Add<Self, Output = Self>
where
Self: Sized,
for<'a> &'a Self: Add<Self, Output = Self>,
for<'b> Self: Add<&'b Self, Output = Self>,
for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
{
}
impl<T: Copy + Add<Output = T>> Addable for MyVec<T> {}
fn add_stuff<'a, 'b, T: Addable>(x: &'a T, y: &'b T) -> T {
x + y
}
fn main() {
let v = MyVec(vec![1, 2, 3]);
let w = MyVec(vec![2, 4, 6]);
println!("{:?}", add_stuff(&v, &w));
}
newtype
模式创建了Vec
的别名,因此我可以在外部结构(Add
)上实现外部特征(Vec
)。Add
及其引用实现了MyVec
。关联类型Output
始终是(未引用的)MyVec
。后三个impl
是根据第一个实现的。Addable
是我想要演示的核心特征。可添加的内容应该允许自己和它们的引用添加,结果为Self
。特别是,在add_stuff
中我希望表达式x + y + x
有效,其中x + y
给出一个非参考号,可以添加x
(尚未移出,因为它是一个参考生成另一个非参考。Addable
MyVec
特征实施的任何投诉。具体来说,编译器似乎认识到上述impl
满足where
子句中的边界。但是,我收到以下编译器错误:
error[E0277]: the trait bound `for<'a> &'a T: std::ops::Add<T>` is not satisfied
--> src/main.rs:33:1
|
33 | / fn add_stuff<'a, 'b, T: Addable>(x: &'a T, y: &'b T) -> T {
34 | | x + y
35 | | }
| |_^ no implementation for `&'a T + T`
|
= help: the trait `for<'a> std::ops::Add<T>` is not implemented for `&'a T`
= help: consider adding a `where for<'a> &'a T: std::ops::Add<T>` bound
= note: required by `Addable`
error[E0277]: the trait bound `for<'a, 'b> &'a T: std::ops::Add<&'b T>` is not satisfied
--> src/main.rs:33:1
|
33 | / fn add_stuff<'a, 'b, T: Addable>(x: &'a T, y: &'b T) -> T {
34 | | x + y
35 | | }
| |_^ no implementation for `&'a T + &'b T`
|
= help: the trait `for<'a, 'b> std::ops::Add<&'b T>` is not implemented for `&'a T`
= help: consider adding a `where for<'a, 'b> &'a T: std::ops::Add<&'b T>` bound
= note: required by `Addable`
这可以通过修改add_stuff
函数和编译器建议的where
子句来修复:
where
for<'c, 'd> &'c T: Add<&'d T, Output = T>,
for<'c> &'c T: Add<T, Output = T>,
我不明白为什么这是必要的。我想通过在特征的定义中指定一个绑定,我可以依赖于实现该特征的任何类型的绑定?必须每次添加这些where
条款都会违反Addable
特征的全部内容。
谷歌搜索提出了this GitHub issue我完全不了解但可能与此有关?这表明这确实是Rust中的一个错误(很长一段时间没有修复)。
答案 0 :(得分:2)
你现在遇到了Rust编译器的缺点。 RFC 2089建议使其按预期工作,并于2017年12月被接受。
但是,截至今天,该功能尚未实施。 tracking issue for the implementation还没有看到很多活动,所以看起来实现甚至还没有开始。看来,在有效实现此特定功能之前,必须对编译器的特征绑定处理进行一些基本改进(搜索关键字:粉笔)。