#Is this a compiler bug or something I didn't understand?

3 messages · Page 1 of 1 (latest)

stark rover
#
use std::sync::{Arc, Mutex};
use tokio::sync::Notify;

struct Allowance {
    state: Mutex<(bool, bool)>, //allow,allowance_acquired
    notify: Notify,
}

async fn test(allowance: Arc<Allowance>) {
    let wait_for_not_allow = {
        let mut allowance_guard = allowance.state.lock().unwrap();
        if !allowance_guard.0 || allowance_guard.1 {
            return;
        }
        allowance_guard.1 = true;
        let mut notified = allowance.notify.notified();
        let clear_guard = scopeguard::guard((), |_| {
            allowance.state.lock().unwrap().1 = false;
        });
        // !There is no 'move' here, why doesn't the compiler report an error? After leave block, won't 'clear_guard' and 'notified' go out of scope?
        async {
            clear_guard;
            loop {
                notified.await;
                notified = allowance.notify.notified();
                if !allowance.state.lock().unwrap().0 {
                    break;
                }
            }
        }
    };
    wait_for_not_allow.await;
}

#[tokio::main]
async fn main() {
    test(Arc::new(Allowance {
        state: Mutex::new((true, false)),
        notify: Notify::new(),
    }))
    .await;
}
lucid thistle
#

where were you expecting to get the error exactly?

#

for the record, the move keyword only tells rust to move a value if it would otherwise have borrowed it. in other words, not including the move keyword does not mean that a value won't be moved.

for example, this is possible:

#[tokio::main]
async fn main() {
    let my_str = String::from("hello");
    async {
        // this will move my_str even though there's no move keyword,
        // because drop() takes the argument by value, not reference
        drop(my_str);
    }.await;

    // this would be an error, because my_str has been moved
    //println!("{my_str}");
}