tokio-rs / tracing

Application level tracing for Rust.
https://tracing.rs
MIT License
5.33k stars 697 forks source link

`tracing::instrument(ret)` errors on function with `&mut` args returning `&`/`&mut` #2857

Closed jdygert-spok closed 6 months ago

jdygert-spok commented 7 months ago

Bug Report

Version

tracing v0.1.40
tracing-attributes v0.1.27 (proc-macro)
tracing-core v0.1.32

Description

When using instrument(ret) (or instrument(err)), the closure in the generated code is inferred to be Fn or FnMut, which causes compile errors when trying to return a reference to an argument.

// error: lifetime may not live long enough
// note: closure implements `Fn`, so references to captured variables can't escape the closure
#[tracing::instrument(ret)]
fn foo(x: &mut ()) -> &() {
    x
}

// error: captured variable cannot escape `FnMut` closure body
#[tracing::instrument(ret)]
fn foo(x: &mut ()) -> &mut () {
    x
}

Possible Solution

Force the generated closure to be FnOnce, either via a function:

fn force_fn_once<T, F: FnOnce() -> T>(f: F) -> F {
    f
}

force_fn_once(move || {
    // ...
})

Or by rebinding a captured variable

let outer = &mut ();
move || {
    { let inner = outer; }
    // ...
}
Hakuyume commented 6 months ago

Seems similar to #2796 ?

jdygert-spok commented 6 months ago

Yep. I swear I searched for it... Closing as duplicate