tokio-rs / toasty

An async ORM for Rust (incubating)
MIT License
1.09k stars 26 forks source link

lifetime errors using db with axum #13

Closed codegod100 closed 1 month ago

codegod100 commented 1 month ago
struct AppState {
    db: Arc<Db>,
    tera: Tera,
}
error: implementation of `Send` is not general enough
  --> examples/toasty/main.rs:72:21
   |
72 |         .route("/", get(root))
   |                     ^^^^^^^^^ implementation of `Send` is not general enough
   |
   = note: `Send` would have to be implemented for the type `&Schema`
   = note: ...but `Send` is actually implemented for the type `&'0 Schema`, for some specific lifetime `'0`
error: implementation of `IntoSelect` is not general enough
  --> examples/toasty/main.rs:72:21
   |
72 |         .route("/", get(root))
   |                     ^^^^^^^^^ implementation of `IntoSelect` is not general enough
   |
   = note: `IntoSelect<'_>` would have to be implemented for the type `Select<'_, Like>`
   = note: ...but `IntoSelect<'0>` is actually implemented for the type `Select<'0, Like>`, for some specific lifetime `'0`
carllerche commented 1 month ago

Is there more code than this? What does root look like?

codegod100 commented 1 month ago
#[axum::debug_handler]
async fn root(State(state): State<AppState>) -> Result<Html<String>, AppError> {
    let context = Context::new();
    let tera = state.tera;
    let db = state.db;
    let user = User::find_by_name("Guy").first(&db).await?.unwrap();
    let mut bookmarks = Vec::new();
    let mut q = user.likes().all(&db).await.unwrap();
    while let Some(like) = q.next().await {
        bookmarks.push(like.unwrap().bookmark().find(&db).await.unwrap());
    }
    println!("{name} likes {bookmarks:?}", name = user.name);
    let render = tera.render("index.tera.html", &context)?;
    Ok(Html(render))
}
carllerche commented 1 month ago

Thanks. I know what is going on. It is going to take a bunch of reshuffling lifetimes internally, but I should have a fix soon.

alaingilbert commented 1 month ago

This error can also be triggered with a simple tokio::spawn.

    let db = Db::new(schema, driver).await;
    tokio::spawn(async {
        User::find_by_name("foo").first(&db).await.unwrap();
    });

Glad you know what's going on. Can't wait to see what's the fix :)

carllerche commented 1 month ago

I isolated it as a test and the fix will be merged soon: https://github.com/tokio-rs/toasty/pull/21/files#diff-e669e107b34d2d12ea757a08b7386701e19cc367aeb5fee09ff0912e7d2b8631

carllerche commented 1 month ago

I haven't verified that your original repro works yet. If it doesn't, there is a second (or more) layer to this.

carllerche commented 1 month ago

This error can also be triggered with a simple tokio::spawn.

    let db = Db::new(schema, driver).await;
    tokio::spawn(async {
        User::find_by_name("foo").first(&db).await.unwrap();
    });

Glad you know what's going on. Can't wait to see what's the fix :)

For this, you need to throw Db in an Arc.

alaingilbert commented 1 month ago

I just meant the error was reproducible using the spawn instead of trying to reproduce with the whole axum framework, but it's all good now, working fine with the fix :)