a4bba694c0
At some stage, we started adding test cases inside the function which tests refutable patterns. This commits splits those test cases out into separate functions.
241 lines
5.0 KiB
Rust
241 lines
5.0 KiB
Rust
#![warn(clippy::while_let_loop, clippy::empty_loop, clippy::while_let_on_iterator)]
|
|
#![allow(dead_code, clippy::never_loop, unused, clippy::cognitive_complexity)]
|
|
|
|
fn main() {
|
|
let y = Some(true);
|
|
loop {
|
|
if let Some(_x) = y {
|
|
let _v = 1;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
loop {
|
|
// no error, break is not in else clause
|
|
if let Some(_x) = y {
|
|
let _v = 1;
|
|
}
|
|
break;
|
|
}
|
|
loop {
|
|
match y {
|
|
Some(_x) => true,
|
|
None => break,
|
|
};
|
|
}
|
|
loop {
|
|
let x = match y {
|
|
Some(x) => x,
|
|
None => break,
|
|
};
|
|
let _x = x;
|
|
let _str = "foo";
|
|
}
|
|
loop {
|
|
let x = match y {
|
|
Some(x) => x,
|
|
None => break,
|
|
};
|
|
{
|
|
let _a = "bar";
|
|
};
|
|
{
|
|
let _b = "foobar";
|
|
}
|
|
}
|
|
loop {
|
|
// no error, else branch does something other than break
|
|
match y {
|
|
Some(_x) => true,
|
|
_ => {
|
|
let _z = 1;
|
|
break;
|
|
},
|
|
};
|
|
}
|
|
while let Some(x) = y {
|
|
// no error, obviously
|
|
println!("{}", x);
|
|
}
|
|
|
|
// #675, this used to have a wrong suggestion
|
|
loop {
|
|
let (e, l) = match "".split_whitespace().next() {
|
|
Some(word) => (word.is_empty(), word.len()),
|
|
None => break,
|
|
};
|
|
|
|
let _ = (e, l);
|
|
}
|
|
|
|
let mut iter = 1..20;
|
|
while let Option::Some(x) = iter.next() {
|
|
println!("{}", x);
|
|
}
|
|
|
|
let mut iter = 1..20;
|
|
while let Some(x) = iter.next() {
|
|
println!("{}", x);
|
|
}
|
|
|
|
let mut iter = 1..20;
|
|
while let Some(_) = iter.next() {}
|
|
|
|
let mut iter = 1..20;
|
|
while let None = iter.next() {} // this is fine (if nonsensical)
|
|
|
|
let mut iter = 1..20;
|
|
if let Some(x) = iter.next() {
|
|
// also fine
|
|
println!("{}", x)
|
|
}
|
|
|
|
// the following shouldn't warn because it can't be written with a for loop
|
|
let mut iter = 1u32..20;
|
|
while let Some(x) = iter.next() {
|
|
println!("next: {:?}", iter.next())
|
|
}
|
|
|
|
// neither can this
|
|
let mut iter = 1u32..20;
|
|
while let Some(x) = iter.next() {
|
|
println!("next: {:?}", iter.next());
|
|
}
|
|
|
|
// or this
|
|
let mut iter = 1u32..20;
|
|
while let Some(x) = iter.next() {
|
|
break;
|
|
}
|
|
println!("Remaining iter {:?}", iter);
|
|
|
|
// or this
|
|
let mut iter = 1u32..20;
|
|
while let Some(x) = iter.next() {
|
|
iter = 1..20;
|
|
}
|
|
}
|
|
|
|
// regression test (#360)
|
|
// this should not panic
|
|
// it's ok if further iterations of the lint
|
|
// cause this function to trigger it
|
|
fn no_panic<T>(slice: &[T]) {
|
|
let mut iter = slice.iter();
|
|
loop {
|
|
let _ = match iter.next() {
|
|
Some(ele) => ele,
|
|
None => break,
|
|
};
|
|
loop {}
|
|
}
|
|
}
|
|
|
|
fn issue1017() {
|
|
let r: Result<u32, u32> = Ok(42);
|
|
let mut len = 1337;
|
|
|
|
loop {
|
|
match r {
|
|
Err(_) => len = 0,
|
|
Ok(length) => {
|
|
len = length;
|
|
break;
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
// Issue #1188
|
|
fn refutable() {
|
|
let a = [42, 1337];
|
|
let mut b = a.iter();
|
|
|
|
// consume all the 42s
|
|
while let Some(&42) = b.next() {}
|
|
|
|
let a = [(1, 2, 3)];
|
|
let mut b = a.iter();
|
|
|
|
while let Some(&(1, 2, 3)) = b.next() {}
|
|
|
|
let a = [Some(42)];
|
|
let mut b = a.iter();
|
|
|
|
while let Some(&None) = b.next() {}
|
|
|
|
/* This gives “refutable pattern in `for` loop binding: `&_` not covered”
|
|
for &42 in b {}
|
|
for &(1, 2, 3) in b {}
|
|
for &Option::None in b.next() {}
|
|
// */
|
|
}
|
|
|
|
fn nested_loops() {
|
|
let a = [42, 1337];
|
|
let mut y = a.iter();
|
|
loop {
|
|
// x is reused, so don't lint here
|
|
while let Some(v) = y.next() {}
|
|
}
|
|
|
|
let mut y = a.iter();
|
|
for _ in 0..2 {
|
|
while let Some(v) = y.next() {
|
|
// y is reused, don't lint
|
|
}
|
|
}
|
|
|
|
loop {
|
|
let mut y = a.iter();
|
|
while let Some(v) = y.next() {
|
|
// use a for loop here
|
|
}
|
|
}
|
|
}
|
|
|
|
fn issue1948() {
|
|
// should not trigger clippy::while_let_loop lint because break passes an expression
|
|
let a = Some(10);
|
|
let b = loop {
|
|
if let Some(c) = a {
|
|
break Some(c);
|
|
} else {
|
|
break None;
|
|
}
|
|
};
|
|
}
|
|
|
|
fn issue1121() {
|
|
use std::collections::HashSet;
|
|
let mut values = HashSet::new();
|
|
values.insert(1);
|
|
|
|
while let Some(&value) = values.iter().next() {
|
|
values.remove(&value);
|
|
}
|
|
}
|
|
|
|
fn issue2965() {
|
|
// This should not cause an ICE and suggest:
|
|
//
|
|
// for _ in values.iter() {}
|
|
//
|
|
use std::collections::HashSet;
|
|
let mut values = HashSet::new();
|
|
values.insert(1);
|
|
|
|
while let Some(..) = values.iter().next() {
|
|
values.remove(&1);
|
|
}
|
|
}
|
|
|
|
fn issue3670() {
|
|
let array = [Some(0), None, Some(1)];
|
|
let mut iter = array.iter();
|
|
|
|
while let Some(elem) = iter.next() {
|
|
let _ = elem.or_else(|| *iter.next()?);
|
|
}
|
|
}
|