无法将core::slice::Iter解析为core::iter::Iterator?

5

我正在尝试在Rust中编写一个简单的迭代器:

#[derive(Debug)]
pub struct StackVec<'a, T: 'a> {
    storage: &'a mut [T],
    len: usize,
    _head: usize,
}

impl<'a, T> IntoIterator for StackVec<'a, T> {
    type Item = T;
    type IntoIter = core::slice::Iter<'a, T>;

    fn into_iter(self) -> core::slice::Iter<'a, T> {
        self.storage.iter()
    }
}

然而,当尝试编译它时,我收到了这个错误:
error[E0271]: type mismatch resolving `<core::slice::Iter<'_, T> as core::iter::Iterator>::Item == T`
   --> src/lib.rs:135:13
    |
135 | impl<'a, T> IntoIterator for StackVec<'a, T> {
    |             ^^^^^^^^^^^^ expected reference, found type parameter
    |
    = note: expected type `&T`
               found type `T`

error: aborting due to previous error

error: Could not compile `stack-vec`.

这个错误信息有几个地方让人感到困惑。首先,似乎Rust无法将core::slice::Iter解析为core::iter::Iterator。但是,core::slice::Iter确实是一个迭代器,对吧?为什么这些类型不匹配呢?
其次,在期望IntoIterator是引用而不是类型参数时,我看到了一个错误。然而它一开始就不是一个类型参数。这是怎么回事?
我在这里做错了什么?Rust试图告诉我有关我的代码的什么?
2个回答

7
以下是翻译的结果:

关于这个错误信息有几件事情让人困惑。

你说得对,这是一个很难解析的消息。

看起来 Rust 无法将 core::slice::Iter 解析为 core::iter::Iterator

你说错了:你错过了一些尖括号而误解了这个消息。(我说过这很难解析!) 让我们看一下该消息,并突出显示一些关键的括号:

type mismatch resolving `<core::slice::Iter<'_, T> as core::iter::Iterator>::Item == T`
                         (________________________________________________)

问题不在于将core::slice::Iter<'_, T>解析为core::iter::Iterator,而在于解析相等性,其中整个表达式<core::slice::Iter<'_, T> as core::iter::Iterator>::Item是左侧。这整个混乱的名称表示单个类型:它是通过使用as运算符将core::slice::Iter<'_, T>向上转型为core::iter::Iterator,然后获取其Item成员而得到的类型。 IntoIterator特质定义如下:
pub trait IntoIterator where
    <Self::IntoIter as Iterator>::Item == Self::Item

换句话说,为了实现这个特性,你需要满足给定的要求。这就是编译器抱怨的要求。你已将 Item 定义为 T,并将 IntoIter 定义为 core::slice::Iter<'_, T>,但将这两个定义放在一起并不能满足相等性。
换句话说,为了实现 IntoIterator,你需要定义一个 Item 类型,并且它需要与你底层迭代器的 Item 类型相同。 core::slice::Iter<'a, T> 将其 Item 类型定义为:
type Item = &'a T

因此,您需要在impl块中使用相同的定义。

这里有一个修复了您的定义的Playground,以及一个空的main()函数,以便编译。


啊!谢谢你的帮助!现在完全明白了。 - bioball

2
首先,似乎 Rust 无法将 core::slice::Iter 解析为 core::iter::Iterator。但是,core::slice::Iter 是一个迭代器,对吧?为什么这些类型不能匹配呢?
您错过了消息的关键部分:
类型不匹配,解决 as std::iter::Iterator>::Item == T
它无法将其解析为具有 Item 类型为 T 的迭代器。
这是因为 slice::Iter 是引用的迭代器,而不是值的迭代器。

所以,我尝试将我的实现更改为:self.storage.into_iter(),但我仍然看到相同的错误消息。那应该返回值的迭代器,而不是引用,对吧? - bioball
@bioball,你的self.storage是一个可变数据引用,是某个其他地方拥有的一些数据的切片。在&mut [T]上调用into_iter不会给你一个拥有值的迭代器,因为你一开始就没有拥有这些数据。 - turbulencetoo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接