## 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: ```rust #[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 { | ^^^^^^ ```
46 lines
709 B
Rust
46 lines
709 B
Rust
#![allow(unreachable_code)]
|
|
|
|
#[tracing::instrument]
|
|
async fn unit() {
|
|
""
|
|
}
|
|
|
|
#[tracing::instrument]
|
|
async fn simple_mismatch() -> String {
|
|
""
|
|
}
|
|
|
|
// FIXME: this span is still pretty poor
|
|
#[tracing::instrument]
|
|
async fn opaque_unsatisfied() -> impl std::fmt::Display {
|
|
("",)
|
|
}
|
|
|
|
struct Wrapper<T>(T);
|
|
|
|
#[tracing::instrument]
|
|
async fn mismatch_with_opaque() -> Wrapper<impl std::fmt::Display> {
|
|
""
|
|
}
|
|
|
|
#[tracing::instrument]
|
|
async fn early_return_unit() {
|
|
if true {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
#[tracing::instrument]
|
|
async fn early_return() -> String {
|
|
if true {
|
|
return "";
|
|
}
|
|
String::new()
|
|
}
|
|
|
|
#[tracing::instrument]
|
|
async fn extra_semicolon() -> i32 {
|
|
1;
|
|
}
|
|
|
|
fn main() {}
|