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()));