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

References or lifetimes in generic types results in lifetimes in impl do not match this method in trait #175

Closed
EliseZeroTwo opened this issue Aug 9, 2021 · 5 comments

Comments

@EliseZeroTwo
Copy link

Hi!

Seemingly providing references or lifetimes in generic types breaks async-trait.

Tested on: rustc 1.56.0-nightly (ad981d58e 2021-08-08) & rustc 1.54.0 (a178d0322 2021-07-26)

Code used to replicate this:

#[async_trait(?Send)]
pub trait DbOpDelete<IdT>: Sized {
	async fn delete(pool: &sqlx::PgPool, id: IdT) -> Result<Option<Self>, bool>;
}

#[async_trait(?Send)]
impl DbOpDelete<&str> for DbCustomer {
    async fn delete(pool: &sqlx::PgPool, id: &str) -> Result<Option<Self>, bool> {
        Err(false)
    }
}

Error:

error[E0195]: lifetime parameters or bounds on method `delete` do not match the trait declaration
  --> src/schema/customer.rs:31:14
   |
31 |     async fn delete(pool: &sqlx::PgPool, id: &str) -> Result<Option<Self>, bool> {
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
   |
  ::: src/schema.rs:37:14
   |
37 |     async fn delete(pool: &sqlx::PgPool, id: IdT) -> Result<Option<Self>, bool>;
   |              ------------------------------------ lifetimes in impl do not match this method in trait

🖤

@taiki-e
Copy link
Contributor

taiki-e commented Aug 9, 2021

Workaround: using an explicit lifetime:

  #[async_trait(?Send)]
- impl DbOpDelete<&str> for DbCustomer {
+ impl<'a> DbOpDelete<&'a str> for DbCustomer {
-     async fn delete(pool: &sqlx::PgPool, id: &str) -> Result<Option<Self>, bool> {
+     async fn delete(pool: &sqlx::PgPool, id: &'a str) -> Result<Option<Self>, bool> {
          Err(false)

related: #106 #64

@taiki-e
Copy link
Contributor

taiki-e commented Aug 9, 2021

proc-macro cannot recognize that the anonymous lifetime in the method argument and the anonymous lifetime in the trait parameter are the same, so IIUC there is no way to automatically resolve this on the proc-macro side.

@EliseZeroTwo
Copy link
Author

Thank you for the fast response! With this I run into another problem (both on nightly & stable):

Code:

pub struct OwO;

#[async_trait(?Send)]
pub trait Trait<IdT>: Sized {
	async fn test(id: IdT) -> Self;
}

#[async_trait(?Send)]
impl<'a> Trait<&'a str> for OwO {
    async fn test(id: &'a str) -> Self {
        todo!()
    }
}

Error:

error[E0276]: impl has stricter requirements than trait
  --> src/main.rs:12:5
   |
7  |     async fn test(id: IdT) -> Self;
   |     ------------------------------- definition of `test` from trait
...
12 |     async fn test(id: &'a str) -> Self {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'async_trait`

For more information about this error, try `rustc --explain E0276`.

However this seems like a separate issue, if this is not just me missing something obvious would you like me to open a new issue?

@taiki-e
Copy link
Contributor

taiki-e commented Aug 9, 2021

That seems related to #8. Workaround is:

  #[async_trait(?Send)]
  pub trait Trait<IdT>: Sized {
-     async fn test(id: IdT) -> Self;
+     async fn test(id: IdT) -> Self
+     where
+         IdT: 'async_trait;
  }

playground

@EliseZeroTwo
Copy link
Author

that worked, thanks! I'm unsure if you want me to mark this as closed or not so I will just leave it, please feel free to mark it as closed

🖤

@dtolnay dtolnay closed this as completed Aug 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants