-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Open
Labels
I-suggestion-causes-errorIssue: The suggestions provided by this Lint cause an ICE/error when appliedIssue: The suggestions provided by this Lint cause an ICE/error when applied
Description
Using the following flags
--force-warn clippy::match-bool
this code:
#![allow(unused)]
use std::{
cell::{Cell, RefCell},
future::Future,
marker::Unpin,
panic,
pin::Pin,
ptr,
rc::Rc,
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};
struct InjectedFailure;
struct Defer<T> {
ready: bool,
value: Option<T>,
}
impl<T: Unpin> Future for Defer<T> {
type Output = T;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
if self.ready {
Poll::Ready(self.value.take().unwrap())
} else {
self.ready = true;
Poll::Pending
}
}
}
/// Allocator tracks the creation and destruction of `Ptr`s.
/// The `failing_op`-th operation will panic.
struct Allocator {
data: RefCell<Vec<bool>>,
failing_op: usize,
cur_ops: Cell<usize>,
}
impl panic::UnwindSafe for Allocator {}
impl panic::RefUnwindSafe for Allocator {}
impl Drop for Allocator {
fn drop(&mut self) {
let data = self.data.borrow();
if data.iter().any(|d| *d) {
panic!("missing free: {:?}", data);
}
}
}
impl Allocator {
fn new(failing_op: usize) -> Self {
Allocator { failing_op, cur_ops: Cell::new(0), data: RefCell::new(vec![]) }
}
fn alloc(&self) -> impl Future<Output = Ptr<'_>> + '_ {
self.fallible_operation();
let mut data = self.data.borrow_mut();
let addr = data.len();
data.push(true);
Defer { ready: false, value: Some(Ptr(addr, self)) }
}
fn fallible_operation(&self) {
self.cur_ops.set(self.cur_ops.get() + 1);
if self.cur_ops.get() == self.failing_op {
panic::panic_any(InjectedFailure);
}
}
}
// Type that tracks whether it was dropped and can panic when it's created or
// destroyed.
struct Ptr<'a>(usize, &'a Allocator);
impl<'a> Drop for Ptr<'a> {
fn drop(&mut self) {
match self.1.data.borrow_mut()[self.0] {
false => panic!("double free at index {:?}", self.0),
ref mut d => *d = false,
}
self.1.fallible_operation();
}
}
caused the following diagnostics:
Checking _a v0.1.0 (/tmp/icemaker_global_tempdir.lAPrPb4j3wVl/icemaker_clippyfix_tempdir.dnKbE3nd6uBx/_a)
warning: `match` on a boolean expression
--> src/lib.rs:80:9
|
80 | / match self.1.data.borrow_mut()[self.0] {
81 | | false => panic!("double free at index {:?}", self.0),
82 | | ref mut d => *d = false,
83 | | }
| |_________^ help: consider using an `if`/`else` expression: `if !self.1.data.borrow_mut()[self.0] { panic!("double free at index {:?}", self.0) } else { *d = false }`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_bool
= note: requested on the command line with `--force-warn clippy::match-bool`
warning: `_a` (lib) generated 1 warning (run `cargo clippy --fix --lib -p _a` to apply 1 suggestion)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.40s
However after applying these diagnostics, the resulting code:
#![allow(unused)]
use std::{
cell::{Cell, RefCell},
future::Future,
marker::Unpin,
panic,
pin::Pin,
ptr,
rc::Rc,
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};
struct InjectedFailure;
struct Defer<T> {
ready: bool,
value: Option<T>,
}
impl<T: Unpin> Future for Defer<T> {
type Output = T;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
if self.ready {
Poll::Ready(self.value.take().unwrap())
} else {
self.ready = true;
Poll::Pending
}
}
}
/// Allocator tracks the creation and destruction of `Ptr`s.
/// The `failing_op`-th operation will panic.
struct Allocator {
data: RefCell<Vec<bool>>,
failing_op: usize,
cur_ops: Cell<usize>,
}
impl panic::UnwindSafe for Allocator {}
impl panic::RefUnwindSafe for Allocator {}
impl Drop for Allocator {
fn drop(&mut self) {
let data = self.data.borrow();
if data.iter().any(|d| *d) {
panic!("missing free: {:?}", data);
}
}
}
impl Allocator {
fn new(failing_op: usize) -> Self {
Allocator { failing_op, cur_ops: Cell::new(0), data: RefCell::new(vec![]) }
}
fn alloc(&self) -> impl Future<Output = Ptr<'_>> + '_ {
self.fallible_operation();
let mut data = self.data.borrow_mut();
let addr = data.len();
data.push(true);
Defer { ready: false, value: Some(Ptr(addr, self)) }
}
fn fallible_operation(&self) {
self.cur_ops.set(self.cur_ops.get() + 1);
if self.cur_ops.get() == self.failing_op {
panic::panic_any(InjectedFailure);
}
}
}
// Type that tracks whether it was dropped and can panic when it's created or
// destroyed.
struct Ptr<'a>(usize, &'a Allocator);
impl<'a> Drop for Ptr<'a> {
fn drop(&mut self) {
if !self.1.data.borrow_mut()[self.0] { panic!("double free at index {:?}", self.0) } else { *d = false }
self.1.fallible_operation();
}
}
no longer compiled:
Checking _a v0.1.0 (/tmp/icemaker_global_tempdir.lAPrPb4j3wVl/icemaker_clippyfix_tempdir.dnKbE3nd6uBx/_a)
error[E0425]: cannot find value `d` in this scope
--> src/lib.rs:80:102
|
80 | if !self.1.data.borrow_mut()[self.0] { panic!("double free at index {:?}", self.0) } else { *d = false }
| ^ not found in this scope
For more information about this error, try `rustc --explain E0425`.
error: could not compile `_a` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...
error: could not compile `_a` (lib test) due to 1 previous error
Version:
rustc 1.90.0-nightly (f32b23204 2025-07-26)
binary: rustc
commit-hash: f32b23204a0efe2fe8383ed4be1a30b56c1bbf94
commit-date: 2025-07-26
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.8
Metadata
Metadata
Assignees
Labels
I-suggestion-causes-errorIssue: The suggestions provided by this Lint cause an ICE/error when appliedIssue: The suggestions provided by this Lint cause an ICE/error when applied