tracing icon indicating copy to clipboard operation
tracing copied to clipboard

Add fake return to improve span on type error in `tracing::instrument`

Open compiler-errors opened this issue 1 year ago • 10 comments

Motivation

Return type errors on instrumented async functions are a bit vague, since the type error originates within the macro itself due to the indirection of additional async {} blocks generated in the proc-macro (and due to the way that inference propagates around in Rust).

This leads to a pretty difficult to understand error. For example:

#[instrument]
async fn foo() -> String {
  ""
}

results in...

error[E0308]: mismatched types
 --> src/main.rs:1:1
  |
1 | #[tracing::instrument]
  | ^^^^^^^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
  | |
  | expected struct `String`, found `&str`

Solution

Installs a fake return statement as the first thing that happens in the auto-generated block of an instrumented async function.

This causes the coercion machinery within rustc to infer the right return type (matching the the outer function) eagerly, as opposed to after the async {} block has been type-checked.

This will cause us to both be able to point out the return type span correctly, and properly suggest fixes on the expressions that cause the type mismatch.

After this change, the example code above compiles to:

error[E0308]: mismatched types
  --> src/main.rs:3:5
   |
3  |     ""
   |     ^^- help: try using a conversion method: `.to_string()`
   |     |
   |     expected struct `String`, found `&str`
   |
note: return type inferred to be `String` here
  --> src/main.rs:2:20
   |
2  | async fn foo() -> String {
   |                   ^^^^^^

compiler-errors avatar Aug 08 '22 22:08 compiler-errors

Note:

Is it possible to provide a UI test (like https://github.com/dtolnay/trybuild) for tracing macros? Otherwise, any recommendations on how to provide a test for this change, since all affected code is not expected to compile (and thus probably doesn't work with a traditional unit test)?

compiler-errors avatar Aug 08 '22 22:08 compiler-errors

Note:

Is it possible to provide a UI test (like https://github.com/dtolnay/trybuild) for tracing macros? Otherwise, any recommendations on how to provide a test for this change, since all affected code is not expected to compile (and thus probably doesn't work with a traditional unit test)?

it's fine to introduce a dev dependency on trybuild for testing this.

hawkw avatar Aug 08 '22 22:08 hawkw

it's fine to introduce a dev dependency on trybuild for testing this.

@davidbarsky just told me to do the same -- will do!

compiler-errors avatar Aug 08 '22 22:08 compiler-errors

Okay, think this is ready for review. Sorry for the force-pushes, wanted to make sure the history was clean.

compiler-errors avatar Aug 08 '22 22:08 compiler-errors

(as a side note, you don't need to force push to branches, as all pull requests will be merged by squashing. see https://github.com/tokio-rs/tracing/blob/master/CONTRIBUTING.md#commit-squashing for details.)

hawkw avatar Aug 08 '22 23:08 hawkw

Good to know. Guess I really should've read the contributing guide first, my bad.

compiler-errors avatar Aug 08 '22 23:08 compiler-errors

(sorry, that force push is because I am dumb and don't know how to use git)

compiler-errors avatar Aug 08 '22 23:08 compiler-errors

no worries, it's nto a big deal!

hawkw avatar Aug 08 '22 23:08 hawkw

mercurial + the diff tool encourages the equivalent of force pushes, but github punishes you for it, so no worries.

davidbarsky avatar Aug 09 '22 02:08 davidbarsky

also used to force-pushing when working on rustc because bors doesn't auto-squash :smile_cat:

compiler-errors avatar Aug 09 '22 02:08 compiler-errors

CI failure is a new clippy warning, unrelated to this change: https://github.com/tokio-rs/tracing/runs/7842367961?check_suite_focus=true I'll fix that on main.

hawkw avatar Aug 15 '22 17:08 hawkw

Would it be too much to ask for an #[allow(clippy::unreachable)] to be added on line 67? (I can open a PR if necessary, or if anyone can directly make that change on master branch, that should be fine too.)

https://github.com/tokio-rs/tracing/blob/196e83e1f3d6d55fa55a5b82e7d36104d56ab4fd/tracing-attributes/src/expand.rs#L66-L73

We use #![warn(clippy::unreachable)] across our codebase and we now receive a load of clippy warnings about this unreachable! call after the tracing upgrade.

SanchithHegde avatar Oct 18 '22 19:10 SanchithHegde

I think opening a PR for this would be fine. Alternatively, one could do the same thing as #[async_trait] and use an alternative desugaring to provide the same return type hint: https://github.com/dtolnay/async-trait/blob/master/src/expand.rs#L374

Though please be careful that it handles return-position impl Trait correctly, since async_trait doesn't need to handle that, but this definitely does.

compiler-errors avatar Oct 18 '22 19:10 compiler-errors