无法为自定义特征实施 io::Read

Can not implement io::Read for a custom trait

我想为我的自定义特征实现 std::io::Read 特征。这是我的尝试:-

use std::io::Read;

trait Bar {
    fn foo(&self);
}

impl<T: Bar> Read for T {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        Ok(0)
    }
}

Playground

错误:-

   Compiling playground v0.0.1 (/playground)
error[E0119]: conflicting implementations of trait `std::io::Read` for type `&mut _`:
 --> src/lib.rs:7:1
  |
7 | impl<T: Bar> Read for T {
  | ^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: conflicting implementation in crate `std`:
          - impl<R> std::io::Read for &mut R
            where R: std::io::Read, R: ?Sized;
  = note: downstream crates may implement trait `Bar` for type `&mut _`

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
 --> src/lib.rs:7:6
  |
7 | impl<T: Bar> Read for T {
  |      ^ type parameter `T` must be used as the type parameter for some local type
  |
  = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
  = note: only traits defined in the current crate can be implemented for a type parameter

error: aborting due to 2 previous errors

目前不允许这样做,如注释中所述:

= note: downstream crates may implement trait `Bar` for type `&mut _`

您正在尝试为实现 Bar 的所有类型实现 Read,但您不能保证 Bar 的所有实现(现在或将来)不会 -或者不会 - 已经实施 Read。例如,您 crate 的用户可能会为他们自己的一种类型实现 Bar

第二个错误中说明了另一个问题:

= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter

如果或者特征在你的板条箱中定义(Read不是)或[=37,你才可以实现特征=] 如果你实现它的类型是在你的板条箱中定义的。这意味着你不能为 T 实现 Read,因为 T 字面上是 any 类型,包括来自其他板条箱的任意类型。

解决此问题的方法是添加一个函数,从任意 T: Bar:

公开 Read 实现
use std::io::Read;

trait Bar {
    fn foo(&self);
    fn as_reader(&self) -> BarRead<&Self> {
        BarRead(self)
    }
}

pub struct BarRead<T>(T);

impl<T: Bar> Read for BarRead<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        Ok(0)
    }
}