Reputation: 1359
I'm trying to write a simple iterator in 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()
}
}
However, when trying to compile it, I'm getting this error:
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`.
There's a couple things that are confusing about this error message. For one, it seems like Rust isn't able to resolve a core::slice::Iter
as core::iter::Iterator
. But, core::slice::Iter
is an iterator, right? Why aren't these types matching up?
Secondly, I'm seeing an error around expecting IntoIterator
to be a reference rather than a type parameter. However, it's not a type parameter to begin with. What's that about?
What am I doing wrong here? What's Rust trying to tell me about my code?
Upvotes: 5
Views: 1249
Reputation: 15290
There's a couple things that are confusing about this error message.
You're dead right, it's quite a hard message to parse.
it seems like Rust isn't able to resolve a
core::slice::Iter
ascore::iter::Iterator
You're dead wrong: you mis-parsed the message by missing some angle brackets. (I said it was hard to parse!) Let's look at the message, with some crucial bracketing highlighted:
type mismatch resolving `<core::slice::Iter<'_, T> as core::iter::Iterator>::Item == T`
(________________________________________________)
The problem isn't resolving core::slice::Iter<'_, T>
as core::iter::Iterator
, it's resolving the equality, where the whole expression <core::slice::Iter<'_, T> as core::iter::Iterator>::Item
is the left-hand side. That whole mess names a single type: it's the type you get by using the as
operator to upcast core::slice::Iter<'_, T>
to core::iter::Iterator
, and then take the Item
member of it.
The trait IntoIterator
is defined as follows:
pub trait IntoIterator where
<Self::IntoIter as Iterator>::Item == Self::Item
That is, to implement the trait, you need to satisfy the requirement given. This is the requirement the compiler is complaining about. You've defined Item
as T
, and IntoIter
as core::slice::Iter<'_, T>
, but putting those two definitions in doesn't satisfy the equality.
Put another way, to implement IntoIterator
, you need to define an Item
type, it needs to be the same as your underlying iterator's Item
type. core::slice::Iter<'a, T>
defines its Item
type like this:
type Item = &'a T
so you need the same definition in your impl
block.
Here's a Playground with your definition fixed, and an empty main()
so it'll compile.
Upvotes: 7
Reputation: 15559
For one, it seems like Rust isn't able to resolve a core::slice::Iter as core::iter::Iterator. But, core::slice::Iter is an iterator, right? Why aren't these types matching up?
You're missing the crucial part of the message:
type mismatch resolving
<std::slice::Iter<'_, T> as std::iter::Iterator>::Item == T
It can't resolve it *as an iterator with the Item
type as T
.
This is because slice::Iter
is an iterator over references, not values.
Upvotes: 2