Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with specialization #25

Closed
jhpratt opened this issue Aug 19, 2019 · 4 comments · Fixed by #29
Closed

Compatibility with specialization #25

jhpratt opened this issue Aug 19, 2019 · 4 comments · Fixed by #29

Comments

@jhpratt
Copy link

jhpratt commented Aug 19, 2019

In Rocket, there's currently the following function:

impl<'r, R: Responder<'r> + Send + 'r, E: fmt::Debug + Send + 'r> Responder<'r> for Result<R, E> {
    default fn respond_to(self, req: &'r Request<'_>) -> response::ResultFuture<'r> {
        Box::pin(async move {
            match self {
                Ok(r) => r.respond_to(req).await,
                Err(e) => {
                    error_!("Response was a non-`Responder` `Err`: {:?}.", e);
                    Err(Status::InternalServerError)
                }
            }
        })
    }
}

I'm looking into rewriting the traits using this crate, and would like to write the function as

#[async_trait]
impl<'r, R: Responder<'r> + Send + 'r, E: fmt::Debug + Send + 'r> Responder<'r> for Result<R, E> {
    default async fn respond_to(self, req: &'r Request<'_>) -> response::Result<'r> {
        match self {
            Ok(r) => r.respond_to(req).await,
            Err(e) => {
                error_!("Response was a non-`Responder` `Err`: {:?}.", e);
                Err(Status::InternalServerError)
            }
        }
    }
}

When doing this, I get an error.

error: missing `fn`, `type`, or `const` for impl-item declaration
   --> core/lib/src/response/responder.rs:296:99
    |
296 |   impl<'r, R: Responder<'r> + Send + 'r, E: fmt::Debug + Send + 'r> Responder<'r> for Result<R, E> {
    |  ___________________________________________________________________________________________________^
297 | |     default async fn respond_to(self, req: &'r Request<'_>) -> response::Result<'r> {
    | |____^ missing `fn`, `type`, or `const`

I presume this is because of specialization, as it seems to work everywhere else.

@dtolnay
Copy link
Owner

dtolnay commented Aug 19, 2019

This looks like a compiler bug -- it fails in rustc's parser before even hitting async_trait.

macro_rules! item {
    ($i:item) => {}
}

item! {
    trait Trait {
        async default fn f() {}
    }
}

item! {
    trait Trait {
        default async fn f() {}
    }
}
error: expected one of `extern`, `fn`, or `unsafe`, found `default`
 --> src/main.rs:7:15
  |
7 |         async default fn f() {}
  |               ^^^^^^^ expected one of `extern`, `fn`, or `unsafe` here

error: missing `fn`, `type`, or `const` for trait-item declaration
  --> src/main.rs:12:18
   |
12 |       trait Trait {
   |  __________________^
13 | |         default async fn f() {}
   | |________^ missing `fn`, `type`, or `const`

error: aborting due to 2 previous errors

Could you follow up with a bug report in rust-lang/rust?

@jhpratt
Copy link
Author

jhpratt commented Aug 19, 2019

Filed as rust-lang/rust#63716.

@dtolnay
Copy link
Owner

dtolnay commented Sep 16, 2019

Specialization works as of the rustc parser fix in rust-lang/rust#63759. The Responder<'r> trait would probably still be blocked on #28.

@dtolnay
Copy link
Owner

dtolnay commented Sep 16, 2019

Should work as of async-trait 0.1.12 thanks to #30.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants