dtolnay / async-trait

Type erasure for async trait methods
Apache License 2.0
1.84k stars 85 forks source link

incorrect use led to compile error with no location information #95

Closed davepacheco closed 4 years ago

davepacheco commented 4 years ago

I ran into a case where I used async_trait incorrectly and the result was a compiler error with no line number information. This seems more likely a compiler issue, not async_trait, but I had trouble reproducing the issue without async_trait. Here's my example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a41abc2ee0d6fc3714ff09e8172aae94

Copying the code here:

use async_trait::async_trait; // 0.1.30

#[async_trait]
pub trait FooTrait {
    #[async_trait] // <-- This shouldn't be here.
    async fn a();
    async fn foo();
}

struct FooStruct {}

#[async_trait]
impl FooTrait for FooStruct {
    async fn foo() {}
}

Here's the build output:

   Compiling playground v0.0.1 (/playground)
error: expected one of: `unsafe`, `pub`, `trait`, `impl`

error: aborting due to previous error

error: could not compile `playground`.

To learn more, run the command again with --verbose.

Obviously I've applied the macro incorrectly here, but it's unfortunate that the compiler can't tell me where the problem is. Is this a known issue, maybe because the code that doesn't compile was created by the macro? Thanks in advance, and sorry if I'm down the wrong path here!

dtolnay commented 4 years ago

It's a compiler bug: https://github.com/rust-lang/rust/issues/43081. The compiler randomly loses all location information before it even gets to applying macros.

davepacheco commented 4 years ago

Thanks for that pointer! And sorry to bug you with another instance of that issue.

Aaron1011 commented 4 years ago

This will be fixed by https://github.com/rust-lang/rust/pull/72306

dtolnay commented 4 years ago

Confirmed fixed in rustc master. The error is not so good but it is at least correctly located. (The error is the inner #[async_trait] attempting to interpret your async fn as a trait or trait impl.)

error: expected one of: `unsafe`, `pub`, `trait`, `impl`
 --> src/main.rs:6:5
  |
6 |     async fn a();
  |     ^^^^^