lending_iterator/lending_iterator/
_mod.rs

1//! Trait and helper adapter definitions.
2
3use {
4    ::core::{
5        marker::PhantomData,
6        ops::Not,
7    },
8    ::never_say_never::{
9        Never as ǃ,
10    },
11    ::nougat::{
12        *,
13    },
14    crate::{
15        higher_kinded_types::{*, Apply as A, HKTItem},
16    },
17    self::{
18        adapters::*,
19    }
20};
21
22pub use self::{
23    r#dyn::LendingIteratorDyn,
24};
25
26#[path = "adapters/_mod.rs"]
27pub
28mod adapters;
29
30/// Functions, extension traits and types allowing direct construction of
31/// [`LendingIterator`]s (no need for custom types or implementations!).
32#[path = "constructors/_mod.rs"]
33pub
34mod constructors;
35
36use r#dyn::*;
37#[path = "dyn/_mod.rs"]
38pub(in crate)
39mod r#dyn;
40
41mod impls;
42
43macro_rules! with_cfg_better_docs {( $($rules:tt)* ) => (
44    macro_rules! __emit__ { $($rules)* }
45
46    #[cfg(feature = "better-docs")]
47    __emit__! {
48        true
49    }
50
51    #[cfg(not(feature = "better-docs"))]
52    __emit__! {
53        false
54    }
55)}
56with_cfg_better_docs! {(
57    $(true $($if_better_docs:tt)?)?
58    $(false $($if_not_better_docs:tt)?)?
59) => (
60
61
62$($($if_better_docs)?
63    /// ⚠️ **NEVER NAME THIS TRAIT DIRECTLY** ⚠️
64    /// Implementation detail of `#[gat] trait LendingIterator`.
65    ///
66    ///   - ⚠️ **The exact name of this trait may change within semver-compatible
67    ///     releases** ⚠️
68    ///
69    /// The only reason this trait is even exposed to begin with is because of
70    /// the `notable_trait` feature greatly improving the readability of
71    /// [`LendingIterator`]'s adapters.
72    #[doc(notable_trait)]
73    pub trait LendingIteratorඞItem<'next, Bounds = &'next Self> {
74        /// The "output" of this whole hand-rolled GAT:
75        /// think of `LendingIteratorඞItem<'lt>::T` as of `LendingIterator::Item<'lt>`.
76        ///
77        /// ⚠️ **NEVER NAME THIS TRAIT OR ASSOC TYPE DIRECTLY** ⚠️ yadda yadda.
78        type T;
79    }
80)?
81
82#[allow(type_alias_bounds)]
83/// `generic_associated_types`-agnostic shorthand for
84/// <code>\<I as [LendingIterator]\>::Item\<\'lt\></code>
85pub
86type Item<'lt, I : LendingIterator> =
87    Gat!(<I as LendingIterator>::Item<'lt>)
88;
89
90/// The meat of the crate. Trait similar to [`Iterator`] but **for the return
91/// type of the `fn next(&'_ mut self)` method being allowed to depend on that
92/// `'_`**.
93///
94/// <details open class="custom"><summary><span class="summary-box"><span>Click to hide</span></span></summary>
95///
96///   - That type is called the `Item<'_>` type, and is a
97///     [`generic_associated_type`](#a-generic-associated-type).
98///
99///   - That difference is crucial both in terms of signature complexity
100///     (as this crate's API ought to prove 😅) and borrowing semantics.
101///
102/// Mainly, when yielded, such `Item<'_>` is still `&mut` borrowing `*self`, so
103/// **it won't be possible to further advance the iterator** (or anything else,
104/// for that matter), **until the current item is no longer used.**
105///
106/// That is: **the `Item<'_>`s yielded by a [`LendingIterator`] cannot
107/// coëxist!**
108///
109///   - this will thus impose serious usability limitations on it (_e.g_, no
110///     `.collect()`ing whatsoever, since collecting items, by definition,
111///     expects them to coëxist (within the collection)).
112///
113///       - For instance, there won't be a `for item in iter {` sugar on these
114///         things, since that `for` sugar currently only blesses the stdlib
115///         [`Iterator`] trait.
116///
117///         That being said, `while let Some(item) = iter.next() {` works just
118///         as well, to be honest.
119///
120///   - but the dual / other side of that API restriction is that it is way
121///     simpler / less constraining, _for implementors_, to implement this
122///     trait.
123///
124///     The canonical example illustrating this difference is [`windows_mut()`][
125///     constructors::windows_mut()], which is both an intuitive "iterator" we
126///     can think of, and yet something for which it is _impossible_ to
127///     implement [`Iterator`].
128///
129/// ## A Generic Associated Type
130///
131/// The core definition of this trait is thus:
132///
133/**  - ```rust ,ignore
134    #![feature(generic_associated_types)]
135
136    trait LendingIterator {
137        type Item<'next>
138        where
139            Self : 'next,
140        ;
141
142        fn next<'next> (
143            self: &'next mut Self, // <- `Self : 'next` indeed!
144        ) -> Option<Self::Item<'next>>
145        ;
146    }
147    ``` */
148///
149/// As you can see, it involves that more complex `type Item` definition, which
150/// is called a _generic associated type_ (GAT for short), and, it _currently_
151/// requires the `nightly`-only `feature(generic_associated_types)`.
152///
153/// –Then how come this crate can work on stable?— you may ask.
154///
155/// The answer is that [(lifetime)-GATs can actually be emulated in stable Rust
156/// through some extra slightly convoluted hoops][`::nougat`].
157///
158/// [`::nougat`]: https://docs.rs/nougat
159///
160/// That's why this crate uses those techniques (and the crate featuring them,
161/// [`::nougat`]), to achieve Stable Rust support:
162///
163/**  - ```rust
164    #[::nougat::gat] // 👈 Add this and now It Just Works™ on stable.
165    trait LendingIterator {
166        type Item<'next>
167        where
168            Self : 'next,
169        ;
170
171        fn next<'next> (
172            self: &'next mut Self,
173        ) -> Option<Self::Item<'next>>
174        ;
175    }
176    ``` */
177///
178/// It does come with a few caveats, though: **the `LendingIterator::Item` item
179/// is no longer really nameable**, at least not _directly_.
180///
181///   - The current implementation of [`::nougat`] uses a helper _higher-order_
182///     super-trait, called
183///     <code>for\<\'any\> [LendingIteratorඞItem]\<\'any\></code>, which has,
184///     itself, a non-generic associated type, `::T`. That way,
185///     `LendingIteratorඞItem<'next>::T` plays the role of
186///     `LendingIterator::Item<'next>`.
187///
188///     **BUT THIS MAY change within semver-compatible changes of `nougat`**
189///
190///     That's why that path should never be used, directly, by downstream code.
191///
192///     The only reason I am even talking about it and not having it
193///     `#[doc(hidden)]` is that exposing it makes understanding the signatures
194///     of the adapters multiple order of magnitude easier.
195///
196/// Hence the following "rules":
197///
198///   - Use <code>[Item]\<\'_, I\></code> instead of `I::Item<'_>`.
199///
200///       - you could technically import the `Gat!` macro from the `::nougat`
201///         crate, and then use `Gat!(I::Item<'_>)` (this is how this crate
202///         manages to define [`Item`], for instance). But it seems less
203///         convenient than a type alias.
204///
205///       - within a `#[gat]`-annotated `trait` or `impl`, most of the
206///         `…::Item<'_>` mentions will automagically be amended by the macro
207///         (which is why the previous snippet works, despite its usage
208///         of `Self::Item<'next>`).
209///
210///   - If implementing the trait yourself, you need to apply
211///     <code>[#\[gat\]][crate::gat]</code> to the `impl` yourself.
212///
213///   - If reëxporting the trait yourself, you need to also apply
214///     <code>[#\[gat(Item)\]][crate::gat]</code> to the `use` statement as
215///     well, so people can implement the trait through the new path.
216///
217///  - [`LendingIterator`] is not really `dyn`-friendly (although IIUC, with
218///     `feature(generic_associated_types)` it wouldn't have been either).
219///
220///     But you can use <code>dyn [LendingIteratorDyn]\<Item = …\> + …</code>
221///     instead, which has been designed with `dyn`-friendlyness in mind 🙂.
222///
223/// </details>
224$($($if_not_better_docs)?
225    #[gat]
226)?
227pub
228trait LendingIterator
229where
230    $($($if_better_docs)?
231        Self : for<'next> LendingIteratorඞItem<'next>,
232    )?
233{
234    $($($if_not_better_docs)?
235        type Item<'next>
236        where
237            Self : 'next,
238        ;
239    )?
240
241    /// Query the `next()` `Item` of this `Self` iterator.
242    ///
243    /// [`LendingIterator`] counterpart of [`Iterator::next()`].
244    fn next (
245        self: &'_ mut Self,
246    ) -> Option<Item<'_, Self>>
247    ;
248
249    /// [`LendingIterator`] counterpart of [`Iterator::filter()`].
250    fn filter<F> (
251        self: Self,
252        should_yield: F,
253    ) -> Filter<Self, F>
254    where
255        Self : Sized,
256        F : FnMut(&'_ Item<'_, Self>) -> bool,
257    {
258        Filter { iter: self, should_yield }
259    }
260
261    /// [`LendingIterator`] counterpart of [`Iterator::for_each()`].
262    fn for_each<> (
263        self: Self,
264        mut f: impl FnMut(Item<'_, Self>),
265    )
266    where
267        Self : Sized,
268    {
269        self.fold((), |(), item| f(item))
270    }
271
272    /// [`LendingIterator`] counterpart of [`Iterator::fold()`].
273    fn fold<Acc> (
274        mut self: Self,
275        acc: Acc,
276        mut f: impl FnMut(Acc, Item<'_, Self>) -> Acc,
277    ) -> Acc
278    where
279        Self : Sized,
280    {
281        self.try_fold(acc, |acc, item| Ok(f(acc, item)))
282            .unwrap_or_else(|unreachable: ǃ| unreachable)
283    }
284
285    /// [`LendingIterator`] counterpart of [`Iterator::try_for_each()`].
286    fn try_for_each<Err> (
287        self: &'_ mut Self,
288        mut f: impl FnMut(Item<'_, Self>) -> Result<(), Err>,
289    ) -> Result<(), Err>
290    {
291        self.try_fold((), |(), item| f(item))
292    }
293
294    /// [`LendingIterator`] counterpart of [`Iterator::try_fold()`].
295    fn try_fold<Acc, Err> (
296        self: &'_ mut Self,
297        mut acc: Acc,
298        mut f: impl FnMut(Acc, Item<'_, Self>) -> Result<Acc, Err>,
299    ) -> Result<Acc, Err>
300    {
301        while let Some(item) = self.next() {
302            acc = f(acc, item)?;
303        }
304        Ok(acc)
305    }
306
307    /// [`LendingIterator`] counterpart of [`Iterator::all()`].
308    fn all<> (
309        self: &'_ mut Self,
310        mut predicate: impl FnMut(Item<'_, Self>) -> bool,
311    ) -> bool
312    where
313        Self : Sized,
314    {
315        self.try_for_each(
316                move |item| if predicate(item) {
317                    Ok(())
318                } else {
319                    Err(())
320                },
321            )
322            .is_ok()
323    }
324
325    /// [`LendingIterator`] counterpart of [`Iterator::any()`].
326    fn any<> (
327        self: &'_ mut Self,
328        mut predicate: impl FnMut(Item<'_, Self>) -> bool,
329    ) -> bool
330    where
331        Self : Sized,
332    {
333        self.all(move |item| predicate(item).not())
334            .not()
335    }
336
337    /// [`LendingIterator`] counterpart of [`Iterator::by_ref()`].
338    fn by_ref<> (self: &'_ mut Self)
339      -> &'_ mut Self
340    where
341        Self : Sized,
342    {
343        self
344    }
345
346    /// [`LendingIterator`] counterpart of [`Iterator::count()`].
347    fn count<> (self: Self)
348      -> usize
349    where
350        Self : Sized,
351    {
352        self.fold(0_usize, |acc, _| acc + 1)
353    }
354
355    /// [`LendingIterator`] counterpart of [`Iterator::find()`].
356    fn find<'find> (
357        self: &'find mut Self,
358        mut predicate: impl 'find + FnMut(&Item<'_, Self>) -> bool,
359    ) -> Option<Item<'find, Self>>
360    where
361        Self : Sized,
362    {
363        use ::polonius_the_crab::prelude::*;
364        let mut this = self;
365        polonius_loop!(|this| -> Option<Item<'polonius, Self>> {
366            let ret = this.next();
367            if matches!(ret, Some(ref it) if predicate(it).not()) {
368                polonius_continue!();
369            }
370            polonius_return!(ret);
371        })
372    }
373
374    /// [`LendingIterator`] counterpart of [`Iterator::fuse()`].
375    fn fuse (self: Self)
376      -> Fuse<Self>
377    where
378        Self : Sized,
379    {
380        Fuse(Some(self))
381    }
382
383    /// [`LendingIterator`] counterpart of [`Iterator::nth()`].
384    fn nth (
385        self: &'_ mut Self,
386        n: usize,
387    ) -> Option<Item<'_, Self>>
388    {
389        if let Some(n_minus_one) = n.checked_sub(1) {
390            self.skip(n_minus_one);
391        }
392        self.next()
393    }
394
395    /// [`LendingIterator`] counterpart of [`Iterator::position()`].
396    fn position<F> (
397        self: &'_ mut Self,
398        mut predicate: impl FnMut(Item<'_, Self>) -> bool,
399    ) -> Option<usize>
400    where
401        Self : Sized,
402    {
403        match
404            self.try_fold(0, |i, item| if predicate(item) {
405                Err(i)
406            } else {
407                Ok(i + 1)
408            })
409        {
410            | Err(position) => Some(position),
411            | Ok(_) => None,
412        }
413    }
414
415    /// [`LendingIterator`] counterpart of [`Iterator::skip()`].
416    fn skip (
417        self: Self,
418        count: usize,
419    ) -> Skip<Self>
420    where
421        Self : Sized,
422    {
423        Skip {
424            iter: self,
425            to_skip: count.try_into().ok(),
426        }
427    }
428
429    /// [`LendingIterator`] counterpart of [`Iterator::skip_while()`].
430    #[cfg(TODO)]
431    fn skip_while<F> (
432        self: Self,
433        predicate: F,
434    ) -> SkipWhile<Self, F>
435    where
436        F : FnMut(Item<'_, Self>) -> bool,
437        Self : Sized,
438    {
439        SkipWhile { iter: self, predicate }
440    }
441
442    /// [`LendingIterator`] counterpart of [`Iterator::take()`].
443    fn take (
444        self: Self,
445        count: usize,
446    ) -> Take<Self>
447    where
448        Self : Sized,
449    {
450        Take {
451            iter: self,
452            remaining: count,
453        }
454    }
455
456    /// [`LendingIterator`] counterpart of [`Iterator::take_while()`].
457    #[cfg(TODO)]
458    fn take_while<F> (
459        self: Self,
460        f: F,
461    ) -> TakeWhile<Self, F>
462    where
463        F : FnMut(&Self::Item) -> bool,
464        Self : Sized,
465    {
466        TakeWhile(self)
467    }
468
469    /// [`LendingIterator`] counterpart of [`Iterator::map()`].
470    ///
471    ///   - **Turbofishing the `NewItemType` is mandatory**, otherwise you'll
472    ///     run into issues with non-higher-order closures.
473    ///
474    ///     See the module-level documentation of [`crate::higher_kinded_types`]
475    ///     for more info.
476    ///
477    ///     But the TL,DR is that you'd use it as:
478    ///
479    ///     <code>lending_iter.map::\<[HKT!]\(ReturnType\<\'_\>\), _>\(</code>
480    ///
481    ///   - the second idiosyncracy is that, for technical reasons[^1] related
482    ///     to the maximally generic aspect of this API, the closure itself
483    ///     cannot just be a `Self::Item<'_> -> Feed<'_, NewItemType>` closure,
484    ///     and instead, requires that an extra `[]` dummy parameter be part
485    ///     of the signature:
486    ///
487    ///     ```rust
488    ///     # #[cfg(any)] macro_rules! ignore { /*
489    ///     lending_iter.map::<HKT…, _>(|[], item| { … })
490    ///                                  👆
491    ///     # */ }
492    ///     ```
493    ///
494    /// [^1]: In the case where `Self::Item<'_>` does _not_ depend on `'_`, the
495    /// return type then technically can't depend on it either, so Rust
496    /// complains about this (in a rather obtuse fashion). We solve this by
497    /// requiring that extra `[]` parameter which acts as a convenient-to-write
498    /// `PhantomData` which does depend on `'_`.
499    fn map<NewItemType : HKT, F> (
500        self: Self,
501        f: F,
502    ) -> Map<Self, F, NewItemType>
503    where
504        for<'next>
505            F : FnMut(
506                [&'next Self; 0],
507                Item<'next, Self>,
508            ) -> A!(NewItemType<'next>)
509        ,
510        Self : Sized,
511    {
512        Map { iter: self, map: f, _phantom_ty: <_>::default() }
513    }
514
515    pervasive_hkt_choices! {
516        (map, Map)(
517            /// Convenience method: same as [`.map()`][Self::map()], but for
518            /// hard-coding the `HKT` parameter to
519            /// <code>[HKTRef]\<R\> = [HKT!]\(\&R\)</code>.
520            ///
521            /// This alleviates the call-sites (no more turbofishing needed!)
522            /// for such pervasive use cases 🙂
523            map_to_ref: [R : ?Sized], HKTRef<R>, -> &'any R,
524            /// Convenience method: same as [`.map()`][Self::map()], but for
525            /// hard-coding the `HKT` parameter to
526            /// <code>[HKTRefMut]\<R\> = [HKT!]\(\&mut R\)</code>.
527            ///
528            /// This alleviates the call-sites (no more turbofishing needed!)
529            /// for such pervasive use cases 🙂
530            map_to_mut: [R : ?Sized], HKTRefMut<R>, -> &'any mut R,
531        ),
532    }
533
534    /// Convenience shorthand for
535    /// <code>[.map…\(…\)][Self::map()][.into_iter()][Self::into_iter()]</code>.
536    ///
537    /// When the return type of the `.map()` closure is not lending
538    /// / borrowing from `*self`, it becomes possible to call
539    /// [.into_iter()][Self::into_iter()] on it right away.
540    ///
541    /// Moreover, it makes the `[], ` closure arg hack no longer necessary.
542    ///
543    /// This convenience function encompasses both things, thence returning
544    /// an [`Iterator`] (not a [`LendingIterator`]!).
545    fn map_into_iter<F, NonLendingItem> (
546        self: Self,
547        f: F,
548    ) -> MapIntoIter<Self, F>
549    where
550        F : FnMut(Item<'_, Self>) -> NonLendingItem,
551        Self : Sized,
552    {
553        MapIntoIter(self, f)
554    }
555
556    /// [`LendingIterator`] counterpart of [`Iterator::filter_map()`].
557    ///
558    /// All the caveats and remarks of [`.map()`][Self::map()] apply, go check
559    /// them up.
560    fn filter_map<NewItemType : HKT, F> (
561        self: Self,
562        f: F,
563    ) -> FilterMap<Self, F, NewItemType>
564    where
565        for<'next>
566            F : FnMut(
567                [&'next Self; 0],
568                Item<'next, Self>,
569            ) -> Option<A!(NewItemType<'next>)>
570        ,
571        Self : Sized,
572    {
573        FilterMap { iter: self, map: f, _phantom_ty: <_>::default() }
574    }
575
576    pervasive_hkt_choices! {
577        (filter_map, FilterMap)(
578            /// Convenience method: same as
579            /// [`.filter_map()`][Self::filter_map()], but for hard-coding the
580            /// `HKT` parameter to <code>[HKTRef]\<R\> = [HKT!]\(\&R\)</code>.
581            ///
582            /// All the caveats and remarks of
583            /// [`.map_to_ref()`][Self::map_to_ref()] apply, go check them up.
584            filter_map_to_ref: [R : ?Sized], HKTRef<R>, -> Option<&'any R>,
585
586            /// Convenience method: same as
587            /// [`.filter_map()`][Self::filter_map()], but for hard-coding the
588            /// `HKT` parameter to <code>[HKTRefMut]\<R\> = [HKT!]\(\&mut R\)</code>.
589            ///
590            /// All the caveats and remarks of
591            /// [`.map_to_mut()`][Self::map_to_mut()] apply, go check them up.
592            filter_map_to_mut: [R : ?Sized], HKTRefMut<R>, -> Option<&'any mut R>,
593        ),
594    }
595
596    /// Convenience shorthand for
597    /// <code>[.filter_map…\(…\)][Self::filter_map()][.into_iter()][Self::into_iter()]</code>.
598    ///
599    /// When the return type of the `.filter_map()` closure is not lending
600    /// / borrowing from `*self`, it becomes possible to call
601    /// [.into_iter()][Self::into_iter()] on it right away.
602    ///
603    /// Moreover, it makes the `[], ` closure arg hack no longer necessary.
604    ///
605    /// This convenience function encompasses both things, thence returning
606    /// an [`Iterator`] (not a [`LendingIterator`]!).
607    fn filter_map_into_iter<F, NonLendingItem> (
608        self: Self,
609        f: F,
610    ) -> FilterMapIntoIter<Self, F>
611    where
612        F : FnMut(Item<'_, Self>) -> Option<NonLendingItem>,
613        Self : Sized,
614    {
615        FilterMapIntoIter(self, f)
616    }
617
618    /// Convert a <code>Self : [LendingIterator]</code> into an [`Iterator`],
619    /// **provided `Self::Item<'_>` does not depend on `'_`**.
620    fn into_iter<Item> (
621        self: Self,
622    ) -> IntoIter<Self>
623    where
624        Self : for<'any> LendingIteratorඞItem<'any, T = Item>,
625        Self : Sized,
626    {
627        IntoIter(self)
628    }
629
630    /// Converts this [`LendingIterator`] into a
631    /// <code>[Box][::alloc::boxed::Box]\<dyn [LendingIteratorDyn]…\></code>.
632    ///
633    /// Note that the return `dyn Trait` will not be `Send` or implement any
634    /// other auto-traits. For a more general albeit harder-on-type-inference
635    /// alternative, see [`.dyn_boxed_auto()`][Self::dyn_boxed_auto()].
636    #[apply(cfg_alloc)]
637    fn dyn_boxed<'usability> (
638        self: Self
639    ) -> ::alloc::boxed::Box<dyn
640            'usability + LendingIteratorDyn<Item = HKTItem<Self>>
641        >
642    where
643        Self : 'usability,
644        Self : Sized,
645    {
646        ::alloc::boxed::Box::new(self)
647    }
648
649    /// Converts this [`LendingIterator`] into a
650    /// <code>[Box][::alloc::boxed::Box]\<dyn [LendingIteratorDyn]…\></code>.
651    ///
652    /// In order for it to work, the `Item` parameter has to be provided
653    /// (probably funneled through a [`CanonicalHKT`]), as well as an explicit
654    /// "landing type" (inference will probably fail to figure it out!).
655    ///
656    /// That is, `BoxedDynLendingIterator` is expected to be of the form:
657    ///
658    /// <code>[Box]\<dyn \'lt \[+ Send\] \[+ Sync\] + [LendingIteratorDyn]\<Item = [CanonicalHKT]\<…\>\>\></code>
659    ///
660    /// [Box]: ::alloc::boxed::Box
661    /// [CanonicalHKT]: crate::prelude::CanonicalHKT
662    #[apply(cfg_alloc)]
663    fn dyn_boxed_auto<BoxedDynLendingIterator, Item : HKT> (self: Self)
664      -> BoxedDynLendingIterator
665    where
666        Self : Sized + DynCoerce<BoxedDynLendingIterator, Item>,
667    {
668        Self::coerce(self)
669    }
670}
671)}
672
673macro_rules! pervasive_hkt_choices {(
674    ($map:ident, $Map:ident)(
675        $(
676            $(#[$attr:meta])*
677            $fname:ident: [$($R:tt)*], $HKT:ty, -> $Ret:ty,
678        )*
679    ) $(,)?
680) => (
681    $(
682        $(#[$attr])*
683        fn $fname<$($R)*, F> (
684            self: Self,
685            f: F,
686        ) -> $Map<Self, F, $HKT>
687        where
688            for<'any>
689                F : FnMut([&'any Self; 0], Item<'any, Self>) -> $Ret
690            ,
691            Self : Sized,
692        {
693            self.$map::<$HKT, F>(f)
694        }
695    )*
696)} use pervasive_hkt_choices;
697
698#[cfg(test)]
699mod tests;