Skip to content

Commit

Permalink
attributes: fix compile error with instrumented async functions (#1616)
Browse files Browse the repository at this point in the history
## Motivation

The changes in #1607 introduced a potential compilation error when using
the `#[instrument]` attribute on `async fn`s that return a type that
includes a closure or is otherwise unnameable. This is because the
future's body code was quoted in two separate places in order to have a
separate branch when the span is statically disabled. This means that
when a closure is returned, it will technically have two distinct types
based on whether or not the span is enabled, since it originates from
two separate source code locations (although `quote_spanned!` obscures
this, so the compiler diagnostic will appear to have two closures
originating from the same location).

## Solution

This branch fixes this issue by changing the code generated for
`#[instrument]`ed async functions. Unfortunately, for async functions,
we can't have the optimization of not creating the span at all when the
level is disabled, because we need to create the span _before_ creating
the future, as it may borrow arguments.

I've also added tests reproducing issue #1615

Fixes #1615
  • Loading branch information
hawkw committed Oct 5, 2021
1 parent d309e7e commit 7191538
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
9 changes: 5 additions & 4 deletions tracing-attributes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,15 +731,16 @@ fn gen_block(
};

return quote_spanned!(block.span()=>
if tracing::level_enabled!(#level) {
let __tracing_attr_span = #span;
let __tracing_attr_span = #span;
let __tracing_instrument_future = #mk_fut;
if !__tracing_attr_span.is_disabled() {
tracing::Instrument::instrument(
#mk_fut,
__tracing_instrument_future,
__tracing_attr_span
)
.await
} else {
#mk_fut.await
__tracing_instrument_future.await
}
);
}
Expand Down
15 changes: 15 additions & 0 deletions tracing-attributes/tests/async_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ async fn test_async_fn(polls: usize) -> Result<(), ()> {
future.await
}

// Reproduces a compile error when returning an `impl Trait` from an
// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
#[instrument]
async fn test_ret_impl_trait(n: i32) -> Result<impl Iterator<Item = i32>, ()> {
let n = n;
Ok((0..10).filter(move |x| *x < n))
}

// Reproduces a compile error when returning an `impl Trait` from an
// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
#[instrument(err)]
async fn test_ret_impl_trait_err(n: i32) -> Result<impl Iterator<Item = i32>, &'static str> {
Ok((0..10).filter(move |x| *x < n))
}

#[instrument]
async fn test_async_fn_empty() {}

Expand Down

0 comments on commit 7191538

Please sign in to comment.