rust - 为什么在将 tokio_io 的 read_exact 与 Rc 一起使用时会出现“溢出评估要求‘Sized’”?
问题描述
已经发布了很多类似的错误:
我的情况要简单得多,看起来很无辜:
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
应该也可以,我只是不明白为什么我们会出现这个错误。
解决方案
&*conn
和之间的区别在于conn.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!
}
该&*conn
表达式使用Deref
trait,其中每种类型只能有一个Deref
实现。但是,一个类型对于不同的 s可以有多个Borrow<X>
实现。X
当你写
read_exact(conn.borrow(), [0u8]);
编译器需要解决以下义务:
Rc<TcpStream>: Borrow<X1>
由于使用borrow()
&X1: AsyncRead
由于read_exact
请注意,这X1
是一个未知类型。编译器将需要找出所有潜在X1
的 s 并查看是否有人可以同时承担这两项义务。义务 2 以某种方式首先得到了评估,最终得到了这些候选人:
impl<X2> AsyncRead for &PollEvented<X2> where &X2: Read
impl AsyncRead for &TcpStream
impl AsyncRead for &[u8]
可能还有更不重要的候选人......
再次,不知何故,候选人 1 在候选人 2 之前被选中。这导致在候选人 1 被选中后,会产生以下一组新的义务:
Rc<TcpStream>: Borrow<PollEvented<X2>>
解决了!&PollEvented<X2>: AsyncRead
&X2: Read
然后导致impl<X3> Read for &PollEvented<X3> where &X3: Read
被选中,从这一点开始,求解器陷入无限循环并最终放弃。
关于编译器如何求解这些方程的详细信息可以在Rust 编译器指南中找到。
好消息是特征系统正在被修改以使用标准逻辑推理技术(如 Prolog),这允许正确推断 OP 的程序。
但是,在实现新的 trait 引擎之前,如果你必须使用,你可以通过告诉编译器应该是borrow
什么来帮助编译器:X1
read_exact::<&TcpStream, _>(conn.borrow(), [u8]);
// ^~~~~~~~~~ forces &X1 = &TcpStream
如果您有兴趣,以下粉笔程序证明新求解器可以对 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 []
推荐阅读
- python - Python 正则表达式在后面查找列名
- nginx - 使用 API 网关 Ocelot 与 Nginx 的微服务
- image-processing - Image - detect low contrast edge
- javascript - 无法从 openWeatherMap Api 渲染 weather[0].main 属性,它给出了未定义的错误?
- python - 将文本框中的字符串与文件一起发送到 Flask
- xcode - Flutter 生成的 ios 文件版本控制
- python - 如何从亚马逊加拿大抓取数据?
- java - 线程无法读取正在被其他线程修改的实例
- google-api - 如何在未经授权的情况下上传到 YouTube
- excel - 具有可变查找值的过滤范围中的 Vlookup,可变查找范围 VBA