Macro polonius_the_crab::polonius
source · [−]macro_rules! polonius {
(
$(
<
$( $(
$lt:lifetime
),+ $(,)? )?
$( $(
$T:ident $(:
$( $super:lifetime + )?
$( ?$Sized:ident )?
$( + )?
$( $Bound:path )?
)?
),+ $(,)? )?
>
)?
|$var:ident| -> $Ret:ty $body:block
) => { ... };
}
Expand description
Convenient entry-point to this crate’s logic.
Usage
use ::polonius_the_crab::prelude::*;
let mut a_mut_binding: &mut _ = // …
// the lifetime placeholder has to be
// named `'polonius` !!
// vvvvvvvvv
let x = polonius!(|a_mut_binding| -> SomeRetType<'polonius> {
let some_dependent_type = stuff(a_mut_binding);
if some_cond() {
polonius_return!(some_dependent_type);
}
if some_other_cond() {
polonius_break!(42);
unreachable!();
}
42
});
assert_eq!(x, 42);
stuff(a_mut_binding) // macro gave it back
// …
Generic parameters
Sometimes, the return value of that polonius!
closure may need to refer to
generic parameters. When that’s the case, you’ll need to tell the macro
about those, using <generics…>
syntax before the |…| ->
part of the
macro input:
use ::polonius_the_crab::prelude::*;
fn get_or_insert<'map, 'v, K, V : ?Sized> (
mut map: &'map mut ::std::collections::HashMap<K, &'v V>,
key: &'_ K,
fallback_value: &'v V,
) -> &'map &'v V
where
K : ::core::hash::Hash + Eq + Clone,
V : ::core::fmt::Debug,
{
// No need to provide `K`, since not part of the return type;
// nor to provide the bounds for `V`, except for:
// - nested borrows (if ever),
// - `?Sized` (every now and then)
// - or to be able to name a bound-provided associated type (super rare!)
polonius!(<'v, V : 'v + ?Sized> |map| -> &'polonius &'v V {
if let Some(v) = map.get(key) {
dbg!(v); // Even though `Debug` is not provided to the signature, it is available to the body.
polonius_return!(v);
}
});
map.insert(key.clone(), fallback_value);
&map[key]
}