@@ -4,6 +4,7 @@ mod explicit_counter_loop;
44mod explicit_into_iter_loop;
55mod explicit_iter_loop;
66mod for_kv_map;
7+ mod for_unbounded_range;
78mod infinite_loop;
89mod iter_next_loop;
910mod manual_find;
@@ -785,6 +786,35 @@ declare_clippy_lint! {
785786 "using the character position yielded by `.chars().enumerate()` in a context where a byte index is expected"
786787}
787788
789+ declare_clippy_lint ! {
790+ /// ### What it does
791+ /// Checks for unbounded for loops over char or integers.
792+ ///
793+ /// ### Why is this bad?
794+ /// Using a unbounded range over char and integers will unexpectedly not handle overflows so it will lead to panics
795+ /// or infinite loops.
796+ ///
797+ /// Instead there should be a max value set, usually the `MAX` constant for a given type such as `'\0'..char::MAX`
798+ /// or `250..u8::MAX`.
799+ ///
800+ /// ### Example
801+ /// ```no_run
802+ /// for i in 250u8.. {
803+ /// println!("{i}");
804+ /// }
805+ /// ```
806+ /// Use instead:
807+ /// ```no_run
808+ /// for i in 250u8..=u8::MAX {
809+ /// println!("{i}");
810+ /// }
811+ /// ```
812+ #[ clippy:: version = "1.94.0" ]
813+ pub FOR_UNBOUNDED_RANGE ,
814+ nursery,
815+ "using a for loop over unbounded range (`0..`)"
816+ }
817+
788818pub struct Loops {
789819 msrv : Msrv ,
790820 enforce_iter_loop_reborrow : bool ,
@@ -823,6 +853,7 @@ impl_lint_pass!(Loops => [
823853 INFINITE_LOOP ,
824854 MANUAL_SLICE_FILL ,
825855 CHAR_INDICES_AS_BYTE_INDICES ,
856+ FOR_UNBOUNDED_RANGE ,
826857] ) ;
827858
828859impl < ' tcx > LateLintPass < ' tcx > for Loops {
@@ -951,6 +982,7 @@ impl Loops {
951982 manual_find:: check ( cx, pat, arg, body, span, expr) ;
952983 unused_enumerate_index:: check ( cx, arg, pat, None , body) ;
953984 char_indices_as_byte_indices:: check ( cx, pat, arg, body) ;
985+ for_unbounded_range:: check ( cx, arg, span) ;
954986 }
955987
956988 fn check_for_loop_arg ( & self , cx : & LateContext < ' _ > , _: & Pat < ' _ > , arg : & Expr < ' _ > ) {
0 commit comments