为什么从TcpStream更改为trait导致“无法将不可变借用内容借用为可变”?

时间:2018-01-26 14:38:01

标签: rust

我想使用异步IO创建SOCKS5代理的变体。我之前在Haskell做过这个,所以我认为这将是一个很好的学习挑战。我从非常well-documented SOCKS5 example code开始。

在示例中,Transfer结构要求读写器属于TcpStream类型。在我的代码中,这些需要是多态的,所以我开始定义:

pub trait Pollable {
    fn poll_read(&self) -> Async<()>;
    fn poll_write(&self) -> Async<()>;
}

impl Pollable for TcpStream {
    fn poll_read(&self) -> Async<()> {
        tokio_core::net::TcpStream::poll_read(&self)
    }
    fn poll_write(&self) -> Async<()> {
        tokio_core::net::TcpStream::poll_write(&self)
    }
}

pub trait AsyncStream: tokio_io::AsyncRead + tokio_io::AsyncWrite + Pollable {}

impl<T> AsyncStream for T
where
    T: tokio_io::AsyncRead + tokio_io::AsyncWrite + Pollable,
{}

当我在第510行将reader的类型从Rc<TcpStream>切换到Rc<AsyncStream>时,编译器在第598行失败并出现此错误:

error[E0596]: cannot borrow immutable borrowed content as mutable
   --> src/transfer.rs:125:33
    |
125 |                 let n = try_nb!((&*self.reader).read(&mut buffer));
    |                                 ^^^^^^^^^^^^^^^ cannot borrow as mutable

忽略错误消息中的文件和行号;我正在将代码移动到多个文件中,但它与示例相同。

我在Stack Overflow的其他地方找到了建议,我检查了类型。在更改之前,&*self.reader的类型为&tokio_core::net::TcpStream;更改后,类型变为&transfer::AsyncStream + 'static。当我从具体类型转变为特质时,我不知道为什么'static生命进入...

为什么会这样?我该如何解决?

1 个答案:

答案 0 :(得分:2)

tokio_core::net::TcpStream实施ReadAsyncRead for an immutable reference。你的特质没有。

lastcol&*self.reader转换为Rc<T>&T用作read方法的目标。

要解决此问题,您需要为特征的不可变引用实现适当的特征,或者使用某种内部可变性。

另见: