Why do I get “overflow evaluating the requirement `Sized`” when using tokio_io's read_exact with a Rc<TcpStream>?

≯℡__Kan透↙ 提交于 2021-02-16 20:11:09

问题


There are quite a few similar errors already posted:

  • "Overflow evaluating the requirement" but that kind of recursion should not happen at all
  • What does "Overflow evaluating the requirement" mean and how can I fix it?

My case is much more simple and looks innocent:

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]);
}

It gives this error:

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`

What is going on?

I know the following works and it is simpler than the above:

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

I believe conn.borrow should work as well, I just don't understand why we have this error.


回答1:


The difference between &*conn and conn.borrow() is that a type may have multiple 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!
}

The &*conn expression uses the Deref trait, where each type can only have a single Deref implementation. However, a type can have multiple Borrow<X> implementations for different Xs.

When you write

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

The compiler needs to solve the following obligations:

  1. Rc<TcpStream>: Borrow<X1> due to use of borrow()
  2. &X1: AsyncRead due to read_exact

Note that X1 is an unknown type. The compiler will need to find out all potential X1s and see if anyone can fit into both obligations. Obligation 2 somehow got evaluated first, which ends up with these candidates:

  1. impl<X2> AsyncRead for &PollEvented<X2> where &X2: Read
  2. impl AsyncRead for &TcpStream
  3. impl AsyncRead for &[u8] and probably more unimportant candidates...

Again, somehow candidate 1 is selected before candidate 2. This leads to the following new set of obligations after candidate 1 is selected:

  1. Rc<TcpStream>: Borrow<PollEvented<X2>>
  2. &PollEvented<X2>: AsyncRead solved!
  3. &X2: Read

which then leads to impl<X3> Read for &PollEvented<X3> where &X3: Read being selected, and from this point the solver got stuck in an infinite loop and eventually gave up.

Details about how the compiler solves these equations can be found in the Rust Compiler Guide.

The good news is that the trait system is being revamped to use standard logic inference techniques (like Prolog) which allows OP's program to be inferred correctly.

However, before the new trait engine is implemented, if you must use borrow you could help the compiler a little bit by telling it what X1 should be:

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

In case you're interested, the following chalk program proves that the new solver can typecheck OP's example

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 []


来源:https://stackoverflow.com/questions/50189976/why-do-i-get-overflow-evaluating-the-requirement-sized-when-using-tokio-ios

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!