【发布时间】:2018-03-23 03:38:47
【问题描述】:
我一直在尝试编写一个特征,该特征需要一个类型来实现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的别名,这样我就可以在外部结构(Vec) 上实现外部特征(Add)。 - 我为
MyVec及其引用实现了Add。关联类型Output始终是(未引用的)MyVec。后三个impls 是按照第一个来实现的。 -
Addable是我要演示的核心特征。可添加的东西应该允许它们自己和它们的引用被添加,结果是Self。特别是,在add_stuff中,我希望表达式x + y + x有效,其中x + y给出一个非引用,可以添加x(它没有被移出,因为它是一个引用)来产生另一个非参考。 - 我没有收到编译器关于在
MyVec上实现Addable特征的任何投诉。具体来说,编译器似乎认识到上述impls 满足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`
这可以通过使用编译器建议的where 子句修改add_stuff 函数来解决:
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 中的一个错误(很长时间没有修复)。
【问题讨论】: