pub trait LendingIterator where
    Self: for<'next> LendingIteratorඞItem<'next>, 
{
Show 27 methods fn next(&mut self) -> Option<Item<'_, Self>>; fn filter<F>(self, should_yield: F) -> Filter<Self, F>Notable traits for Filter<I, F>impl<'next, I, F> LendingIteratorඞItem<'next, &'next Filter<I, F>> for Filter<I, F> where
    I: LendingIterator,
    F: FnMut(&Item<'_, I>) -> bool
type T = Item<'next, I>;

    where
        Self: Sized,
        F: FnMut(&Item<'_, Self>) -> bool
, { ... } fn for_each(self, f: impl FnMut(Item<'_, Self>))
    where
        Self: Sized
, { ... } fn fold<Acc>(self, acc: Acc, f: impl FnMut(Acc, Item<'_, Self>) -> Acc) -> Acc
    where
        Self: Sized
, { ... } fn try_for_each<Err>(
        &mut self,
        f: impl FnMut(Item<'_, Self>) -> Result<(), Err>
    ) -> Result<(), Err> { ... } fn try_fold<Acc, Err>(
        &mut self,
        acc: Acc,
        f: impl FnMut(Acc, Item<'_, Self>) -> Result<Acc, Err>
    ) -> Result<Acc, Err> { ... } fn all(&mut self, predicate: impl FnMut(Item<'_, Self>) -> bool) -> bool
    where
        Self: Sized
, { ... } fn any(&mut self, predicate: impl FnMut(Item<'_, Self>) -> bool) -> bool
    where
        Self: Sized
, { ... } fn by_ref(&mut self) -> &mut SelfNotable traits for &'r mut Iimpl<'next, 'r, I: ?Sized + LendingIterator> LendingIteratorඞItem<'next, &'next &'r mut I> for &'r mut I type T = Item<'next, I>;impl<'next, 'r, I: ?Sized + LendingIterator> LendingIteratorඞItem<'next, &'next Pin<&'r mut I>> for Pin<&'r mut I> where
    I: Unpin
type T = Item<'next, I>;

    where
        Self: Sized
, { ... } fn count(self) -> usize
    where
        Self: Sized
, { ... } fn find<'find>(
        &'find mut self,
        predicate: impl 'find + FnMut(&Item<'_, Self>) -> bool
    ) -> Option<Item<'find, Self>>
    where
        Self: Sized
, { ... } fn fuse(self) -> Fuse<Self>Notable traits for Fuse<I>impl<'next, I: LendingIterator> LendingIteratorඞItem<'next, &'next Fuse<I>> for Fuse<I> type T = Item<'next, I>;
    where
        Self: Sized
, { ... } fn nth(&mut self, n: usize) -> Option<Item<'_, Self>> { ... } fn position<F>(
        &mut self,
        predicate: impl FnMut(Item<'_, Self>) -> bool
    ) -> Option<usize>
    where
        Self: Sized
, { ... } fn skip(self, count: usize) -> Skip<Self>Notable traits for Skip<I>impl<'next, I: LendingIterator> LendingIteratorඞItem<'next, &'next Skip<I>> for Skip<I> type T = Item<'next, I>;
    where
        Self: Sized
, { ... } fn take(self, count: usize) -> Take<Self>Notable traits for Take<I>impl<'next, I: LendingIterator> LendingIteratorඞItem<'next, &'next Take<I>> for Take<I> type T = Item<'next, I>;
    where
        Self: Sized
, { ... } fn map<NewItemType: HKT, F>(self, f: F) -> Map<Self, F, NewItemType>Notable traits for Map<I, F, NewItemType>impl<'next, I, NewItemType, F> LendingIteratorඞItem<'next, &'next Map<I, F, NewItemType>> for Map<I, F, NewItemType> where
    I: LendingIterator,
    NewItemType: HKT,
    for<'any> F: FnMut([&'any I; 0], Item<'any, I>) -> Feed<'any, NewItemType>, 
type T = Feed<'next, NewItemType>;

    where
        for<'next> F: FnMut([&'next Self; 0], Item<'next, Self>) -> Feed<'next, NewItemType>,
        Self: Sized
, { ... } fn map_to_ref<R: ?Sized, F>(self, f: F) -> Map<Self, F, HKTRef<R>>Notable traits for Map<I, F, NewItemType>impl<'next, I, NewItemType, F> LendingIteratorඞItem<'next, &'next Map<I, F, NewItemType>> for Map<I, F, NewItemType> where
    I: LendingIterator,
    NewItemType: HKT,
    for<'any> F: FnMut([&'any I; 0], Item<'any, I>) -> Feed<'any, NewItemType>, 
type T = Feed<'next, NewItemType>;

    where
        for<'any> F: FnMut([&'any Self; 0], Item<'any, Self>) -> &'any R,
        Self: Sized
, { ... } fn map_to_mut<R: ?Sized, F>(self, f: F) -> Map<Self, F, HKTRefMut<R>>Notable traits for Map<I, F, NewItemType>impl<'next, I, NewItemType, F> LendingIteratorඞItem<'next, &'next Map<I, F, NewItemType>> for Map<I, F, NewItemType> where
    I: LendingIterator,
    NewItemType: HKT,
    for<'any> F: FnMut([&'any I; 0], Item<'any, I>) -> Feed<'any, NewItemType>, 
type T = Feed<'next, NewItemType>;

    where
        for<'any> F: FnMut([&'any Self; 0], Item<'any, Self>) -> &'any mut R,
        Self: Sized
, { ... } fn map_into_iter<F, NonLendingItem>(self, f: F) -> MapIntoIter<Self, F>Notable traits for MapIntoIter<I, F>impl<I, F, R> Iterator for MapIntoIter<I, F> where
    I: LendingIterator,
    F: FnMut(Item<'_, I>) -> R, 
type Item = R;

    where
        F: FnMut(Item<'_, Self>) -> NonLendingItem,
        Self: Sized
, { ... } fn filter_map<NewItemType: HKT, F>(
        self,
        f: F
    ) -> FilterMap<Self, F, NewItemType>Notable traits for FilterMap<I, F, NewItemType>impl<'next, I, NewItemType, F> LendingIteratorඞItem<'next, &'next FilterMap<I, F, NewItemType>> for FilterMap<I, F, NewItemType> where
    I: LendingIterator,
    NewItemType: HKT,
    for<'any> F: FnMut([&'any I; 0], Item<'any, I>) -> Option<Feed<'any, NewItemType>>, 
type T = Feed<'next, NewItemType>;

    where
        for<'next> F: FnMut([&'next Self; 0], Item<'next, Self>) -> Option<Feed<'next, NewItemType>>,
        Self: Sized
, { ... } fn filter_map_to_ref<R: ?Sized, F>(
        self,
        f: F
    ) -> FilterMap<Self, F, HKTRef<R>>Notable traits for FilterMap<I, F, NewItemType>impl<'next, I, NewItemType, F> LendingIteratorඞItem<'next, &'next FilterMap<I, F, NewItemType>> for FilterMap<I, F, NewItemType> where
    I: LendingIterator,
    NewItemType: HKT,
    for<'any> F: FnMut([&'any I; 0], Item<'any, I>) -> Option<Feed<'any, NewItemType>>, 
type T = Feed<'next, NewItemType>;

    where
        for<'any> F: FnMut([&'any Self; 0], Item<'any, Self>) -> Option<&'any R>,
        Self: Sized
, { ... } fn filter_map_to_mut<R: ?Sized, F>(
        self,
        f: F
    ) -> FilterMap<Self, F, HKTRefMut<R>>Notable traits for FilterMap<I, F, NewItemType>impl<'next, I, NewItemType, F> LendingIteratorඞItem<'next, &'next FilterMap<I, F, NewItemType>> for FilterMap<I, F, NewItemType> where
    I: LendingIterator,
    NewItemType: HKT,
    for<'any> F: FnMut([&'any I; 0], Item<'any, I>) -> Option<Feed<'any, NewItemType>>, 
type T = Feed<'next, NewItemType>;

    where
        for<'any> F: FnMut([&'any Self; 0], Item<'any, Self>) -> Option<&'any mut R>,
        Self: Sized
, { ... } fn filter_map_into_iter<F, NonLendingItem>(
        self,
        f: F
    ) -> FilterMapIntoIter<Self, F>Notable traits for FilterMapIntoIter<I, F>impl<I, F, R> Iterator for FilterMapIntoIter<I, F> where
    I: LendingIterator,
    F: FnMut(Item<'_, I>) -> Option<R>, 
type Item = R;

    where
        F: FnMut(Item<'_, Self>) -> Option<NonLendingItem>,
        Self: Sized
, { ... } fn into_iter<Item>(self) -> IntoIter<Self>Notable traits for IntoIter<I>impl<Item, I: ?Sized + LendingIterator> Iterator for IntoIter<I> where
    for<'any> I: LendingIteratorඞItem<'any, T = Item>, 
type Item = Item;

    where
        Self: for<'any> LendingIteratorඞItem<'any, T = Item>,
        Self: Sized
, { ... } fn dyn_boxed<'usability>(
        self
    ) -> Box<dyn LendingIteratorDyn<Item = HKTItem<Self>> + 'usability>Notable traits for Box<I>impl<'next, I: ?Sized + LendingIterator> LendingIteratorඞItem<'next, &'next Box<I, Global>> for Box<I> type T = Item<'next, I>;
    where
        Self: 'usability,
        Self: Sized
, { ... } fn dyn_boxed_auto<BoxedDynLendingIterator, Item: HKT>(
        self
    ) -> BoxedDynLendingIterator
    where
        Self: Sized + DynCoerce<BoxedDynLendingIterator, Item>
, { ... }
}
Expand description

The meat of the crate. Trait similar to Iterator but for the return type of the fn next(&'_ mut self) method being allowed to depend on that '_.

Click to hide
  • That type is called the Item<'_> type, and is a generic_associated_type.

  • That difference is crucial both in terms of signature complexity (as this crate’s API ought to prove 😅) and borrowing semantics.

Mainly, when yielded, such Item<'_> is still &mut borrowing *self, so it won’t be possible to further advance the iterator (or anything else, for that matter), until the current item is no longer used.

That is: the Item<'_>s yielded by a LendingIterator cannot coëxist!

  • this will thus impose serious usability limitations on it (e.g, no .collect()ing whatsoever, since collecting items, by definition, expects them to coëxist (within the collection)).

    • For instance, there won’t be a for item in iter { sugar on these things, since that for sugar currently only blesses the stdlib Iterator trait.

      That being said, while let Some(item) = iter.next() { works just as well, to be honest.

  • but the dual / other side of that API restriction is that it is way simpler / less constraining, for implementors, to implement this trait.

    The canonical example illustrating this difference is windows_mut(), which is both an intuitive “iterator” we can think of, and yet something for which it is impossible to implement Iterator.

A Generic Associated Type

The core definition of this trait is thus:

  • #![feature(generic_associated_types)]
    
    trait LendingIterator {
        type Item<'next>
        where
            Self : 'next,
        ;
    
        fn next<'next> (
            self: &'next mut Self, // <- `Self : 'next` indeed!
        ) -> Option<Self::Item<'next>>
        ;
    }

As you can see, it involves that more complex type Item definition, which is called a generic associated type (GAT for short), and, it currently requires the nightly-only feature(generic_associated_types).

–Then how come this crate can work on stable?— you may ask.

The answer is that (lifetime)-GATs can actually be emulated in stable Rust through some extra slightly convoluted hoops.

That’s why this crate uses those techniques (and the crate featuring them, ::nougat), to achieve Stable Rust support:

  • #[::nougat::gat] // 👈 Add this and now It Just Works™ on stable.
    trait LendingIterator {
        type Item<'next>
        where
            Self : 'next,
        ;
    
        fn next<'next> (
            self: &'next mut Self,
        ) -> Option<Self::Item<'next>>
        ;
    }

It does come with a few caveats, though: the LendingIterator::Item item is no longer really nameable, at least not directly.

  • The current implementation of ::nougat uses a helper higher-order super-trait, called for<'any> LendingIteratorඞItem<'any>, which has, itself, a non-generic associated type, ::T. That way, LendingIteratorඞItem<'next>::T plays the role of LendingIterator::Item<'next>.

    BUT THIS MAY change within semver-compatible changes of nougat

    That’s why that path should never be used, directly, by downstream code.

    The only reason I am even talking about it and not having it #[doc(hidden)] is that exposing it makes understanding the signatures of the adapters multiple order of magnitude easier.

Hence the following “rules”:

  • Use Item<'_, I> instead of I::Item<'_>.

    • you could technically import the Gat! macro from the ::nougat crate, and then use Gat!(I::Item<'_>) (this is how this crate manages to define Item, for instance). But it seems less convenient than a type alias.

    • within a #[gat]-annotated trait or impl, most of the …::Item<'_> mentions will automagically be amended by the macro (which is why the previous snippet works, despite its usage of Self::Item<'next>).

  • If implementing the trait yourself, you need to apply #[gat] to the impl yourself.

  • If reëxporting the trait yourself, you need to also apply #[gat(Item)] to the use statement as well, so people can implement the trait through the new path.

  • LendingIterator is not really dyn-friendly (although IIUC, with feature(generic_associated_types) it wouldn’t have been either).

    But you can use dyn LendingIteratorDyn<Item = …> + … instead, which has been designed with dyn-friendlyness in mind 🙂.

Required Methods

Query the next() Item of this Self iterator.

LendingIterator counterpart of Iterator::next().

Provided Methods

LendingIterator counterpart of Iterator::map().

  • Turbofishing the NewItemType is mandatory, otherwise you’ll run into issues with non-higher-order closures.

    See the module-level documentation of crate::higher_kinded_types for more info.

    But the TL,DR is that you’d use it as:

    lending_iter.map::<HKT!(ReturnType<'_>), _>(

  • the second idiosyncracy is that, for technical reasons1 related to the maximally generic aspect of this API, the closure itself cannot just be a Self::Item<'_> -> Feed<'_, NewItemType> closure, and instead, requires that an extra [] dummy parameter be part of the signature:

    lending_iter.map::<HKT…, _>(|[], item| { … })
                                 👆

  1. In the case where Self::Item<'_> does not depend on '_, the return type then technically can’t depend on it either, so Rust complains about this (in a rather obtuse fashion). We solve this by requiring that extra [] parameter which acts as a convenient-to-write PhantomData which does depend on '_

Convenience method: same as .map(), but for hard-coding the HKT parameter to HKTRef<R> = HKT!(&R).

This alleviates the call-sites (no more turbofishing needed!) for such pervasive use cases 🙂

Convenience method: same as .map(), but for hard-coding the HKT parameter to HKTRefMut<R> = HKT!(&mut R).

This alleviates the call-sites (no more turbofishing needed!) for such pervasive use cases 🙂

Convenience shorthand for .map…(…).into_iter().

When the return type of the .map() closure is not lending / borrowing from *self, it becomes possible to call .into_iter() on it right away.

Moreover, it makes the [], closure arg hack no longer necessary.

This convenience function encompasses both things, thence returning an Iterator (not a LendingIterator!).

LendingIterator counterpart of Iterator::filter_map().

All the caveats and remarks of .map() apply, go check them up.

Convenience method: same as .filter_map(), but for hard-coding the HKT parameter to HKTRef<R> = HKT!(&R).

All the caveats and remarks of .map_to_ref() apply, go check them up.

Convenience method: same as .filter_map(), but for hard-coding the HKT parameter to HKTRefMut<R> = HKT!(&mut R).

All the caveats and remarks of .map_to_mut() apply, go check them up.

Convenience shorthand for .filter_map…(…).into_iter().

When the return type of the .filter_map() closure is not lending / borrowing from *self, it becomes possible to call .into_iter() on it right away.

Moreover, it makes the [], closure arg hack no longer necessary.

This convenience function encompasses both things, thence returning an Iterator (not a LendingIterator!).

Convert a Self : LendingIterator into an Iterator, provided Self::Item<'_> does not depend on '_.

Available on crate feature alloc only.

Converts this LendingIterator into a Box<dyn LendingIteratorDyn…>.

Note that the return dyn Trait will not be Send or implement any other auto-traits. For a more general albeit harder-on-type-inference alternative, see .dyn_boxed_auto().

Available on crate feature alloc only.

Converts this LendingIterator into a Box<dyn LendingIteratorDyn…>.

In order for it to work, the Item parameter has to be provided (probably funneled through a CanonicalHKT), as well as an explicit “landing type” (inference will probably fail to figure it out!).

That is, BoxedDynLendingIterator is expected to be of the form:

Box<dyn 'lt [+ Send] [+ Sync] + LendingIteratorDyn<Item = CanonicalHKT<…>>>

Implementations on Foreign Types

Implementors

dyn LendingIteratorDyn + … : LendingIterator

dyn LendingIteratorDyn + … : LendingIterator

dyn LendingIteratorDyn + … : LendingIterator

dyn LendingIteratorDyn + … : LendingIterator