即使我的特征使用与边界相同的特征,为什么还需要添加冗余特征边界? [英] Why is it necessary to add redundant trait bounds even though my trait uses those same traits as bounds?

查看:30
本文介绍了即使我的特征使用与边界相同的特征,为什么还需要添加冗余特征边界?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试编写一个 trait,它需要一个类型来实现 Add(以及向量空间的其他操作)及其自身及其引用.下面是一个小例子,说明了我遇到的问题:

I have been trying to code a trait which requires a type to implement Add (and further down the line other operations for vector spaces) with itself as well as among its references. The following is a small example, illustrating the problem I ran into:

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) 上实现外部特征 (Add)Vec).
  • 我为 MyVec 及其引用实现了 Add.关联类型 Output 始终是(未引用的)MyVec.后三个 impl 是根据第一个实现的.
  • Addable 是我想要演示的核心特征.可添加的东西应该允许它们自己和它们的引用被添加,结果是 Self.特别是,在 add_stuff 我希望表达式 x + y + x 是有效的,其中 x + y 给出了一个可以添加的非引用使用 x(它没有被移出,因为它是一个 ref)来产生另一个非 ref.
  • 我没有收到编译器关于 MyVec 上的 Addable 特性实现的任何抱怨.具体来说,编译器似乎认识到上述 impl 满足 where 子句中的边界.
    • I use the newtype pattern to create an alias of Vec so I can implement a foreign trait (Add) on a foreign struct (Vec).
    • I implement Add for MyVec and its references. The associated type Output is always the (unreferenced) MyVec. The latter three impls are implemented in terms of the first.
    • Addable is the central trait that I want to demo. Things that are addable should allow themselves and their references to be added with the result being Self. Particularly, in add_stuff I want the expression x + y + x to be valid where x + y gives a non-ref which can be added with x (which has not been moved out of, because it's a ref) to produce another non-ref.
    • I don't get any complaints from the compiler regarding the implementation of the Addable trait on MyVec. Specifically, the compiler seems to recognize that the above impls satisfy the bounds in the where clause.
    • 但是,我收到以下编译器错误:

      However, I get the following compiler errors:

      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 函数来解决:

      This can be fixed by amending the add_stuff function with a where clause as suggested by the compiler:

      where
          for<'c, 'd> &'c T: Add<&'d T, Output = T>,
          for<'c> &'c T: Add<T, Output = T>,
      

      我不明白为什么这是必要的.我认为通过在 trait 的定义中指定一个边界,我可以依赖于实现该 trait 的任何类型满足该边界?每次都必须添加这些 where 子句有点违背了我的 Addable 特性的全部要点.

      I do not understand why this is necessary. I thought by specifying a bound in the definition of the trait I could rely on that bound being met for any type that implements that trait? Having to add these where clauses every time sort of defies the whole point of my Addable trait.

      谷歌搜索提出了这个 GitHub 问题,我不完全理解但这可能是相关的?这表明这确实是 Rust 中的一个错误(很长时间没有修复).

      Googling brought up this GitHub issue which I don't understand fully but which might be related? That would suggest this is indeed a bug in Rust (which hasn't been fixed for a very long time).

      推荐答案

      您遇到了 Rust 编译器目前的一个缺点.RFC 2089 提议使其按预期工作,并于 12 月被接受2017.

      You've hit a shortcoming of the Rust compiler as it currently is. RFC 2089 proposed to make it work as you expect, and was accepted in December 2017.

      但是,截至今天,该功能尚未实现.跟踪问题 还没有看到太多活动,所以它似乎实施甚至还没有开始.在有效实现此特定功能之前,似乎需要对编译器的 trait bound 处理进行一些根本性的改进(搜索关键字:chalk).

      However, as of today, the feature isn't implemented. The tracking issue for the implementation hasn't seen much activity yet, so it appears implementation hasn't even started. It appears that some fundamental improvements to the compiler's trait bound handling are necessary before this particular feature can be efficiently implemented (search keyword: chalk).

      这篇关于即使我的特征使用与边界相同的特征,为什么还需要添加冗余特征边界?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆