[英]Why are iterator items which are references not cast to a trait object reference?
I'm trying to define a function that should receive an iterator where each item is a reference to a trait object. 我试图定义一个应该接收迭代器的函数,其中每个项目都是对特征对象的引用。 For example:
例如:
use std::fmt::Display;
fn show_items<'a>(items: impl Iterator<Item = &'a Display>) {
items.for_each(|item| println!("{}", item));
}
When I try to call it on an iterator where each item is a reference to a type implementing Display
: 当我尝试在迭代器上调用它时,其中每个项目都是对实现
Display
的类型的引用:
let items: Vec<u32> = (1..10).into_iter().collect();
show_items(items.iter());
I get an error: 我收到一个错误:
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, u32> as std::iter::Iterator>::Item == &dyn std::fmt::Display`
--> src/lib.rs:9:5
|
9 | show_items(items.iter());
| ^^^^^^^^^^ expected u32, found trait std::fmt::Display
|
= note: expected type `&u32`
found type `&dyn std::fmt::Display`
note: required by `show_items`
--> src/lib.rs:3:1
|
3 | fn show_items<'a>(items: impl Iterator<Item = &'a Display>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Why is &u32
not considered as &dyn std::fmt::Display
? 为什么
&u32
不被视为&dyn std::fmt::Display
?
An explicit cast works fine: 显式强制转换可以正常工作:
show_items(items.iter().map(|item| item as &Display));
It also works fine for a single item: 它也可以用于单个项目:
fn show_item(item: &Display) {
println!("{:?}", item);
}
let item: u32 = 1;
show_item(&item);
The implicit conversion from a type T
to dyn Trait
for a Trait
implemented by T
is a so-called unsized coercion , a special kind of coercion. 从类型的隐式转换
T
到dyn Trait
的Trait
通过实施T
是所谓的未分级的强制 ,一种特殊形式的胁迫。 While Rust is somewhat reluctant with implicit type conversions, coercions do happen implicitly at coercion sites , but not in other places. 尽管Rust不太愿意使用隐式类型转换,但强制确实会在强制站点上隐式发生,而在其他地方却不会。
Function call arguments are coercion sites. 函数调用参数是强制站点。 This explains why your
show_item()
function works as desired. 这解释了为什么
show_item()
函数可以show_item()
工作。
All coercions can also be performed explicitly using the as
operator. 还可以使用
as
运算符显式执行所有强制。 For this reason, the version using map()
works fine. 因此,使用
map()
的版本可以正常工作。
Your definition of show_items()
, 您对
show_items()
定义,
fn show_items<'a>(items: impl Iterator<Item = &'a Display>)
on the other hand is a completely different story. 另一方面是完全不同的故事。 The
impl
syntax used here is a shorthand for 这里使用的
impl
语法是的简写
fn show_items<'a, I>(items: I)
where
I: Iterator<Item = &'a dyn Display>,
The function is generic over the iterator type, and the compiler verifies that the type that you actually pass in implements the trait bound Iterator<Item = &'a dyn Display>
. 该函数在迭代器类型上是通用的,并且编译器验证您实际传入的类型是否实现了特征绑定
Iterator<Item = &'a dyn Display>
。 The type std::slice::Iter<'_, u32>
from you example code simply does not, hence the error. 示例代码中的类型
std::slice::Iter<'_, u32>
根本没有,因此出现错误。 There is no coercion that converts an argument to a different type to make it implement some trait bound required by a generic function. 没有强制将参数转换为其他类型以使其实现通用函数所需的某些特征绑定的强制转换。 It is also entirely unclear what type to convert
std::slice::Iter<'_, u32>
to to turn it into an iterator over &dyn Display
. 还完全不清楚将
std::slice::Iter<'_, u32>
转换为通过&dyn Display
进行迭代的类型。
Note that your version of the function definition is unnecessarily restrictive by requiring an iterator over trait objects. 请注意,您的函数定义版本由于需要对特征对象进行迭代而不必要地受到限制。 It would be far more natural and more performant to simply require that the iterator items implement
Display
instead: 仅要求迭代器项改为实现
Display
会更自然,更高效:
fn show_items<I>(items: I)
where
I: IntoIterator,
I::Item: Display,
(I also changed Iterator
to IntoIterator
, since this is more general and more convenient.) (我也将
Iterator
更改为IntoIterator
,因为这更通用,更方便。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.