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?
This is the reverse version of Iterator::try_fold (): it takes elements starting from the back of the iterator. Read more An iterator method that reduces the iterator’s elements to a single, final value, starting from the back. Read more Searches for an element of an iterator from the back that satisfies a predicate. Read more
This has the same lifetime as the original slice, and so the iterator can continue to be used while this exists. Converts this type into a shared reference of the (usually inferred) input type. Returns a copy of the value. Read more Performs copy-assignment from source. Read more Formats the value using the given formatter. Read more
An iterator method that applies a fallible function to each item in the iterator, stopping at the first error and returning that error. Read more Folds every element into an accumulator by applying an operation, returning the final result. Read more Reduces the elements to a single one, by repeatedly applying a reducing operation. Read more
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With