Commit 2dc4aff1 authored by Raphaël Gomès's avatar Raphaël Gomès
Browse files

Check for mutability needed for closure

This prevents the "unused mut" warnings if we always put `mut` and the errors
if we don't and the closure needs mutability.
parent 45b76835f0cd
......@@ -26,15 +26,47 @@ pub fn timed(_attr_ts: TokenStream, fn_ts: TokenStream) -> TokenStream {
outer.sig.ident = func.sig.ident.to_owned();
let original_func_name = func.sig.ident.to_string();
// Figure out if the `inner` closure needs to be mut based on whether
// the original signature contains a `mut self`, `&mut self`,
// `mut thing: T` or a `thing: &mut T`.
// There are probably more ways you can have a signature need mutability,
// but this is good enough for now.
let needs_mut = func.sig.inputs.iter().any(|arg| match arg {
syn::FnArg::Receiver(rec) => rec.mutability.is_some(),
syn::FnArg::Typed(typed) => match *typed.pat {
syn::Pat::Ident(syn::PatIdent { mutability, .. }) => {
// Is it `mut arg: T`?
if mutability.is_some() {
return true;
}
// Is it `arg: &mut T`?
match *typed.ty {
syn::Type::Reference(ref r) => r.mutability.is_some(),
_ => false,
}
}
_ => false,
},
});
let mutability = if needs_mut {
quote! {mut}
} else {
quote! {}
};
let inner_block = &func.block;
let span = outer.sig.ident.span();
// We use `__micro_timer_inner` as a name in case it pops up in error
// messages to make it obvious that it's an issue caused by this crate,
// it is not meant to prevent name collision.
let block = quote_spanned! {
span=>
{
let timer = ::std::time::Instant::now();
let mut inner = || { #inner_block };
let ret = inner();
let #mutability __micro_timer_inner = || #inner_block;
let ret = __micro_timer_inner();
crate::log::trace!(
"Duration of `{}`: {:?}",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment