New lint suggestion: You're using a blocking operation when you could be using an async one

Open
#10,794 3 comments 3 reactions 1 assignee View on GitHub

@J-ZhengLi is already working on this.

Since Sep 25, 2023.

Assessment

This issue has not been assessed yet.

Description

A-lint
What it does

A lint which checks for blocking functions inside an async block.

One I know of (and the cause of a bug I ran into today) is std::thread::sleep, but there are others. (file operations, networking, ...). If such a function has an async counterpart, then the user could be warned of this fact.

Lint Name

unwise-block

Category

suspicious

Advantage
  • warn of badly behaving async programs
Drawbacks
  • might be too noisy
Example
use std::thread::sleep;
use std::time::Duration;
use tokio::signal::unix::signal;
use tokio::signal::unix::SignalKind;
use tokio::sync::mpsc;

async fn rx(rx: &mut mpsc::Receiver<()>) {
    loop {
        sleep(Duration::new(1, 0));
        if rx.try_recv().is_ok() {
            println!("got one splivet");
        }
    }
}

async fn tx(tx: mpsc::Sender<()>) {
    let mut stream = signal(SignalKind::user_defined1()).unwrap();

    loop {
        stream.recv().await;
        println!("sending one splivet");
        tx.send(()).await.unwrap();
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let (stx, mut srx) = mpsc::channel::<()>(5);

    tokio::join!(tx(stx), rx(&mut srx));
}

Could be written as:

use std::thread::sleep;
use std::time::Duration;
use tokio::signal::unix::signal;
use tokio::signal::unix::SignalKind;
use tokio::sync::mpsc;

async fn rx(rx: &mut mpsc::Receiver<()>) {
    loop {
        tokio::time::sleep(Duration::new(1, 0)).await;
        if rx.try_recv().is_ok() {
            println!("got one splivet");
        }
    }
}

async fn tx(tx: mpsc::Sender<()>) {
    let mut stream = signal(SignalKind::user_defined1()).unwrap();

    loop {
        stream.recv().await;
        println!("sending one splivet");
        tx.send(()).await.unwrap();
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let (stx, mut srx) = mpsc::channel::<()>(5);

    tokio::join!(tx(stx), rx(&mut srx));
}

Note the different way to sleep in the rx function.

Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rust-lang/rust-clippy

All issues in rust-lang/rust-clippy

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.