pub fn polonius<'i, Input: ?Sized, OwnedOutput, BorrowingOutput>(
    input_borrow: &'i mut Input,
    branch: impl for<'any> FnOnce(&'any mut Input) -> PoloniusResult<BorrowingOutput::Of<'any>, OwnedOutput>
) -> PoloniusResult<BorrowingOutput::Of<'i>, OwnedOutput, &'i mut Input>
where BorrowingOutput: ForLt + ?Sized,
Expand description

The key stone of the API of this crate. See the top-level docs for more info.

Signature formatted for readability:

fn polonius<'i, Input : ?Sized, OwnedOutput, BorrowingOutput : ?Sized> (
    input_borrow: &'i mut Input,
    branch:
        impl for<'any>
            FnOnce(&'any mut Input)
              -> PoloniusResult<
                    BorrowingOutput::Of<'any>,
                    OwnedOutput, // -----------+
                >                           // |
    ,                                       // | `polonius()`
) -> PoloniusResult<                        // | magic
        BorrowingOutput::Of<'i>,            // | adds "back"
        OwnedOutput, &'i mut Input, // <-------+ the `input_borrow`
    >
where
    BorrowingOutput : ForLt,

Turbofishing a ForLt!() parameter.

As described in the top-level docs, the key aspect that allows this function to be both sound, and generic, is that it involves a for<'any>-quantified lifetime in its branching closure, and a lifetime-generic generic type parameter.

There was no stutter: this is indeed a generic generic type parameter: the API is said to be “higher-kinded”, related to HKTs (higher-kinded types).

Hence the BorrowingOutput : ForLt (lifetime-generic) generic type parameter.

Such “For types” involved in these HKT APIs, however, cannot be elided, since they do not play well with type inference.

This means that turbofishing this third type parameter is:

  • mandatory;
  • to be done using the ForLt! macro.
polonius::<_, _, ForLt!(…)>(…)

If this sounds too complex or abstract, know that there also are:

Easier APIs for the most pervasive use cases

These are provided as the macros that accompany this crate: