polonius_the_crab/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#![doc = include_str!("../README.md")]
#![no_std]
#![cfg_attr(feature = "polonius",
    forbid(unsafe_code),
)]
#![allow(uncommon_codepoints)]

/// ACT I SCENE I. Elsinore. A platform before the castle.
pub
mod prelude {
    pub use crate::{
        exit_polonius,
        polonius,
        polonius_break,
        polonius_break_dependent,
        polonius_continue,
        polonius_loop,
        polonius_return,
        polonius_try,
    };
}

#[doc(no_inline)]
pub use ::higher_kinded_types::ForLt;

pub use macros::ඞ;
mod macros;

mod r#try;

/// The key stone of the API of this crate.
/// See the [top-level docs][crate] for more info.
///
/// Signature formatted for readability:
/**
```rust
# const _IGNORED: &str = stringify! {
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][crate], 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][PoloniusResult] 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][hkts]).
///
/// Hence the <code>BorrowingOutput : [ForLt]</code> (lifetime-generic) generic
/// type parameter.
///
/// [ForLt]: trait@ForLt
///
/// 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.
///
/// ```rust
/// # /*
/// polonius::<_, _, ForLt!(…)>(…)
/// # */
/// ```
///
/// [hkts]: https://docs.rs/higher-kinded-types
///
/// 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:
///
///   - [`polonius!`] for most cases;
///
///   - [`polonius_loop!`] as extra sugar for a specific shape of
///     `loop { polonius!(…) }`
///
///       - ⚠️ [not every `loop { polonius!(…); … }` case can be translated][l]
///         to a `polonius_loop!`. When in doubt, fall back to a lower-level
///         [`polonius!`] invocation, or even to a manual [`polonius()`] call.
///
/// [l]: https://github.com/danielhenrymantilla/polonius-the-crab.rs/issues/11
pub
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,
                >
    ,
) -> PoloniusResult<
        BorrowingOutput::Of<'i>,
        OwnedOutput, &'i mut Input,
    >
where
    BorrowingOutput : ForLt,
{
    #[cfg(feature = "polonius")]
    let tentative_borrow = &mut *input_borrow;
    #[cfg(not(feature = "polonius"))]
    let tentative_borrow = unsafe {
        // SAFETY:
        // > Though this be `unsafe`, there is soundness in 't.
        //
        // More seriously, read the docs, I've detailed the reasoning there
        // in great length. And/or check the `tests/soundness.rs` test,
        // which `cargo check`s this very snippet without this `unsafe`.
        &mut *(input_borrow as *mut _)
    };
    let owned_value = match branch(tentative_borrow) {
        | PoloniusResult::Borrowing(dependent) => {
            return PoloniusResult::Borrowing(dependent);
        },
        | PoloniusResult::Owned { value, .. } => value,
    }; // <- `drop(PoloniusResult::Owned { .. })`.
       // See https://github.com/rust-lang/rust/issues/126520 for more info.
    PoloniusResult::Owned {
        value: owned_value,
        input_borrow,
    }
}

/// Placeholder type to be used when _constructing_ a
/// [`PoloniusResult::Owned`].
///
/// [`PoloniusResult::Owned`]: type@PoloniusResult::Owned
///
/// Since there is no access to the original `input_borrow` yet (due to the
/// very polonius limitation that makes this crate necessary), this
/// [`Placeholder`] is used in its stead.
///
/// ```rust, no_run
/// use ::polonius_the_crab::*;
///
/// type StringRef = ForLt!(&str);
///
/// let map: &mut ::std::collections::HashMap<i32, String> = // ...
/// # None.unwrap();
///
/// # use drop as stuff;
/// #
/// match polonius::<_, _, StringRef>(map, |map| match map.get(&22) {
///     | Some(ret) => PoloniusResult::Borrowing(ret),
///     | None => PoloniusResult::Owned {
///         value: 42,
///         input_borrow: /* WHAT TO PUT HERE?? */ Placeholder, // 👈👈
///     },
/// }) {
///     // `polonius` magic
///     | PoloniusResult::Borrowing(dependent_entry) => {
///         // ...
///         stuff(dependent_entry);
///     },
///     | PoloniusResult::Owned {
///         value,
///         input_borrow: map, // we got our `map` borrow back! 🙌
///     } => {
///         assert_eq!(value, 42);
///         stuff(map);
///     },
/// }
/// ```
///
/// Note that despite intellectually interesting w.r.t properly understanding
/// the API, providing that `input_borrow: Placeholder` does not provide any
/// valuable information to the call, and is thus rather noisy.
///
/// Hence the [`PoloniusResult::Owned()`] constructor shorthand,
/// so as to be able to write:
///
/// ```rust
/// # const _IGNORED: &str = stringify! {
/// PoloniusResult::Owned(42)
/// // is just a shorthand for:
/// PoloniusResult::Owned {
///     value: 42,
///     input_borrow: /* WHAT TO PUT HERE?? */ Placeholder, // 👈👈
/// }
/// # };
/// ```
pub
struct Placeholder;

/// Output type of both the [`polonius()`] function and the closure it takes.
///
/// It represents the conceptual code-flow / branch disjunction between:
///
///   - having some _dependent_ type still [`Borrowing`][Self::Borrowing] from
///     the `input_borrow` _given_/forfeited to [`polonius()`];
///
///   - or having no such type, _i.e._, having only "[`Owned`][type@Self::Owned]"
///     (as far as the `input_borrow` is concerned) output.
///
///       - [`polonius()`] magic makes it so, in this branch/case, its
///         `.input_borrow` shall be populated for the caller to get back access
///         to it.
pub
enum PoloniusResult<BorrowingOutput, OwnedOutput, InputBorrow = Placeholder> {
    /// Variant to return in the "happy" case where our tentative (re)borrow
    /// actually yielded some dependent / still-`Borrowing` type which we wish
    /// to keep hold of, _e.g._, [to `return` it from the
    /// function][`polonius_return!`].
    Borrowing(BorrowingOutput),

    /// Variant to return in the branches where we are done with any dependent
    /// value, and we would like to instead get our `input_borrow` back.
    Owned {
        /// The inner `value` of the [`Self::Owned(value)`][Self::Owned()] case.
        value: OwnedOutput,

        /// When constructing this variant, inside [`polonius()`]' closure,
        /// a [`Placeholder`] is to be put in its stead, to let [`polonius()`]
        /// replace it with its `input_borrow`.
        input_borrow: InputBorrow,
    },
}

impl<BorrowingOutput, OwnedOutput> PoloniusResult<BorrowingOutput, OwnedOutput> {
    /// Tuple-variant-looking sugar to _construct_
    /// the <code>[Self::Owned]</code> variant.
    ///
    /// It's just convenience sugar for
    /// <code>[Self::Owned] { value, input_borrow: [Placeholder] }</code>.
    ///
    /// ```rust
    /// # const _IGNORED: &str = stringify! {
    /// PoloniusResult::Owned(42)
    /// // is the same as:
    /// PoloniusResult::Owned {
    ///     value: 42,
    ///     input_borrow: Placeholder,
    /// }
    /// # };
    /// ```
    ///
    /// See [`Placeholder`] for more info.
    ///
    /// [Self::Owned]: type@Self::Owned
    #[allow(nonstandard_style)]
    pub
    const
    fn Owned(value: OwnedOutput)
      -> Self
    {
        Self::Owned {
            value: value,
            input_borrow: Placeholder,
        }
    }
}

#[cfg_attr(feature = "ui-tests",
    cfg_attr(all(), doc = include_str!("compile_fail_tests.md")),
)]
mod _compile_fail_tests {}