@@ -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,37 @@ 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+ ///
792+ /// Check for unbounded for loops over char or integers.
793+ ///
794+ /// ### Why is this bad?
795+ ///
796+ /// Using a unbounded range over char and integers will unexpectedly not handle overflows so it will lead to panics
797+ /// or infinite loops.
798+ ///
799+ /// Instead there should be a max value set, usually the `MAX` constant for a given type such as `'\0'..char::MAX`
800+ /// or `250..u8::MAX`.
801+ ///
802+ /// ### Example
803+ /// ```no_run
804+ /// for i in 250u8.. {
805+ /// println!("{i}");
806+ /// }
807+ /// ```
808+ /// Use instead:
809+ /// ```no_run
810+ /// for i in 250u8..=u8::MAX {
811+ /// println!("{i}");
812+ /// }
813+ /// ```
814+ #[ clippy:: version = "1.94.0" ]
815+ pub FOR_UNBOUNDED_RANGE ,
816+ nursery,
817+ "for loop on unbounded range (`0..`)"
818+ }
819+
788820pub struct Loops {
789821 msrv : Msrv ,
790822 enforce_iter_loop_reborrow : bool ,
@@ -823,6 +855,7 @@ impl_lint_pass!(Loops => [
823855 INFINITE_LOOP ,
824856 MANUAL_SLICE_FILL ,
825857 CHAR_INDICES_AS_BYTE_INDICES ,
858+ FOR_UNBOUNDED_RANGE ,
826859] ) ;
827860
828861impl < ' tcx > LateLintPass < ' tcx > for Loops {
@@ -951,6 +984,7 @@ impl Loops {
951984 manual_find:: check ( cx, pat, arg, body, span, expr) ;
952985 unused_enumerate_index:: check ( cx, arg, pat, None , body) ;
953986 char_indices_as_byte_indices:: check ( cx, pat, arg, body) ;
987+ for_unbounded_range:: check ( cx, arg, span)
954988 }
955989
956990 fn check_for_loop_arg ( & self , cx : & LateContext < ' _ > , _: & Pat < ' _ > , arg : & Expr < ' _ > ) {
0 commit comments