-
-
Save durka/375c277cc7df3a4608da to your computer and use it in GitHub Desktop.
Macro for pre-computing method arguments to avoid borrowck errors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Precompute a method's arguments before the call so that borrowck sees | |
/// them the same way that trans does. | |
macro_rules! unborrow { | |
// this rule fires when we have parsed all the arguments | |
// fall through to output stage | |
(@parse () -> ($names:tt $lets:tt) $($thru:tt)*) => { | |
unborrow!(@out $names $lets $($thru)*) | |
}; | |
// parse an argument and continue parsing | |
// this is the key rule, assigning a name for the argument and generating the let statement | |
(@parse ($arg:expr, $($rest:tt)*) -> ([$($names:ident),*] [$($lets:stmt);*]) $($thru:tt)*) => { | |
unborrow!(@parse ($($rest)*) -> ([$($names,)* arg] [$($lets;)* let arg = $arg]) $($thru)*) | |
// ^ ^ | |
// right here an ident is created out of thin air using hygiene | |
// every time the macro recurses, we get a new syntax context so "arg" is actually a new identifier! | |
}; | |
(@out [$($names:ident),*] [$($lets:stmt);*] $obj:ident $meth:ident) => {{ | |
$($lets;)* | |
$obj.$meth($($names),*) | |
}}; | |
// macro entry point | |
($obj:ident . $meth:ident ($($args:expr),*)) => { | |
unborrow!(@parse ($($args,)*) -> ([] []) $obj $meth) | |
// | | | ^ info about the method call, saved for later | |
// | | ^ generated let statements | |
// | ^ generated argument names | |
// ^ arguments to be parsed | |
} | |
} | |
fn main() { | |
let mut v = vec![1, 2, 3]; | |
// v.reserve(v.capacity()); | |
unborrow!(v.reserve(v.capacity())); | |
println!("{} {:?}", v.capacity(), v); | |
// v.insert(v.len() - 1, v[0] + 41); | |
unborrow!(v.insert(v.len() - 1, v[0] + 41)); | |
println!("{:?}", v); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment