尝试将&[u8]
作为参数提供给需要Read
的函数似乎无法正常工作,如下例所示。
use std::io::Read;
fn main() {
let bytes: &[u8] = &[1, 2, 3, 4];
print_reader(&bytes);
}
fn print_reader(reader: &(Read + Sized)) {
for byte in reader.bytes() {
println!("{}", byte.unwrap());
}
}
编译错误:
error: the trait bound `std::io::Read + Sized: std::marker::Sized` is not satisfied [--explain E0277]
--> <anon>:9:24
9 |> for byte in reader.bytes() {
|> ^^^^^
note: `std::io::Read + Sized` does not have a constant size known at compile-time
error: the trait bound `std::io::Read + Sized: std::marker::Sized` is not satisfied [--explain E0277]
--> <anon>:9:5
9 |> for byte in reader.bytes() {
|> ^
note: `std::io::Read + Sized` does not have a constant size known at compile-time
note: required because of the requirements on the impl of `std::iter::Iterator` for `std::io::Bytes<std::io::Read + Sized>`
error: aborting due to 2 previous errors
可以在std::slice
文档中找到以下特征实现:
impl<'a> Read for &'a [u8]
。
答案 0 :(得分:2)
我认为这是一个相当无用的错误消息。我试着解释一下:
首先:您不能拥有特征对象&Sized
。这违反了first object safety rule,它也没有任何意义。添加Sized
特征限制的唯一原因是使用所有Sized
类型的特殊属性(例如,将其保存在堆栈中)。看看这个例子试图使用属性:
fn foo(x: &Sized) {
let y = *x;
}
y
的大小是多少?编译器不能像任何其他特征对象那样知道。因此,我们无法将Sized
的唯一目的用于特征对象。因此,特质对象&Sized
是无用的,并且不存在。
在这种情况下,错误消息至少会告诉我们正确的事情:
error: the trait `std::marker::Sized` cannot be made into an object [--explain E0038]
--> <anon>:7:1
7 |> fn foo(x: &Sized) {
|> ^
note: the trait cannot require that `Self : Sized`
此外:我怀疑你添加+ Sized
绑定可以解决同一个错误,当你有参数reader: &Read
时就已经出现了错误。以下是详细错误描述的一个重要见解:
通常,
Self : Sized
用于表示特征不应用作特征对象。
Read::bytes
的这个限制确实有意义,因为Bytes
迭代器会为每个字节调用Read::read()
一次。如果此函数调用是虚拟/动态调用,则函数调用的开销将远远高于read
字节的实际过程。
所以...... 为什么你需要将Read
作为特征对象呢?通过泛型来处理这个问题通常是足够的(并且在任何情况下要快得多):
fn print_reader<R: Read>(reader: R) {
for byte in reader.bytes() {
println!("{}", byte.unwrap());
}
}
这可以避免动态调度,并且可以与类型检查器和优化器一起使用。