Skip to content

implementation of 'std::marker::Send' is not general enough error when changing from and_run to and_run2 #1490

@tyilo

Description

@tyilo

Versions/Environment

  1. What version of Rust are you using? 1.90
  2. What operating system are you using? Linux
  3. What versions of the driver and its dependencies are you using? (Run
    cargo pkgid mongodb & cargo pkgid bson)
registry+https://github.com/rust-lang/crates.io-index#[email protected]
registry+https://github.com/rust-lang/crates.io-index#[email protected]
  1. What version of MongoDB are you using? (Check with the MongoDB shell using db.version()) N/A
  2. What is your MongoDB topology (standalone, replica set, sharded cluster, serverless)? N/A

Describe the bug

Current code (minified) works fine with and_run:

use mongodb::{BoxFuture, Client, ClientSession};
use std::sync::Arc;

struct Foo {
    client: Client,
}

impl Foo {
    fn new() -> Self {
        Self { client: todo!() }
    }

    async fn do_stuff_in_trasaction(&self) -> mongodb::error::Result<()> {
        let mut session = self.client.start_session().await?;
        session
            .start_transaction()
            .and_run(self, |session, this| {
                Box::pin(this.inside_transaction(session))
            })
            .await?;
        Ok(())
    }

    async fn inside_transaction(&self, session: &mut ClientSession) -> mongodb::error::Result<()> {
        println!("Inside transaction with session: {session:?}");
        Ok(())
    }
}

type TaskHandler = Arc<dyn Fn() -> BoxFuture<'static, ()> + Send + Sync>;

#[derive(Default)]
struct RecurringTasks {
    tasks: Vec<TaskHandler>,
}

impl RecurringTasks {
    fn register_task(&mut self, f: impl Fn() -> BoxFuture<'static, ()> + 'static + Send + Sync) {
        self.tasks.push(Arc::new(f));
    }
}

fn main() {
    let mut tasks = RecurringTasks::default();
    let foo = Arc::new(Foo::new());
    tasks.register_task(move || {
        let foo = foo.clone();
        Box::pin(async move {
            foo.do_stuff_in_trasaction().await.unwrap();
        })
    });
}

but changing the implementation of do_stuff_in_transaction to use and_run2:

async fn do_stuff_in_trasaction(&self) -> mongodb::error::Result<()> {
    let mut session = self.client.start_session().await?;
    session
        .start_transaction()
        .and_run2(async move |session| self.inside_transaction(session).await)
        .await?;
    Ok(())
}

I get the following error when compiling:

   Compiling test-and-run v0.1.0 (/tmp/test-and-run)
warning: unreachable expression
  --> src/main.rs:10:9
   |
10 |         Self { client: todo!() }
   |         ^^^^^^^^^^^^^^^-------^^
   |         |              |
   |         |              any code following this expression is unreachable
   |         unreachable expression
   |
   = note: `#[warn(unreachable_code)]` on by default

error: implementation of `Send` is not general enough
  --> src/main.rs:46:9
   |
46 | /         Box::pin(async move {
47 | |             foo.do_stuff_in_trasaction().await.unwrap();
48 | |         })
   | |__________^ implementation of `Send` is not general enough
   |
   = note: `Send` would have to be implemented for the type `&'0 Foo`, for any lifetime `'0`...
   = note: ...but `Send` is actually implemented for the type `&'1 Foo`, for some specific lifetime `'1`

warning: `test-and-run` (bin "test-and-run") generated 1 warning
error: could not compile `test-and-run` (bin "test-and-run") due to 1 previous error; 1 warning emitted

I would expect I could upgrade to use and_run2 when and_run is deprecated.

There seems to be some discussion about this error in the implementation PR #1372 but the description says:

I think it pretty unlikely actual library users will run into this.

Well, I'm a library user and ran into it.

I can't change RecurringTasks but is there a way to modify do_stuff_in_trasaction so that it can use and_run2 instead of and_run?

If not, I don't think and_run should be deprecated.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions