我有一段Rust代码可以编译,而另一段代码则非常相似。
有效的那个:
pub fn do_something(_: Box<Iterator<Item = f64>>) {}
fn main() {
let iter = Box::new(vec![1.0].into_iter());
do_something(iter);
}
失败者:
pub fn do_something(_: Box<Box<Iterator<Item = f64>>>) {}
fn main() {
let iter = Box::new(Box::new(vec![1.0].into_iter()));
do_something(iter);
}
区别在于我有一个Box<Box<..>>
而不是Box<..>
我收到以下错误:
error[E0308]: mismatched types
--> src/main.rs:5:18
|
5 | do_something(iter);
| ^^^^ expected trait std::iter::Iterator, found struct `std::vec::IntoIter`
|
= note: expected type `std::boxed::Box<std::boxed::Box<std::iter::Iterator<Item=f64> + 'static>>`
found type `std::boxed::Box<std::boxed::Box<std::vec::IntoIter<{float}>>>`
我正在解释这个错误,说“IntoIter
没有特征Iterator
”..但确实如此。有什么问题?
答案 0 :(得分:2)
老实说,我根本不是Rust的专家,但我的期望是你展示的这两个片段都没有编译。这是因为,正如您所指出的那样,Iterator
是一种特质,而不是一种类型,基本上您希望do_something
接收任何实现Iterator
的类型。也许存在一个快捷方式,使得编译器可以将签名转换为泛型,如果其中一个类型是一个特征,这可能是为什么有时可行的,但那时我也不够熟悉Rust语言规范。 / p>
不要让do_something
采用类型为Iterator
(?)的内容,而是使其成为T
类型的通用,其中T
是特征绑定的。
pub fn do_something<T>(_: Box<Box<T>>)
where T: Iterator<Item = f64> + Send {}
fn main() {
let iter = Box::new(Box::new(vec![1.0].into_iter()));
do_something(iter);
}
或者,您将do_something
完全限制为std::vec::IntoIter
,并仅采用该类型的参数。
pub fn do_something(_: Box<Box<std::vec::IntoIter<f64>>>) {}
fn main() {
let iter = Box::new(Box::new(vec![1.0].into_iter()));
do_something(iter);
}
答案 1 :(得分:2)
由于[{3}}中讨论的原因,您无法将Box<Box<I>>
强制转换为Box<Box<Iterator<Item = f64>>>
,但您可以强制执行内部Box
:
pub fn do_something(_: Box<Box<Iterator<Item = f64>>>) {}
fn main() {
let iter = Box::new(Box::new(vec![1.0].into_iter()) as Box<Iterator<Item = f64>>);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
do_something(iter);
}
这是有效的,因为演员表是Playground。通过编写as Box<Iterator<Item = f64>>
,您可以向编译器暗示它应该尝试使左侧的表达式适合该类型,而不是推断Box<IntoIter<f64>>
,因为一旦它被包裹起来&#34;外部&#34; Box
,您无法再对其进行更改。
或者(但不太清楚),您可以通过明确参数化Box::new(...)
来使Box
成为强制性网站:
let iter = Box::<Box<Iterator<Item = f64>>>::new(Box::new(vec![1.0].into_iter()));
有效地做同样的事情。