Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failing to match on a mutable pattern in tokio::select! #4182

Closed
bwc-x opened this issue Oct 19, 2021 · 0 comments · Fixed by #4211
Closed

Failing to match on a mutable pattern in tokio::select! #4182

bwc-x opened this issue Oct 19, 2021 · 0 comments · Fixed by #4211
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. M-macros Module: macros in the main Tokio crate

Comments

@bwc-x
Copy link

bwc-x commented Oct 19, 2021

As requested by Alice in the Users Forum.

Version
cargo tree | grep tokio

├── tokio v1.12.0
│   └── tokio-macros v1.4.1 (proc-macro)

Platform
uname -a

Linux DESKTOP-NT88DIE 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Description

Mutable pattern matching in tokio::select! appears to be disallowed, with streams yielding immutable references by default.

Code Sample

use tokio::sync::mpsc;
use futures::{FutureExt, StreamExt, future::join};

async fn test() {

  let (tx, rx) = mpsc::channel::<i32>(1);
  let stream = async move { rx }.into_stream();
  let mut pinned = Box::pin(stream);

  loop {
    tokio::select! {
      Some(mut rx) = pinned.next() => {
        let (_, n) = join(tx.send(5), rx.recv()).await;
        println!("n: {:?}", n);
        break;
      }
      else => {
        println!("nothing");
      }
    }
  }
}

Which fails for the following reason:

error[E0507]: cannot move out of a shared reference
  --> src/main.rs:28:5
   |
28 | /     tokio::select! {
29 | |       Some(mut rx) = pinned.next() => {
   | |            ------
   | |            |
   | |            data moved here
   | |            move occurs because `rx` has type `tokio::sync::mpsc::Receiver<i32>`, which does not implement the `Copy` trait
30 | |         let (_, n) = join(tx.send(5), rx.recv()).await;
31 | |         println!("n: {:?}", n);
...  |
36 | |       }
37 | |     }
   | |_____^

Workaround

use tokio::sync::mpsc;
use futures::{FutureExt, StreamExt, future::join};

async fn test() {

  let (tx, rx) = mpsc::channel::<i32>(1);
  let stream = async move { rx }.into_stream();
  let mut pinned = Box::pin(stream);

  loop {
    tokio::select! {
      Some(rx) = pinned.next() => {  // no mut
        let mut rx = rx; // an explicit mutable shadowing
        let (_, n) = join(tx.send(5), rx.recv()).await;
        println!("n: {:?}", n);
        break;
      }
      else => {
        println!("nothing");
      }
    }
  }
}

Solution

Unclear, to me at the very least. The problem definitely seems to be related to the way the tokio::select! expands, but I would have little to no clue whatsoever as to where it might make sense to start looking for the source of the issue.

@bwc-x bwc-x added A-tokio Area: The main tokio crate C-bug Category: This is a bug. labels Oct 19, 2021
@Darksonn Darksonn added the M-macros Module: macros in the main Tokio crate label Oct 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. M-macros Module: macros in the main Tokio crate
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants