rust-lang / rust-lang/rust-clippy
`never_loop` false-positive when using join_handles
Open
Nobody has claimed this yet.
C-bug
I-false-positive
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the report from src/main.rs and trace the never_loop lint's handling of the join_handles loop, comparing it with the inner loop. Done means the provided example no longer emits this false positive and the behavior is covered by a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100