diff --git a/tracing-attributes/src/expand.rs b/tracing-attributes/src/expand.rs index aa3719d9e..7eb7384d5 100644 --- a/tracing-attributes/src/expand.rs +++ b/tracing-attributes/src/expand.rs @@ -351,11 +351,27 @@ fn gen_block( } ); + // Bind a non-Copy value to make the closure FnOnce + // (https://github.com/tokio-rs/tracing/issues/2796). + let fn_once_init = quote!( + let __tracing_attr_fn_once = { + struct TracingAttrFnOnce; + TracingAttrFnOnce + }; + ); + let fn_once_bind = quote!( + let __tracing_attr_fn_once = __tracing_attr_fn_once; + ); + match (err_event, ret_event) { (Some(err_event), Some(ret_event)) => quote_spanned! {block.span()=> #span + #fn_once_init #[allow(clippy::redundant_closure_call)] - match (move || #block)() { + match (move || { + #fn_once_bind + #block + })() { #[allow(clippy::unit_arg)] Ok(x) => { #ret_event; @@ -369,8 +385,12 @@ fn gen_block( }, (Some(err_event), None) => quote_spanned!(block.span()=> #span + #fn_once_init #[allow(clippy::redundant_closure_call)] - match (move || #block)() { + match (move || { + #fn_once_bind + #block + })() { #[allow(clippy::unit_arg)] Ok(x) => Ok(x), Err(e) => { @@ -381,8 +401,12 @@ fn gen_block( ), (None, Some(ret_event)) => quote_spanned!(block.span()=> #span + #fn_once_init #[allow(clippy::redundant_closure_call)] - let x = (move || #block)(); + let x = (move || { + #fn_once_bind + #block + })(); #ret_event; x ), diff --git a/tracing-attributes/tests/instrument.rs b/tracing-attributes/tests/instrument.rs index 2897316be..b9662b5ea 100644 --- a/tracing-attributes/tests/instrument.rs +++ b/tracing-attributes/tests/instrument.rs @@ -12,6 +12,21 @@ fn repro_2294() { let i = 42; } +// Reproduces a compile error when an instrumented function signature contains lifetimes +// (https://github.com/tokio-rs/tracing/issues/2796). +#[instrument(err)] +fn repro_2796_err(x: &mut u8) -> Result<&u8, &u8> { + Ok(x) +} +#[instrument(ret)] +fn repro_2796_ret(x: &mut u8) -> Result<&u8, &u8> { + Ok(x) +} +#[instrument(err, ret)] +fn repro_2796_err_ret(x: &mut u8) -> Result<&u8, &u8> { + Ok(x) +} + #[test] fn override_everything() { #[instrument(target = "my_target", level = "debug")]