【问题标题】:Why do I get "overflow evaluating the requirement `Sized`" when using tokio_io's read_exact with a Rc<TcpStream>?为什么在将 tokio_io 的 read_exact 与 Rc<TcpStream> 一起使用时会出现“评估要求‘Sized’的溢出”?
【发布时间】:2018-10-15 19:54:45
【问题描述】:

已经贴了不少类似的错误:

My case 更简单,看起来很无辜:

extern crate tokio_core;
extern crate tokio_io;

use std::{borrow::Borrow, rc::Rc};
use tokio_core::net::TcpStream;
use tokio_io::io::read_exact;

fn read_one(conn: Rc<TcpStream>) {
    read_exact(conn.borrow(), [0u8]);
}

它给出了这个错误:

error[E0275]: overflow evaluating the requirement `_: std::marker::Sized`
 --> src/main.rs:9:5
  |
9 |     read_exact(conn.borrow(), [0u8]);
  |     ^^^^^^^^^^
  |
  = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
  = note: required because of the requirements on the impl of `std::io::Read` for `&tokio_core::reactor::poll_evented2::PollEvented<_>`
  = note: required because of the requirements on the impl of `std::io::Read` for `&tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<_>>`
  = note: required because of the requirements on the impl of `std::io::Read` for `&tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<_>>>`
[... snip ...]
  = note: required because of the requirements on the impl of `std::io::Read` for `&tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
  = note: required because of the requirements on the impl of `tokio_io::AsyncRead` for `&tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<tokio_core::reactor::poll_evented2::PollEvented<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
  = note: required by `tokio_io::io::read_exact`

发生了什么事?

我知道以下工作,它比上面的更简单:

read_exact(&*conn, [0u8]);

我相信conn.borrow 应该也能正常工作,我只是不明白为什么会出现这个错误。

【问题讨论】:

  • 这个read_exact::&lt;&amp;TcpStream, _&gt;(conn.borrow(), [0u8]); 会起作用,我没有知识来解释它,但它与您链接的问题的答案相似。 “这会导致溢出和普遍的悲伤。Rust 永远不会找到反证,所以不能保证它会走错路。”
  • 对。我觉得背后的原因是一样的。但是如果这是编译器中的一个不容易修复的bug,我该怪tokio吗?如果我自己的库也遇到这个问题,如何避免用户出现这样的困惑?
  • 也许你应该在 rust 编译器的 github 上搜索或打开一个问题,他们将能够正确地回答你(之后不要忘记带着答案来这里;))

标签: rust


【解决方案1】:

&amp;*connconn.borrow() 的区别在于一个类型可能有多个 Borrow impls

use std::borrow::Borrow;

fn main() {
    let input = vec![1, 2, 3];

    let _slice:   &[u8]    = input.borrow(); // ok
    let _vec_ref: &Vec<u8> = input.borrow(); // also ok 

    let _slice:   &[u8]    = &*input; // ok
//  let _vec_ref: &Vec<u8> = &*input; // error!
}

&amp;*conn 表达式使用 Deref 特征,其中每个类型只能有一个 Deref 实现。但是,一个类型可以针对不同的Xs 有多个Borrow&lt;X&gt; 实现。

当你写作时

read_exact(conn.borrow(), [0u8]);

编译器需要解决以下义务:

  1. Rc&lt;TcpStream&gt;: Borrow&lt;X1&gt; 由于使用了borrow()
  2. &amp;X1: AsyncRead 由于read_exact

请注意,X1 是未知类型。编译器需要找出所有潜在的X1s 并查看是否有人可以同时承担这两项义务。义务 2 以某种方式首先得到了评估,最终得到了这些候选人:

  1. impl&lt;X2&gt; AsyncRead for &amp;PollEvented&lt;X2&gt; where &amp;X2: Read
  2. impl AsyncRead for &amp;TcpStream
  3. impl AsyncRead for &amp;[u8] 和可能更不重要的候选人...

再次,不知何故,候选人 1 在候选人 2 之前被选中。这导致在候选人 1 被选中后,会出现以下一组新的义务:

  1. Rc&lt;TcpStream&gt;: Borrow&lt;PollEvented&lt;X2&gt;&gt;
  2. &amp;PollEvented&lt;X2&gt;: AsyncRead 解决了!
  3. &amp;X2: Read

然后导致impl&lt;X3&gt; Read for &amp;PollEvented&lt;X3&gt; where &amp;X3: Read 被选中,从这一点开始求解器陷入无限循环并最终放弃。

有关编译器如何求解这些方程的详细信息,请参阅Rust Compiler Guide

好消息是 trait 系统正在 revamped 使用标准逻辑推理技术(如 Prolog),它允许正确推断 OP 的程序。

但是,在实现新的 trait 引擎之前,如果你必须使用 borrow,你可以告诉编译器 X1 应该是什么:

read_exact::<&TcpStream, _>(conn.borrow(), [u8]);
//           ^~~~~~~~~~ forces &X1 = &TcpStream

如果您有兴趣,下面的chalk 程序证明新的求解器可以对 OP 的示例进行类型检查

trait Borrow<T> {}
trait AsyncRead {}
trait Read {}

struct Ref<T> {} // meaning &T

struct Rc<T> {}
impl<T> Borrow<T> for Rc<T> {}

struct TcpStream {}
impl Read for TcpStream {}
impl AsyncRead for TcpStream {}
impl Read for Ref<TcpStream> {}
impl AsyncRead for Ref<TcpStream> {}

struct PollEvented<E> {}
impl<E> AsyncRead for Ref<PollEvented<E>> where Ref<E>: Read {}
impl<E> Read for Ref<PollEvented<E>> where Ref<E>: Read {}

// Verify:
// 
// ?- exists<X> { Ref<X>: AsyncRead, Rc<TcpStream>: Borrow<X> }
// Unique; substitution [?0 := TcpStream], lifetime constraints []

【讨论】:

  • 在我研究这个问题时,一位编译器开发人员告诉我,有一些特殊情况可以解决允许无限递归的引用。我不确定是&amp;X1: AsyncRead 中的引用还是impl&lt;X2&gt; AsyncRead for &amp;PollEvented&lt;X2&gt; where &amp;X2: Read 中的引用之一触发了这种特殊情况。
  • 允许正确推断 OP 的程序 — 你知道如何吗? AsyncRead 仍然可能存在无限循环;现在是否考虑到Borrow 对于Rc&lt;T&gt; 只有一种实现?
  • @Shepmaster 我认为您需要向 niko 询问“如何”,我只知道它有效? 也许通过 smallcultfollowing.com/babysteps/blog/2017/09/12/… 中编写的一些方法
  • 我认为x.borrow() 等同于&amp;*x,但如果我知道&amp;*x 实际上等同于x.deref(),我会尽可能使用它。只是一个但不喜欢神奇的符号运算符。
  • @kennytm 所以新引擎和旧引擎一样(我的意思是,做同样的事情,也许以不同的方式),但使用 BFS 而不是 DFS,所以它不会被困在一个圆圈,对吗?
猜你喜欢
  • 2021-08-12
  • 2019-10-13
  • 1970-01-01
  • 1970-01-01
  • 2020-04-29
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
相关资源
最近更新 更多