Skip to content

Commit

Permalink
add better error message when using async-trait (#149)
Browse files Browse the repository at this point in the history
* add better error message when using `async-trait`

* change output file

* move #121 compile tests into trybuild harness
  • Loading branch information
mellowagain authored Oct 25, 2023
1 parent 1381182 commit 2b43d0a
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 4 deletions.
22 changes: 21 additions & 1 deletion autometrics-macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::parse::{AutometricsArgs, Item};
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
use proc_macro2::TokenStream;
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
use std::env;
use syn::{
Expand All @@ -22,6 +22,13 @@ pub fn autometrics(
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let args = parse_macro_input!(args as parse::AutometricsArgs);

// if the input has yet to be modified by the `async-trait` crate, we will fail parsing in
// in the next line, so lets error early now
if let Err(err) = check_async_trait(&item) {
return err.into_compile_error().into();
}

let item = parse_macro_input!(item as Item);

let result = match item {
Expand All @@ -37,6 +44,19 @@ pub fn autometrics(
output.into()
}

fn check_async_trait(input: &proc_macro::TokenStream) -> Result<()> {
let str = input.to_string();

if str.contains("#[async_trait]") || str.contains("#[async_trait::async_trait]") {
Err(syn::Error::new(
Span::call_site(),
"#[async_trait] must be defined BEFORE #[autometrics]",
))
} else {
Ok(())
}
}

#[proc_macro_derive(ResultLabels, attributes(label))]
pub fn result_labels(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as syn::DeriveInput);
Expand Down
1 change: 1 addition & 0 deletions autometrics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ tracing-opentelemetry-0-20 = { package = "tracing-opentelemetry", version = "0.2
tracing-opentelemetry-0-21 = { package = "tracing-opentelemetry", version = "0.21.0", default-features = false, optional = true }

[dev-dependencies]
async-trait = "0.1.74"
axum = { version = "0.6", features = ["tokio"] }
criterion = "0.5"
http = "0.2"
Expand Down
34 changes: 34 additions & 0 deletions autometrics/tests/result_labels/fail/async_trait_support.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use async_trait::async_trait;
use autometrics::autometrics;

// https://github.com/autometrics-dev/autometrics-rs/issues/141

#[async_trait]
trait TestTrait {
async fn method() -> bool;
async fn self_method(&self) -> bool;
}

#[derive(Default)]
struct TestStruct;

#[autometrics]
#[async_trait]
impl TestTrait for TestStruct {
async fn method() -> bool {
true
}

async fn self_method(&self) -> bool {
true
}
}

fn main() {
let ts = TestStruct::default();

async move {
<TestStruct as TestTrait>::method().await;
ts.self_method().await;
};
}
29 changes: 29 additions & 0 deletions autometrics/tests/result_labels/fail/async_trait_support.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error: #[async_trait] must be defined BEFORE #[autometrics]
--> tests/result_labels/fail/async_trait_support.rs:15:1
|
15 | #[autometrics]
| ^^^^^^^^^^^^^^
|
= note: this error originates in the attribute macro `autometrics` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `TestStruct: TestTrait` is not satisfied
--> tests/result_labels/fail/async_trait_support.rs:31:9
|
31 | <TestStruct as TestTrait>::method().await;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TestTrait` is not implemented for `TestStruct`

error[E0599]: no method named `self_method` found for struct `TestStruct` in the current scope
--> tests/result_labels/fail/async_trait_support.rs:32:12
|
13 | struct TestStruct;
| ----------------- method `self_method` not found for this struct
...
32 | ts.self_method().await;
| ^^^^^^^^^^^ method not found in `TestStruct`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `TestTrait` defines an item `self_method`, perhaps you need to implement it
--> tests/result_labels/fail/async_trait_support.rs:7:1
|
7 | trait TestTrait {
| ^^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ fn issue_121_d() -> Result<impl ToString, impl std::error::Error> {
}
}

#[test]
fn invoke_issue_121() {
// we need to handle all three code generation cases
fn main() {
// we need to handle all four code generation cases
issue_121_a().unwrap();
issue_121_b().unwrap();
issue_121_c().unwrap();
Expand Down

0 comments on commit 2b43d0a

Please sign in to comment.