Closed vigna closed 11 months ago
Thanks for the report! While I think about a fix or re-design[^1] to palliate this issue, FWIW, you should be able to work around the issue by defining a helper type alias:
type GraphIteratorSuccessors<'next, I> = <I as GraphIterator>::Successors<'next>;
#[::nougat::gat]
impl<I : GraphIterator> LendingIterator for Adapter<I> {
type Item<'next> = (usize, GraphIteratorSuccessors<'next, I>)
where
Self : 'next,
;
fn next(&mut self) -> Option<Self::Item<'_>> {
self.0.next_inner()
}
}
[^1]: I'd like for the next release of lending-iterator
not to need nougat
Thanks for the answer! Next question :), how do I make this work:
pub fn extend<'a, 'b, I: Iterator<Item = usize>, L: LendingIterator<Item<'b> = (usize, I)>>(
&mut self,
iter_nodes: &'b mut L,
){}
as the compiler complains that Item
is not an associated type. I've read your note about using Item<'_,I>
but I need to constrain the type of the returned item instead (note that the answer might obvious, I've been programming Rust since just six months).
So, the main solution here is to be using #[apply(Gat)]
on the fn
. The issue, then, is that LendingIterator
(and nougat) involve for<'next>
kind of bounds, and your 'b
-specific extra bound then makes it run into a limitation of Rust.
There are then two workarounds:
LendingIterator
isn't truly lending / if I
does not depend on 'c
)=
bound, since this allows using an extra line/clause.#[apply(Gat!)]
pub fn extend<'a, 'b, I, L>(
&mut self,
iter_nodes: &'b mut L,
)
where
I : Iterator<Item = usize>,
L : for<'c> LendingIterator<Item<'c> = (usize, I)>,
{
let it: (usize, I) = iter_nodes.next().unwrap();
}
#[apply(Gat!)]
pub fn extend2<'a, 'b, I, L>(
&mut self,
iter_nodes: &'b mut L,
)
where
I : Iterator<Item = usize>,
L : LendingIterator,
// <L as LendingIterator>::Item<'b> = (usize, I) ,
<L as LendingIterator>::Item<'b> : Is<EqTo = (usize, I)>,
{
let it: (usize, I) = Is::eq_to(iter_nodes.next().unwrap());
}
trait Is
helperThat's definitely type magick. I understand that Is::eq_to()
will extract the type, but I can't see how to write a while let Some((x,i)) = iter.next() {}
. I mean, I tried, but...
Yeah, this is a bit subtle to explain; do you happen to be on Discord or some other instant messaging platform? It may be easier to work with there than over here 🙂
The Rust Community Discord server: https://discord.gg/rust-lang-community
You can then create a post over #rust-help-forum
You can then ping me when doing so: @yandros
Otherwise, the TL,DR, if we remove usize
from the situation to simplify things, what you have is (ignoring nougat
syntax sugar/hacks, imagining full GATs all the way):
Yeah, this is a bit subtle to explain; do you happen to be on Discord or some other instant messaging platform? It may be easier to work with there than over here 🙂
I think I'm bothering you more than enough here!
So, thank you a lot for the explanation: turns out I was desperately trying to do what you suggest, but I was looking for Rust syntax that would make it possible to extract the type of a component of a tuple, and I couldn't find any. I didn't think about the trait—that's a bit too far for me.
I've implemented the idea and it seems to work even with actual GATs (using gat_lending_iterator), except that when I try to call a function with the multi-line parameter declaration above using a LendingIterator<Item<'a> = (usize, Self::Successors<'a>)>
I get
the trait bound `for<'c> <_ as gat_lending_iterator::LendingIterator>::Item<'c>: traits::graph::Tuple2` is not satisfied
the trait `traits::graph::Tuple2` is implemented for `(T, U)`
which puzzles me because the item is a 2-tuple. That might be a limitation of the compiler that does not apply to your HKT implementation, but it seems to be something else. I tried to reproduce the situation using your library but I got stuck trying to set the Item type to a pair (possibly I misunderstood the Item<'_,L>
syntax).
Basically, I need to return a LendingIterator<Item<'a> = (usize, Self::Successors<'a>)>
from a function and pass it to another. With the complex signature you propose the function finally compiles, but then it doesn't accept what I would expect as a possible argument with the error above.
If you can share some more wisdom I would be immensely grateful!
And, I was able to make this into a playground.
The following playground compiles
I see—you really need a different definition of lending iterator to make this work.
I realize it is similar to the type structure of your library, so probably the LendingIterator
definition we were using was wrong from the start. Thank you again, I think we'll be able to work out this idea.
So, in the end this was the idea we were looking for. With a bit of 'static
we have been able to make everything work as we were expecting. I credited your contribution in the docs.
This code won't compile:
The problem is that apparently the macro fiddles also with
::Sucessors
, while it should just leave it alone. How can we achieve that?(I realize it is not a compilable snippet, but I think the problem we have is clear—I can produce a compilable example if you need it.)