Rust - Specifying a Lifetime Parameter for the Borrow Trait - rust

I have a struct (DataSource) that holds some data (&[u8]), and a custom iterator that iterates over it.
struct DataSource<'a> {
data: &'a Vec<u8>,
}
struct MyIterator<'a> {
source: DataSource<'a>,
}
impl<'a> Iterator for MyIterator<'a> {
type Item = &'a u8;
fn next(&mut self) -> Option<Self::Item> {
let ret = &self.source.data[0];
Some(ret)
}
}
Notice a few important things here:
The Item of the iterator has a lifetime. This is only possible because the lifetime is already used by one of the struct's fields - source
The compiler is smart enough to detect that since Items lifetime is 'a, the lifetime of ret must also be 'a.
Now, due to my use-case, I would like to add the following features:
DataSource should also be able to own data.
data is not Clone.
My initial solution was to replalce data: &'a [u8] with data: D where D: Borrow<[u8]>:
struct DataHolder<D: Borrow<[u8]>> {
data: D,
}
struct MyIterator<D: Borrow<[u8]>> {
holder: DataHolder<D>,
}
impl<D: Borrow<[u8]>> Iterator for MyIterator<D> {
type Item = &u8;
fn next(&mut self) -> Option<Self::Item> {
Some(&self.holder.data.borrow()[0])
}
}
I thought this would work since due to blanket implementations both &[u8] and [u8] implement Borrow<[u8]>. However this doesn't compile. The iterator's item is &u8 so it requires an explicit lifetime. MyIterator doesn't have any lifetimes to reference so writing type Item = &'a u8 would result in an undeclared lifetime.
My next solution was to add phantom data and reference the lifetime through that:
struct DataHolder<'a, D: Borrow<[u8]>, T: 'a> {
data: D,
p: PhantomData<&'a T>,
}
struct MyIterator<'a, D: Borrow<[u8]>, T: 'a> {
holder: DataHolder<'a, D, T>,
}
impl<'a, D: Borrow<[u8]>, T> Iterator for MyIterator<'a, D, T> {
type Item = &'a u8;
fn next(&mut self) -> Option<Self::Item> {
Some(&self.holder.data.borrow()[0])
}
}
Which produces the following error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src\bin\main7c.rs:16:26
|
16 | Some(&self.holder.data.borrow()[0])
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src\bin\main7c.rs:15:10
|
15 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src\bin\main7c.rs:16:9
|
16 | Some(&self.holder.data.borrow()[0])
| ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src\bin\main7c.rs:12:6
|
12 | impl<'a, D: Borrow<[u8]>, T> Iterator for MyIterator<'a, D, T> {
| ^^
note: ...so that the types are compatible
--> src\bin\main7c.rs:15:43
|
15 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
16 | | Some(&self.holder.data.borrow()[0])
17 | | }
| |_____^
= note: expected `<MyIterator<'a, D, T> as Iterator>`
found `<MyIterator<'_, D, T> as Iterator>`
The compiler can't infer that the lifetime of the returned value must be 'a like in the first example. I could solve this giving up on implementing Iterator but that would defeat the whole point of using an iterator.
impl<'a, D: Borrow<[u8]>, T> MyIterator<'a, D, T> {
fn next(&'a mut self) -> Option<&'a u8> {
Some(&self.holder.data.borrow()[0])
}
}
Is there a way of solving this without giving up on the Iterator trait?

Is there a way of solving this without giving up on the Iterator trait?
No. Suppose D is Vec<u8>. What would be the lifetime 'a?
When it was already a reference, we could just reuse its lifetime. This is because, assuming data is &'a T, &self.data[0] where self is &'b mut self can be seen as (pseudo-Rust):
let slice_data_pointer: &'a u8 = (*self.data);
slice_data_pointer
That is, we just copy the reference.
But when data is owned, there is no reference to be copied. The only source of truth is self.data itself - and self.data is borrowed only for the lifetime of self. So you need the yielded values of iterator to depend on next()'s self. This is the classic lending/streaming iterator, and it:
Doesn't exist in the standard library.
Requires Generic Associated Types (which is part of the reason it is not in the standard library).
Allows only one yielded value to exist at any time - they can't coexist, because they all borrow mutably from self with different lifetimes. In other words, it cannot implement operations like collect().
However, we can learn from the way the actual Vec impls Iterator. Specifically, it doesn't - and so do owned values in general - they implement IntoIterator instead for a reference to them, potentially with an iter() method.

Related

Error while implementing iterator on a struct with a mutable life time

i was trying to implement an iterator over a complex struct, and to do that i decided to use a support structure, which points to the original one. (to do that i had to use lifetimes). i wrote the code for the reference iterator and it works. but if i write the same code for a mutable reference it doesn't work, the weird thing is that the error seems to have to do with lifetimes, and not with ownership
here is the code for iterating over the reference, and it works:
struct Iter<'a>{
vec: &'a i32// i32 is just an example, assume is a more complex strict
}
impl<'a> Iterator for Iter<'a>{
type Item = &'a i32;
fn next(&mut self) -> Option<Self::Item> {
Option::Some(self.vec)//assume this actually iterate over something, again... is just an example
}
}
here is the same code, but with mutable reference and it doesn't compile:
struct IterMut<'a>{
vec: &'a mut i32
}
impl<'a> Iterator for IterMut<'a>{
type Item = &'a mut i32;
fn next(&mut self) -> Option<Self::Item> {
Option::Some(self.vec)
}
}
the error i get is the following:
error: lifetime may not live long enough
--> src\main.rs:19:9
|
16 | impl<'a> Iterator for IterMut<'a>{
| -- lifetime `'a` defined here
17 | type Item = &'a mut i32;
18 | fn next(&mut self) -> Option<Self::Item> {
| - let's call the lifetime of this reference `'1`
19 | Option::Some(self.vec)
| ^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
could someone tell me why it doesn't work, and why it does work in the first example? (even if the lifetimes are exactly the same)
The problem is shared references are Copy while mutable ones are not.
For your simple example this would work.
struct IterMut<'a>{
vec: Option<&'a mut i32>
}
impl<'a> Iterator for IterMut<'a>{
type Item = &'a mut i32;
fn next(&mut self) -> Option<Self::Item> {
self.vec.take()
}
}
The gist is you can't hold on to the reference you're returning.

Trying To Understand Generic Lifetime Parameters [duplicate]

I have created a data structure in Rust and I want to create iterators for it. Immutable iterators are easy enough. I currently have this, and it works fine:
// This is a mock of the "real" EdgeIndexes class as
// the one in my real program is somewhat complex, but
// of identical type
struct EdgeIndexes;
impl Iterator for EdgeIndexes {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
Some(0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
pub struct CGraph<E> {
nodes: usize,
edges: Vec<E>,
}
pub struct Edges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a CGraph<E>,
}
impl<'a, E> Iterator for Edges<'a, E> {
type Item = &'a E;
fn next(&mut self) -> Option<Self::Item> {
match self.index.next() {
None => None,
Some(x) => Some(&self.graph.edges[x]),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
I want to create a iterator that returns mutable references as well. I've tried doing this, but can't find a way to get it to compile:
pub struct MutEdges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a mut CGraph<E>,
}
impl<'a, E> Iterator for MutEdges<'a, E> {
type Item = &'a mut E;
fn next(&mut self) -> Option<&'a mut E> {
match self.index.next() {
None => None,
Some(x) => self.graph.edges.get_mut(x),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
Compiling this results in the following error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 51:5...
--> src/lib.rs:51:5
|
51 | / fn next(&mut self) -> Option<&'a mut E> {
52 | | match self.index.next() {
53 | | None => None,
54 | | Some(x) => self.graph.edges.get_mut(x),
55 | | }
56 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 48:6...
--> src/lib.rs:48:6
|
48 | impl<'a, E> Iterator for MutEdges<'a, E> {
| ^^
= note: ...so that the expression is assignable:
expected std::option::Option<&'a mut E>
found std::option::Option<&mut E>
I'm unsure how to interpret these errors and how to change my code in order to allow MutEdges to return mutable references.
Link to playground with code.
You can't compile this because mutable references are more restrictive than immutable references. A shortened version that illustrates the issue is this:
struct MutIntRef<'a> {
r: &'a mut i32
}
impl<'a> MutIntRef<'a> {
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
}
fn main() {
let mut i = 42;
let mut mir = MutIntRef { r: &mut i };
let p = mir.mut_get();
let q = mir.mut_get();
println!("{}, {}", p, q);
}
Which produces the same error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / fn mut_get(&mut self) -> &'a mut i32 {
7 | | &mut *self.r
8 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> MutIntRef<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
If we take a look at the main function, we get two mutable references called p and q that both alias the memory location of i. This is not allowed. In Rust, we can't have two mutable references that alias and are both usable. The motivation for this restriction is the observation that mutation and aliasing don't play well together with respect to memory safety. So, it's good that the compiler rejected the code. If something like this compiled, it would be easy to get all kinds of memory corruption errors.
The way Rust avoids this kind of danger is by keeping at most one mutable reference usable. So, if you want to create mutable reference to X based on a mutable reference to Y where X is owned by Y, we better make sure that as long as the reference to X exists, we can't touch the other reference to Y anymore. In Rust this is achieved through lifetimes and borrowing. The compiler considers the original reference to be borrowed in such a case and this has an effect on the lifetime parameter of the resulting reference as well. If we change
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
to
fn mut_get(&mut self) -> &mut i32 { // <-- no 'a anymore
&mut *self.r // Ok!
}
the compiler stops complaining about this get_mut function. It now returns a reference with a lifetime parameter that matches &self and not 'a anymore. This makes mut_get a function with which you "borrow" self. And that's why the compiler complains about a different location:
error[E0499]: cannot borrow `mir` as mutable more than once at a time
--> src/main.rs:15:13
|
14 | let p = mir.mut_get();
| --- first mutable borrow occurs here
15 | let q = mir.mut_get();
| ^^^ second mutable borrow occurs here
16 | println!("{}, {}", p, q);
| - first borrow later used here
Apparently, the compiler really did consider mir to be borrowed. This is good. This means that now there is only one way of reaching the memory location of i: p.
Now you may wonder: How did the standard library authors manage to write the mutable vector iterator? The answer is simple: They used unsafe code. There is no other way. The Rust compiler simply does not know that whenever you ask a mutable vector iterator for the next element, that you get a different reference every time and never the same reference twice. Of course, we know that such an iterator won't give you the same reference twice and that makes it safe to offer this kind of interface you are used to. We don't need to "freeze" such an iterator. If the references an iterator returns don't overlap, it's safe to not have to borrow the iterator for accessing an element. Internally, this is done using unsafe code (turning raw pointers into references).
The easy solution for your problem might be to rely on MutItems. This is already a library-provided mutable iterator over a vector. So, you might get away with just using that instead of your own custom type, or you could wrap it inside your custom iterator type. In case you can't do that for some reason, you would have to write your own unsafe code. And if you do so, make sure that
You don't create multiple mutable references that alias. If you did, this would violate the Rust rules and invoke undefined behavior.
You don't forget to use the PhantomData type to tell the compiler that your iterator is a reference-like type where replacing the lifetime with a longer one is not allowed and could otherwise create a dangling iterator.

Trait associated type lifetime and self

I have a struct that wraps a std::cell::Ref and provides access by reference to the underlying value. Something like this:
use std::cell::Ref;
struct IntAccess<'a> {
i: Ref<'a, i32>,
}
impl IntAccess<'_> {
fn get(&self) -> &i32 {
&self.i
}
}
This works fine. Since I have multiple structs like this, I'd like to define a common trait:
trait Access {
type Item;
fn get(&self) -> Self::Item;
}
However, I get into trouble when trying to implement Access for IntAccess:
impl<'a> Access for IntAccess<'a> {
type Item = &'a i32;
fn get(&self) -> Self::Item {
&self.i
}
}
It fails with the following error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:23:9
|
23 | &self.i
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/main.rs:22:12
|
22 | fn get(&self) -> Self::Item {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:23:9
|
23 | &self.i
| ^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/main.rs:19:6
|
19 | impl<'a> Access for IntAccess<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:22:33
|
22 | fn get(&self) -> Self::Item {
| _________________________________^
23 | | &self.i
24 | | }
| |_____^
= note: expected `<IntAccess<'a> as Access>`
found `<IntAccess<'_> as Access>`
I think I kind of get what the compiler is trying to tell me: I'm trying to borrow self.i which has an anonymous lifetime unrelated to the lifetime of Self::Item ('a). So what seems to be needed is to somehow tie the lifetime of self in get to the lifetime 'a. Is there a way to do this?
I have to admit that I don't fully grasp the problem. Since I pass the lifetime 'a to the Ref, and Ref internally stores a reference with this lifetime, it seems to me that it should somehow be possible to get a reference with lifetime 'a out of it without having to explicitly tie self to this lifetime as well. So what am I missing here?
Your understanding is correct. About your doubt, let's name the lifetimes for easier debugging:
impl<'a> Access for IntAccess<'a> {
type Item = &'a i32;
fn get<'b>(&'b self) -> Self::Item {
&self.i
}
}
self has the type &'b IntAccess<'a>. 'b is shorter than or equal to 'a - that is required for self to be well-formed, i.e. able to exist (otherwise, it would contain a dangling reference).
For that reason, we cannot borrow self for more than 'b - or we could do something like:
let v: IntAccess<'a>;
let inner: &'a i32 = {
let r: &'b IntAccess<'a> = &v;
<IntAccess<'a> as Access>::get(r)
}
let mut_r: &mut IntAccess<'a> = &mut v;
And we have both a shared and a mutable reference to (parts of) inner!
Your problem cannot be solved fully without Generic Associated Types. They allow you to parameterize an associated type by a lifetime, making it able to express "I want to return this associated type tied to the lifetime of self":
#![feature(generic_associated_types)]
trait Access {
type Item<'a>
where
Self: 'a;
fn get<'a>(&'a self) -> Self::Item<'a>;
// Or, with lifetime elision:
// fn get(&self) -> Self::Item<'_>;
}
impl<'a> Access for IntAccess<'a> {
type Item<'b> = &'b i32
where
'a: 'b;
fn get<'b>(&'b self) -> Self::Item<'b> {
&self.i
}
}
Playground.
Can we do that on stable? We can emulate that. Instead of implementing Access for IntAccess itself, we will implement it for a reference to it!
trait Access {
type Item;
fn get(self) -> Self::Item;
}
impl<'a, 'b> Access for &'b IntAccess<'a> {
type Item = &'b i32;
fn get(self) -> &'b i32 {
&self.i
}
}
Playground
This does not always work, and thus is not a full replacement to GATs, but is good enough in this case.

Cannot infer lifetime when implementing mutable iterator [duplicate]

I have created a data structure in Rust and I want to create iterators for it. Immutable iterators are easy enough. I currently have this, and it works fine:
// This is a mock of the "real" EdgeIndexes class as
// the one in my real program is somewhat complex, but
// of identical type
struct EdgeIndexes;
impl Iterator for EdgeIndexes {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
Some(0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
pub struct CGraph<E> {
nodes: usize,
edges: Vec<E>,
}
pub struct Edges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a CGraph<E>,
}
impl<'a, E> Iterator for Edges<'a, E> {
type Item = &'a E;
fn next(&mut self) -> Option<Self::Item> {
match self.index.next() {
None => None,
Some(x) => Some(&self.graph.edges[x]),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
I want to create a iterator that returns mutable references as well. I've tried doing this, but can't find a way to get it to compile:
pub struct MutEdges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a mut CGraph<E>,
}
impl<'a, E> Iterator for MutEdges<'a, E> {
type Item = &'a mut E;
fn next(&mut self) -> Option<&'a mut E> {
match self.index.next() {
None => None,
Some(x) => self.graph.edges.get_mut(x),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
Compiling this results in the following error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 51:5...
--> src/lib.rs:51:5
|
51 | / fn next(&mut self) -> Option<&'a mut E> {
52 | | match self.index.next() {
53 | | None => None,
54 | | Some(x) => self.graph.edges.get_mut(x),
55 | | }
56 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:54:24
|
54 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 48:6...
--> src/lib.rs:48:6
|
48 | impl<'a, E> Iterator for MutEdges<'a, E> {
| ^^
= note: ...so that the expression is assignable:
expected std::option::Option<&'a mut E>
found std::option::Option<&mut E>
I'm unsure how to interpret these errors and how to change my code in order to allow MutEdges to return mutable references.
Link to playground with code.
You can't compile this because mutable references are more restrictive than immutable references. A shortened version that illustrates the issue is this:
struct MutIntRef<'a> {
r: &'a mut i32
}
impl<'a> MutIntRef<'a> {
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
}
fn main() {
let mut i = 42;
let mut mir = MutIntRef { r: &mut i };
let p = mir.mut_get();
let q = mir.mut_get();
println!("{}, {}", p, q);
}
Which produces the same error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / fn mut_get(&mut self) -> &'a mut i32 {
7 | | &mut *self.r
8 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> MutIntRef<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:9
|
7 | &mut *self.r
| ^^^^^^^^^^^^
If we take a look at the main function, we get two mutable references called p and q that both alias the memory location of i. This is not allowed. In Rust, we can't have two mutable references that alias and are both usable. The motivation for this restriction is the observation that mutation and aliasing don't play well together with respect to memory safety. So, it's good that the compiler rejected the code. If something like this compiled, it would be easy to get all kinds of memory corruption errors.
The way Rust avoids this kind of danger is by keeping at most one mutable reference usable. So, if you want to create mutable reference to X based on a mutable reference to Y where X is owned by Y, we better make sure that as long as the reference to X exists, we can't touch the other reference to Y anymore. In Rust this is achieved through lifetimes and borrowing. The compiler considers the original reference to be borrowed in such a case and this has an effect on the lifetime parameter of the resulting reference as well. If we change
fn mut_get(&mut self) -> &'a mut i32 {
&mut *self.r
}
to
fn mut_get(&mut self) -> &mut i32 { // <-- no 'a anymore
&mut *self.r // Ok!
}
the compiler stops complaining about this get_mut function. It now returns a reference with a lifetime parameter that matches &self and not 'a anymore. This makes mut_get a function with which you "borrow" self. And that's why the compiler complains about a different location:
error[E0499]: cannot borrow `mir` as mutable more than once at a time
--> src/main.rs:15:13
|
14 | let p = mir.mut_get();
| --- first mutable borrow occurs here
15 | let q = mir.mut_get();
| ^^^ second mutable borrow occurs here
16 | println!("{}, {}", p, q);
| - first borrow later used here
Apparently, the compiler really did consider mir to be borrowed. This is good. This means that now there is only one way of reaching the memory location of i: p.
Now you may wonder: How did the standard library authors manage to write the mutable vector iterator? The answer is simple: They used unsafe code. There is no other way. The Rust compiler simply does not know that whenever you ask a mutable vector iterator for the next element, that you get a different reference every time and never the same reference twice. Of course, we know that such an iterator won't give you the same reference twice and that makes it safe to offer this kind of interface you are used to. We don't need to "freeze" such an iterator. If the references an iterator returns don't overlap, it's safe to not have to borrow the iterator for accessing an element. Internally, this is done using unsafe code (turning raw pointers into references).
The easy solution for your problem might be to rely on MutItems. This is already a library-provided mutable iterator over a vector. So, you might get away with just using that instead of your own custom type, or you could wrap it inside your custom iterator type. In case you can't do that for some reason, you would have to write your own unsafe code. And if you do so, make sure that
You don't create multiple mutable references that alias. If you did, this would violate the Rust rules and invoke undefined behavior.
You don't forget to use the PhantomData type to tell the compiler that your iterator is a reference-like type where replacing the lifetime with a longer one is not allowed and could otherwise create a dangling iterator.

Implement chain() for a GATified Lending Iterator

I am trying to implement an Iterator::chain()-like operation for a GATified lending iterator:
#![feature(generic_associated_types)]
pub trait LendingIterator {
type Item<'a> where Self: 'a;
fn next(&mut self) -> Option<Self::Item<'_>>;
}
To do this, similarly to the normal Iterator::chain(), I need a struct Chain that contains the two chained iterators and impl's LendingIterator.
The problem I have is I need to specify the iterator types A and B having matching Item generic associated types, so I tried this:
pub struct Chain<A, B> {
a: Option<A>,
b: Option<B>,
}
impl<A, B> LendingIterator for Chain<A, B>
where
A: LendingIterator,
B: for<'a> LendingIterator<Item<'a>=A::Item<'a>>
{
type Item<'a> where Self: 'a = A::Item<'a>;
fn next(&mut self) -> Option<Self::Item<'_>> {
todo!()
}
}
But I get:
error[E0311]: the parameter type `B` may not live long enough
--> src\lib.rs:63:12
|
63 | impl<A, B> LendingIterator for Chain<A, B> where A: LendingIterator, B: for<'a> LendingIterator<Item<'a>=A::Item<'a>> {
| - ^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds...
| |
| help: consider adding an explicit lifetime bound...: `B: 'a`
|
note: ...that is required by this bound
| ^^^^ ...so that the type `B` will meet its required lifetime bounds
Of course the compiler's suggestions don't seem to work.
How can I add the constraint that B does have a long enough lifetime?
Turns out this is a bug in rust's GAT implementation. See this:
https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/.E2.9C.94.20GAT.20LendingIterator.3A.3Achain.20Issue
https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Understanding.20the.20motivations.20for.20GATs/near/269863728

Resources