implement unoptimized code logic for [infinite_loops]
This commit is contained in:
parent
406d953820
commit
2d9fc6dfc8
6 changed files with 571 additions and 8 deletions
259
tests/ui/infinite_loops.rs
Normal file
259
tests/ui/infinite_loops.rs
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
//@no-rustfix
|
||||
#![allow(clippy::never_loop)]
|
||||
#![warn(clippy::infinite_loops)]
|
||||
|
||||
fn do_something() {}
|
||||
|
||||
fn no_break() {
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
do_something();
|
||||
}
|
||||
}
|
||||
|
||||
fn no_break_never_ret() -> ! {
|
||||
loop {
|
||||
do_something();
|
||||
}
|
||||
}
|
||||
|
||||
fn no_break_never_ret_noise() {
|
||||
loop {
|
||||
fn inner_fn() -> ! {
|
||||
std::process::exit(0);
|
||||
}
|
||||
do_something();
|
||||
}
|
||||
}
|
||||
|
||||
fn has_direct_break_1() {
|
||||
loop {
|
||||
do_something();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fn has_direct_break_2() {
|
||||
'outer: loop {
|
||||
do_something();
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
|
||||
fn has_indirect_break_1(cond: bool) {
|
||||
'outer: loop {
|
||||
loop {
|
||||
if cond {
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn has_indirect_break_2(stop_num: i32) {
|
||||
'outer: loop {
|
||||
for x in 0..5 {
|
||||
if x == stop_num {
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn break_inner_but_not_outer_1(cond: bool) {
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
loop {
|
||||
if cond {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn break_inner_but_not_outer_2(cond: bool) {
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
'inner: loop {
|
||||
loop {
|
||||
if cond {
|
||||
break 'inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn break_outer_but_not_inner() {
|
||||
loop {
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
do_something();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fn can_break_both_inner_and_outer(cond: bool) {
|
||||
'outer: loop {
|
||||
loop {
|
||||
if cond {
|
||||
break 'outer;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn break_wrong_loop(cond: bool) {
|
||||
// 'inner has statement to break 'outer loop, but it was breaked early by a labeled child loop
|
||||
'outer: loop {
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
'inner: loop {
|
||||
loop {
|
||||
loop {
|
||||
break 'inner;
|
||||
}
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn has_direct_return(cond: bool) {
|
||||
loop {
|
||||
if cond {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ret_in_inner(cond: bool) {
|
||||
loop {
|
||||
loop {
|
||||
if cond {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Foo {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
fn match_like() {
|
||||
let opt: Option<u8> = Some(1);
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
match opt {
|
||||
Some(v) => {
|
||||
println!("{v}");
|
||||
},
|
||||
None => {
|
||||
do_something();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
match opt {
|
||||
Some(v) => {
|
||||
println!("{v}");
|
||||
},
|
||||
None => {
|
||||
do_something();
|
||||
break;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
let result: Result<u8, u16> = Ok(1);
|
||||
loop {
|
||||
let _val = match result {
|
||||
Ok(1) => 1 + 1,
|
||||
Ok(v) => v / 2,
|
||||
Err(_) => return,
|
||||
};
|
||||
}
|
||||
|
||||
loop {
|
||||
let Ok(_val) = result else { return };
|
||||
}
|
||||
|
||||
loop {
|
||||
let Ok(_val) = result.map(|v| 10) else { break };
|
||||
}
|
||||
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
let _x = matches!(result, Ok(v) if v != 0).then_some(0);
|
||||
}
|
||||
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
// This `return` does not return the function, so it doesn't count
|
||||
let _x = matches!(result, Ok(v) if v != 0).then(|| {
|
||||
if true {
|
||||
return;
|
||||
}
|
||||
do_something();
|
||||
});
|
||||
}
|
||||
|
||||
let mut val = 0;
|
||||
let mut fooc = Foo::C;
|
||||
|
||||
loop {
|
||||
val = match fooc {
|
||||
Foo::A => 0,
|
||||
Foo::B => {
|
||||
fooc = Foo::C;
|
||||
1
|
||||
},
|
||||
Foo::C => break,
|
||||
};
|
||||
}
|
||||
|
||||
loop {
|
||||
val = match fooc {
|
||||
Foo::A => 0,
|
||||
Foo::B => 1,
|
||||
Foo::C => {
|
||||
break;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! set_or_ret {
|
||||
($opt:expr, $a:expr) => {{
|
||||
match $opt {
|
||||
Some(val) => $a = val,
|
||||
None => return,
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn ret_in_macro(opt: Option<u8>) {
|
||||
let opt: Option<u8> = Some(1);
|
||||
let mut a: u8 = 0;
|
||||
loop {
|
||||
set_or_ret!(opt, a);
|
||||
}
|
||||
|
||||
let res: Result<bool, u8> = Ok(true);
|
||||
loop {
|
||||
match res {
|
||||
Ok(true) => set_or_ret!(opt, a),
|
||||
_ => do_something(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
147
tests/ui/infinite_loops.stderr
Normal file
147
tests/ui/infinite_loops.stderr
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
error: infinite loop detected
|
||||
--> $DIR/infinite_loops.rs:8:5
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | do_something();
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: `-D clippy::infinite-loops` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::infinite_loops)]`
|
||||
help: if this is intentional, consider specifing `!` as function return
|
||||
|
|
||||
LL | fn no_break() -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> $DIR/infinite_loops.rs:21:5
|
||||
|
|
||||
LL | / loop {
|
||||
LL | | fn inner_fn() -> ! {
|
||||
LL | | std::process::exit(0);
|
||||
LL | | }
|
||||
LL | | do_something();
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: if this is intentional, consider specifing `!` as function return
|
||||
|
|
||||
LL | fn no_break_never_ret_noise() -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> $DIR/infinite_loops.rs:64:5
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | loop {
|
||||
LL | | if cond {
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: if this is intentional, consider specifing `!` as function return
|
||||
|
|
||||
LL | fn break_inner_but_not_outer_1(cond: bool) -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> $DIR/infinite_loops.rs:75:5
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | 'inner: loop {
|
||||
LL | | loop {
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: if this is intentional, consider specifing `!` as function return
|
||||
|
|
||||
LL | fn break_inner_but_not_outer_2(cond: bool) -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> $DIR/infinite_loops.rs:89:9
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | do_something();
|
||||
LL | | }
|
||||
| |_________^
|
||||
|
|
||||
help: if this is intentional, consider specifing `!` as function return
|
||||
|
|
||||
LL | fn break_outer_but_not_inner() -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> $DIR/infinite_loops.rs:112:9
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | 'inner: loop {
|
||||
LL | | loop {
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_________^
|
||||
|
|
||||
help: if this is intentional, consider specifing `!` as function return
|
||||
|
|
||||
LL | fn break_wrong_loop(cond: bool) -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> $DIR/infinite_loops.rs:152:5
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | match opt {
|
||||
LL | | Some(v) => {
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: if this is intentional, consider specifing `!` as function return
|
||||
|
|
||||
LL | fn match_like() -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> $DIR/infinite_loops.rs:193:5
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | let _x = matches!(result, Ok(v) if v != 0).then_some(0);
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: if this is intentional, consider specifing `!` as function return
|
||||
|
|
||||
LL | fn match_like() -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> $DIR/infinite_loops.rs:198:5
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | // This `return` does not return the function, so it doesn't count
|
||||
LL | | let _x = matches!(result, Ok(v) if v != 0).then(|| {
|
||||
... |
|
||||
LL | | });
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: if this is intentional, consider specifing `!` as function return
|
||||
|
|
||||
LL | fn match_like() -> ! {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue