Macro polonius_the_crab::polonius_loop
source · [−]macro_rules! polonius_loop {
(
| $var:ident $(,)? | -> $Ret:ty
$body:block
$(,)?
) => { ... };
}
Expand description
Convenience support for the loop { … polonius!(…) }
pattern.
Example
#![forbid(unsafe_code)]
use {
::polonius_the_crab::{
prelude::*,
},
::std::{
collections::HashMap,
},
};
enum Value {
Alive(i32),
Daed,
}
/// Notice how this example, *despite its usage of the fancy `.entry()` API
/// of `HashMap`s*, still needs `polonius_the_crab` to express this logic!
fn get_first_alive_from_base_or_insert (
mut map: &'_ mut HashMap<usize, Value>,
base: usize,
default_value: i32,
) -> &'_ i32
{
let mut idx = base;
// (loop {
polonius_loop!(|map| -> &'polonius i32 {
use ::std::collections::hash_map::*;
// return(
polonius_return!(
match map.entry(idx) {
| Entry::Occupied(entry) => match entry.into_mut() {
// Found a value!
| &mut Value::Alive(ref val) => val,
// "tombstone", keep searching
| &mut Value::Daed => {
idx += 1;
// continue;
polonius_continue!();
},
},
| Entry::Vacant(slot) => match slot.insert(Value::Alive(default_value)) {
| &mut Value::Alive(ref val) => val,
| &mut Value::Daed => unreachable!(),
},
}
);
})
}
Error message without polonius
error[E0499]: cannot borrow `*map` as mutable more than once at a time
--> src/lib.rs:222:18
|
22 | mut map: &'_ mut HashMap<usize, Value>,
| - let's call the lifetime of this reference `'1`
...
33 | match map.entry(idx) {
| ^^^ `*map` was mutably borrowed here in the previous iteration of the loop
...
45 | | &mut Value::Alive(ref val) => val,
| --- returning this value requires that `*map` be borrowed for `'1`