Skip to content

never_loop false-positive when using join_handles #16054

@SciMind2460

Description

@SciMind2460

Summary

When using a JoinHandle, Clippy seems to think that loops will never pass.

Lint Name

never_loop

Reproducer

I tried this code:

use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

#[derive(Clone)]
struct Philosopher {
    pub fork1: Arc<Mutex<usize>>,
    pub fork2: Arc<Mutex<usize>>,
    pub is_eating: bool,
    pub id: usize,
}

impl Philosopher {
    pub fn eat(&mut self) {
        {
            if let Ok(_) = self.fork1.lock() && let Ok(_) = self.fork2.lock() {
                self.is_eating = true;
            }
            println!("Philosopher {} is eating!", self.id);
            thread::sleep(Duration::from_secs(1));
        }
        self.is_eating = false;
    }
}

fn algo() {
    let forks: [Arc<Mutex<usize>>; 5] = core::array::from_fn(|x| Arc::new(Mutex::new(x)));
    let philosophers: [Arc<Mutex<Philosopher>>; 5] = core::array::from_fn(|x| Arc::new(Mutex::new(Philosopher {fork1: Arc::clone(&forks[x % 5]), fork2: Arc::clone(&forks[(x + 1) % 5]), is_eating: false, id: x})));
    let mut join_handles = Vec::new();
    for i in 0..5 {
        let value = philosophers.clone();
        let join_handle = thread::spawn(move || {
            let binding = Arc::clone(&value[i]);
            let mut philosopher = binding.lock().unwrap();
            loop {
                philosopher.eat();
            }
        });
        join_handles.push(join_handle);
    }
    for join_handle in join_handles {
        join_handle.join().unwrap();
    }
}

fn main() {
    algo();
}

I saw this happen:

error: this loop never actually loops                                                                                                                                           
  --> src\main.rs:41:5
   |
41 | /     for join_handle in join_handles {
42 | |         join_handle.join().unwrap();
43 | |     }
   | |_____^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.91.0/index.html#never_loop
   = note: `#[deny(clippy::never_loop)]` on by default
help: if you need the first element of the iterator, try writing
   |
41 -     for join_handle in join_handles {
41 +     if let Some(join_handle) = join_handles.into_iter().next() {
   |

I expected to see this happen:
The code passes without error

Version

rustc 1.91.0 (f8297e351 2025-10-28)
binary: rustc
commit-hash: f8297e351a40c1439a467bbbb6879088047f50b3
commit-date: 2025-10-28
host: x86_64-pc-windows-msvc
release: 1.91.0
LLVM version: 21.1.2

Additional Labels

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-false-positiveIssue: The lint was triggered on code it shouldn't have

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions