

現在 tokio のチュートリアルに取り組んでいます。  
["Shared state"](https://tokio.rs/tokio/tutorial/shared-state) の "Holding a
`MutexGuard` across an `.await`" で、 `MutexGuard` は `Send` でないため、`.await`
をまたいで利用できないことを学びました。  
そこで示されていた例についてコンパイルを試みて、「`MutexGuard` を `.await`
をまたいで使用したら実際にコンパイルエラーを起こすか」を確認しようとしたのですが、コンパイルが問題なく通って、実行までされてしまいました。  
このコードはなぜ問題なくコンパイルされるのでしょうか？

実行したコードは以下の通りです：

[code]

    use std::sync::Mutex;
    
    async fn increment_and_do_stuff(mutex: &Mutex<i32>) {
        let mut lock = mutex.lock().unwrap();
        *lock += 1;
        
        do_something_async().await;
    }
    
    async fn do_something_async() {}
    
    #[tokio::main]
    async fn main() {
        let m = Mutex::new(1);
        increment_and_do_stuff(&m).await;
        println!("{}", m.lock().unwrap());
    }
    
[/code]

実行結果は以下の通りです：

[code]

    2
    
[/code]


CC BY-SA 4.0
2023-09-10T02:51:09.100
96170
2023-09-10T04:44:47.470
59729
question
rust
Rust で `MutexGuard` は `Send` でないため、`.await` をまたいで利用できないはずなのにできてしまう


Rust のコミュニティで同じ質問をして解決しました。

`Send` が要求されるのはあくまでも「`tokio::spawn` で作成されるタスク」に対してなので、`tokio::spawn`
を利用していない今回のケースでは、問題が起こらない  
ということのようです。

なので、上記のコードは問題なくコンパイルされますが、下記のようなコードではコンパイルエラーが起きます：

[code]

    use std::sync::Mutex;
    
    async fn increment_and_do_stuff(mutex: &Mutex<i32>) {
        let mut lock = mutex.lock().unwrap();
        *lock += 1;
        
        do_something_async().await;
    }
    
    async fn do_something_async() {}
    
    #[tokio::main]
    async fn main() {
        let m = Mutex::new(1);
        tokio::spawn(async move {
            increment_and_do_stuff(&m).await
        });
    }
    
[/code]


CC BY-SA 4.0
2023-09-10T04:44:47.470
96172
2023-09-10T04:44:47.470
59729
96170
answer