//@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 = 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 = 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) { let opt: Option = Some(1); let mut a: u8 = 0; loop { set_or_ret!(opt, a); } let res: Result = Ok(true); loop { match res { Ok(true) => set_or_ret!(opt, a), _ => do_something(), } } } fn main() {}