Is this a rustc bug?

I have the following code failing to compile. giving

   ::: /home/zylthinking/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/tokio-1.11.0/src/task/spawn.rs:127:21
    |
127 |         T: Future + Send + 'static,
    |                     ---- required by this bound in `tokio::spawn`
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `std::sync::MutexGuard<'_, Box<ListHead>>`
    = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2> {ResumeTy, &'r Autex, Result<i32, i32>, autex::autex<'s>, std::sync::MutexGuard<'t0, Box<ListHead>>, &'t1 mut autex::autex<'t2>, ()}`
    = note: required because it appears within the type `[static generator@Autex::lock::{closure#0} for<'r, 's, 't0, 't1, 't2> {ResumeTy, &'r Autex, Result<i32, i32>, autex::autex<'s>, std::sync::MutexGuard<'t0, Box<ListHead>>, &'t1 mut autex::autex<'t2>, ()}]`
    = note: required because it appears within the type `from_generator::GenFuture<[static generator@Autex::lock::{closure#0} for<'r, 's, 't0, 't1, 't2> {ResumeTy, &'r Autex, Result<i32, i32>, autex::autex<'s>, std::sync::MutexGuard<'t0, Box<ListHead>>, &'t1 mut autex::autex<'t2>, ()}]>`
    = note: required because it appears within the type `impl Future`
    = note: required because it appears within the type `impl Future`
    = note: required because it appears within the type `for<'r, 's, 't0> {ResumeTy, &'r Autex, Autex, impl Future, (), Guard<'t0>, u64, Duration, Sleep}`
    = note: required because it appears within the type `[static generator@tests/tokio.rs:8:20: 17:6 for<'r, 's, 't0> {ResumeTy, &'r Autex, Autex, impl Future, (), Guard<'t0>, u64, Duration, Sleep}]`
    = note: required because it appears within the type `from_generator::GenFuture<[static generator@tests/tokio.rs:8:20: 17:6 for<'r, 's, 't0> {ResumeTy, &'r Autex, Autex, impl Future, (), Guard<'t0>, u64, Duration, Sleep}]>`
    = note: required because it appears within the type `impl Future`

It seems the auto generated future put a MutexGuard into it's generic parameter, which is dropped before await.

Just for a try, I put the code into another fn a(); this time, it compiles.
So, this is a compiler bug or there some reasonable things I don't know?

    fn a(&self, autx: &mut autex) {
        let mut g0 = self.mux.lock().unwrap();
        unsafe {
            g0.list_add_tail(&mut autx.ent);
        }
        drop(g0);
    }

    pub async fn lock<'a>(&'a self) -> Guard<'a> {
        let r = self
            .hold
            .atomic_compare_exchange(0, 1, Ordering::Relaxed, Ordering::Relaxed);
        if r.is_ok() {
            return Guard(self);
        }

        let mut autx = autex::new(self);

       // this line will compiles
        self.a(&mut autx);

        // but the following is not
        // let mut g0 = self.mux.lock().unwrap();
        // unsafe {
        //     g0.list_add_tail(&mut autx.ent);
        // }
        // drop(g0);

        let g1 = (&mut autx).await;
        let g2 = self.mux.lock().unwrap();
        unsafe {
            autx.ent.list_del();
        }
        drop(g2);
        g1
    }
1 Like

Currently the compiler uses only scope information and ignores drop for determining when things are alive. This means that it is stricter than necessary in determining when something is ok.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.