launchbadge / sqlx

🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite.
Apache License 2.0
12.48k stars 1.19k forks source link

Migrate macro in async-trait: higher ranked lifetime error #2529

Open SimTheFool opened 1 year ago

SimTheFool commented 1 year ago

Bug Description

When trying to implement a trait async function, that error spaws. It works well outside traits.

error: higher-ranked lifetime error
  --> tests/sqlx.rs:52:39
   |
52 |       async fn migrate(&mut self) -> () {
   |  _______________________________________^
53 | |         sqlx::migrate!("./migrations")
54 | |             .run(&mut self.conn)
55 | |             .await
56 | |             .unwrap();
57 | |     }
   | |_____^
   |
   = note: could not prove `Pin<Box<[async block@tests/sqlx.rs:52:39: 57:6]>>: CoerceUnsized<Pin<Box<(dyn futures::Future<Output = ()> + std::marker::Send + 'd)>>>`

Minimal Reproduction

Here is a playground with struct and trait, en dependencies involved.

Info

Arthex1 commented 1 year ago

Hello there, I had the same issue. Has anyone found a solution yet?

tiquthon commented 1 year ago

I had the same problem for around a month and found a workaround today.

Instead of using .run(&mut self.conn), I use the undocumented, but existing .run_direct(&mut self.conn). (Look for run_direct in https://docs.rs/crate/sqlx-core/0.6.3/source/src/migrate/migrator.rs)

With this your migrate would look like:

async fn migrate(&mut self) -> () {
    sqlx::migrate!("./migrations")
        .run_direct(&mut self.conn)
        .await
        .unwrap();
}

As far as I know the Future created by sqlx::migrate!(...).run(...) is itself or with its data not Send, but the marker Send is needed by the async runtime.

It looks like this is could be a bug in Rust itself or the Migrator created by sqlx::migrate(...) has to be made Send, BUT I don't know for sure as I also don't have enough knowledge.