tracing icon indicating copy to clipboard operation
tracing copied to clipboard

`#[tracing::instrument(err)]` fails to build when Ok variant has lifetime, "lifetime may not live long enough"

Open tv42 opened this issue 2 years ago • 1 comments

Bug Report

Version

rust-tracing-instrument-bug v0.1.0 (/foo)
└── tracing v0.1.40
    ├── tracing-attributes v0.1.27 (proc-macro)
    └── tracing-core v0.1.32

Platform

Linux gear 6.1.59 #1-NixOS SMP PREEMPT_DYNAMIC Thu Oct 19 21:08:58 UTC 2023 x86_64 GNU/Linux

Crates

[dependencies]
tracing = "0.1.40"

Description

[tracing::instrument(ret)] fails to build in some scenarios where the return Ok value is generic over a lifetime.

$ cargo build
   Compiling rust-tracing-instrument-bug v0.1.0 (/foo)
error: lifetime may not live long enough
  --> src/lib.rs:16:5
   |
11 | #[tracing::instrument(skip(node), err)]
   | ---------------------------------------
   | |                                     |
   | |                                     return type of closure is Result<Option<Ref<'2>>, std::io::Error>
   | lifetime `'1` represents this closure's body
...
16 |     Ok(Some(x))
   |     ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
   |
   = note: closure implements `Fn`, so references to captured variables can't escape the closure

error: could not compile `rust-tracing-instrument-bug` (lib) due to previous error```
struct Node {}

struct Ref<'a> {
    node: &'a Node,
}

fn get_ref<'a>(_node: &'a Node) -> Ref<'a> {
    todo!();
}

#[tracing::instrument(skip(node), err)]
fn fails_to_compile_with_instrument<'a>(node: &'a mut Node) -> Result<Ref<'a>, std::io::Error> {
    let x = get_ref(node);
    Ok(x)
}

#[tracing::instrument(skip(node))]
fn works<'a>(node: &'a mut Node) -> Result<Ref<'a>, std::io::Error> {
    let x = get_ref(node);
    Ok(x)
}

Remove , err and it starts to build.

tv42 avatar Nov 07 '23 02:11 tv42

I had the same error. I found that I can suppress the error by capturing the mutable reference explicitly.

#[tracing::instrument(skip(node), err)]
fn fails_to_compile_with_instrument<'a>(node: &'a mut Node) -> Result<Ref<'a>, std::io::Error> {
    let node = node;  // capture
    let x = get_ref(node);
    Ok(x)
}

Hakuyume avatar Jan 08 '24 06:01 Hakuyume