11use clippy_utils:: {
2- consts:: constant, diagnostics:: span_lint_and_then, is_from_proc_macro, path_to_local, source:: snippet_opt,
2+ consts:: { constant, Constant } ,
3+ diagnostics:: span_lint_and_then,
4+ is_from_proc_macro, path_to_local,
5+ source:: snippet_opt,
36} ;
47use rustc_errors:: Applicability ;
58use rustc_hir:: { BinOpKind , Expr , ExprKind } ;
@@ -9,10 +12,11 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
912
1013declare_clippy_lint ! {
1114 /// ### What it does
12- /// Checks for `x == <float>::INFINITY || x == <float>::NEG_INFINITY`.
15+ /// Checks for manual `is_infinite` reimplementations
16+ /// (i.e., `x == <float>::INFINITY || x == <float>::NEG_INFINITY`).
1317 ///
1418 /// ### Why is this bad?
15- /// This should use the dedicated method instead, `is_infinite`.
19+ /// This should use the aforementioned dedicated method instead, `is_infinite`.
1620 ///
1721 /// ### Example
1822 /// ```rust
@@ -31,20 +35,23 @@ declare_clippy_lint! {
3135}
3236declare_clippy_lint ! {
3337 /// ### What it does
34- /// Checks for `x != <float>::INFINITY && x != <float>::NEG_INFINITY`.
38+ /// Checks for manual `is_finite` reimplementations
39+ /// (i.e., `x != <float>::INFINITY && x != <float>::NEG_INFINITY`).
3540 ///
3641 /// ### Why is this bad?
37- /// This should use the dedicated method instead, `is_finite`.
42+ /// This should use the aforementioned dedicated method instead, `is_finite`.
3843 ///
3944 /// ### Example
4045 /// ```rust
4146 /// # let x = 1.0f32;
4247 /// if x != f32::INFINITY && x != f32::NEG_INFINITY {}
48+ /// if x.abs() < f32::INFINITY {}
4349 /// ```
4450 /// Use instead:
4551 /// ```rust
4652 /// # let x = 1.0f32;
4753 /// if x.is_finite() {}
54+ /// if x.is_finite() {}
4855 /// ```
4956 #[ clippy:: version = "1.72.0" ]
5057 pub MANUAL_IS_FINITE ,
@@ -84,18 +91,20 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
8491 && let ExprKind :: Binary ( rhs_kind, rhs_lhs, rhs_rhs) = rhs. kind
8592 // Checking all possible scenarios using a function would be a hopeless task, as we have
8693 // 16 possible alignments of constants/operands. For now, let's use `partition`.
87- && let ( operands, consts ) = [ lhs_lhs, lhs_rhs, rhs_lhs, rhs_rhs]
94+ && let ( operands, constants ) = [ lhs_lhs, lhs_rhs, rhs_lhs, rhs_rhs]
8895 . into_iter ( )
8996 . partition :: < Vec < & Expr < ' _ > > , _ > ( |i| path_to_local ( i) . is_some ( ) )
9097 && let [ first, second] = & * operands
91- && let Some ( [ const_1, const_2] ) = consts
98+ && let Some ( [ const_1, const_2] ) = constants
9299 . into_iter ( )
93- . map ( |i| constant ( cx, cx. typeck_results ( ) , i) . and_then ( |c| c . to_bits ( ) ) )
100+ . map ( |i| constant ( cx, cx. typeck_results ( ) , i) )
94101 . collect :: < Option < Vec < _ > > > ( )
95102 . as_deref ( )
96103 && path_to_local ( first) . is_some_and ( |f| path_to_local ( second) . is_some_and ( |s| f == s) )
97- && ( is_infinity ( * const_1) && is_neg_infinity ( * const_2)
98- || is_neg_infinity ( * const_1) && is_infinity ( * const_2) )
104+ // The actual infinity check, we also allow `NEG_INFINITY` before` INFINITY` just in
105+ // case somebody does that for some reason
106+ && ( is_infinity ( const_1) && is_neg_infinity ( const_2)
107+ || is_neg_infinity ( const_1) && is_infinity ( const_2) )
99108 && let Some ( local_snippet) = snippet_opt ( cx, first. span )
100109 && !is_from_proc_macro ( cx, expr)
101110 {
@@ -141,18 +150,26 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
141150 format ! ( "!{local_snippet}.is_infinite()" ) ,
142151 Applicability :: MaybeIncorrect ,
143152 ) ;
144- }
153+ } ,
145154 }
146- }
155+ } ,
147156 ) ;
148157 }
149158 }
150159}
151160
152- fn is_infinity ( bits : u128 ) -> bool {
153- bits == 0x7f80_0000 || bits == 0x7ff0_0000_0000_0000
161+ fn is_infinity ( constant : & Constant < ' _ > ) -> bool {
162+ match constant {
163+ Constant :: F32 ( float) => * float == f32:: INFINITY ,
164+ Constant :: F64 ( float) => * float == f64:: INFINITY ,
165+ _ => false ,
166+ }
154167}
155168
156- fn is_neg_infinity ( bits : u128 ) -> bool {
157- bits == 0xff80_0000 || bits == 0xfff0_0000_0000_0000
169+ fn is_neg_infinity ( constant : & Constant < ' _ > ) -> bool {
170+ match constant {
171+ Constant :: F32 ( float) => * float == f32:: NEG_INFINITY ,
172+ Constant :: F64 ( float) => * float == f64:: NEG_INFINITY ,
173+ _ => false ,
174+ }
158175}
0 commit comments