Macro unborrow::unborrow [] [src]

macro_rules! unborrow {
    (@parse () -> ($names:tt $lets:tt) $($thru:tt)*) => { ... };
    (@parse ($arg:expr, $($rest:tt)*) -> ([$($names:ident),*] [$($lets:stmt);*]) $($thru:tt)*) => { ... };
    (@out [$($names:ident),*] [$($lets:stmt);*] ($($meth:ident)::+) $arg1:expr) => { ... };
    (@out [$($names:ident),*] [$($lets:stmt);*] $($obj:ident).+) => { ... };
    ($($obj:ident).+ ($($args:expr),*)) => { ... };
    ($($meth:ident)::+ ($arg1:expr, $($args:expr),*)) => { ... };
}

Explicitly precompute a method's arguments before the call so that borrowck sees them the same way that trans does.

Examples

let mut v = vec![1, 2, 3];

// this line would cause an error because borrowck consider `v` borrowed by `reserve`
// during its parameter list
// v.reserve(v.capacity()); //~ERROR cannot borrow `v`
// but wrap the call in unborrow!() and it works!
unborrow!(v.reserve(v.capacity()));
assert!(v.capacity() >= 6);
assert_eq!(v, [1, 2, 3]);
 
// similar to the above, both v.len()-1 and v[0]+41 require borrowing `v` and we can't
// do that while borrowck thinks is is mutably borrowed by `insert`
// v.insert(v.len() - 1, v[0] + 41); //~ERROR cannot borrow `v`
// but wrap the call in unborrow!() and it works!
unborrow!(v.insert(v.len() - 1, v[0] + 41));
assert_eq!(v, [1, 2, 42, 3]);

// it also works for nested objects!
struct Wrapper { v: Vec<i32> }
let mut w = Wrapper { v: vec![1, 2, 3] };
unborrow!(w.v.reserve(w.v.capacity()));

// ...and with free functions! (the first argument is assumed to be the mutable borrow)
use std::mem;
unborrow!(mem::replace(&mut v, v.clone()));