Skip to content

Commit ae284a6

Browse files
committed
Support f16 and f128 in zero_divided_by_zero lint
1 parent a4b8e9a commit ae284a6

File tree

5 files changed

+46
-23
lines changed

5 files changed

+46
-23
lines changed

clippy_lints/src/zero_div_zero.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant};
22
use clippy_utils::diagnostics::span_lint_and_help;
33
use rustc_hir::{BinOpKind, Expr, ExprKind};
44
use rustc_lint::{LateContext, LateLintPass};
5+
use rustc_middle::ty;
56
use rustc_session::declare_lint_pass;
67

78
declare_clippy_lint! {
89
/// ### What it does
910
/// Checks for `0.0 / 0.0`.
1011
///
1112
/// ### Why is this bad?
12-
/// It's less readable than `f32::NAN` or `f64::NAN`.
13+
/// It's less readable than using the proper associated `NAN` constant.
1314
///
1415
/// ### Example
1516
/// ```no_run
@@ -23,7 +24,7 @@ declare_clippy_lint! {
2324
#[clippy::version = "pre 1.29.0"]
2425
pub ZERO_DIVIDED_BY_ZERO,
2526
complexity,
26-
"usage of `0.0 / 0.0` to obtain NaN instead of `f32::NAN` or `f64::NAN`"
27+
"usage of `0.0 / 0.0` to obtain NaN instead of using a predefined constant"
2728
}
2829

2930
declare_lint_pass!(ZeroDiv => [ZERO_DIVIDED_BY_ZERO]);
@@ -40,23 +41,20 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv {
4041
&& let ctxt = expr.span.ctxt()
4142
&& let Some(lhs_value) = ecx.eval_local(left, ctxt)
4243
&& let Some(rhs_value) = ecx.eval_local(right, ctxt)
43-
// FIXME(f16_f128): add these types when eq is available on all platforms
44-
&& (Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value)
45-
&& (Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value)
44+
&& matches!(lhs_value, Constant::F16(0.0) | Constant::F32(0.0) | Constant::F64(0.0) | Constant::F128(0.0))
45+
&& matches!(rhs_value, Constant::F16(0.0) | Constant::F32(0.0) | Constant::F64(0.0) | Constant::F128(0.0))
46+
&& let ty::Float(float_ty) = cx.typeck_results().expr_ty(expr).kind()
4647
{
47-
// since we're about to suggest a use of f32::NAN or f64::NAN,
48-
// match the precision of the literals that are given.
49-
let float_type = match (lhs_value, rhs_value) {
50-
(Constant::F64(_), _) | (_, Constant::F64(_)) => "f64",
51-
_ => "f32",
52-
};
5348
span_lint_and_help(
5449
cx,
5550
ZERO_DIVIDED_BY_ZERO,
5651
expr.span,
5752
"constant division of `0.0` with `0.0` will always result in NaN",
5853
None,
59-
format!("consider using `{float_type}::NAN` if you would like a constant representing NaN",),
54+
format!(
55+
"consider using `{}::NAN` if you would like a constant representing NaN",
56+
float_ty.name_str()
57+
),
6058
);
6159
}
6260
}

tests/ui/cast_nan_to_int.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![allow(clippy::eq_op)]
55

66
fn main() {
7+
#[expect(clippy::zero_divided_by_zero)]
78
let _ = (0.0_f32 / -0.0) as usize;
89
//~^ cast_nan_to_int
910

tests/ui/cast_nan_to_int.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: casting a known NaN to usize
2-
--> tests/ui/cast_nan_to_int.rs:7:13
2+
--> tests/ui/cast_nan_to_int.rs:8:13
33
|
44
LL | let _ = (0.0_f32 / -0.0) as usize;
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,39 +9,39 @@ LL | let _ = (0.0_f32 / -0.0) as usize;
99
= help: to override `-D warnings` add `#[allow(clippy::cast_nan_to_int)]`
1010

1111
error: casting a known NaN to usize
12-
--> tests/ui/cast_nan_to_int.rs:10:13
12+
--> tests/ui/cast_nan_to_int.rs:11:13
1313
|
1414
LL | let _ = (f64::INFINITY * -0.0) as usize;
1515
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1616
|
1717
= note: this always evaluates to 0
1818

1919
error: casting a known NaN to usize
20-
--> tests/ui/cast_nan_to_int.rs:13:13
20+
--> tests/ui/cast_nan_to_int.rs:14:13
2121
|
2222
LL | let _ = (0.0 * f32::INFINITY) as usize;
2323
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424
|
2525
= note: this always evaluates to 0
2626

2727
error: casting a known NaN to usize
28-
--> tests/ui/cast_nan_to_int.rs:16:13
28+
--> tests/ui/cast_nan_to_int.rs:17:13
2929
|
3030
LL | let _ = (f64::INFINITY + f64::NEG_INFINITY) as usize;
3131
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3232
|
3333
= note: this always evaluates to 0
3434

3535
error: casting a known NaN to usize
36-
--> tests/ui/cast_nan_to_int.rs:19:13
36+
--> tests/ui/cast_nan_to_int.rs:20:13
3737
|
3838
LL | let _ = (f32::INFINITY - f32::INFINITY) as usize;
3939
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4040
|
4141
= note: this always evaluates to 0
4242

4343
error: casting a known NaN to usize
44-
--> tests/ui/cast_nan_to_int.rs:22:13
44+
--> tests/ui/cast_nan_to_int.rs:23:13
4545
|
4646
LL | let _ = (f32::INFINITY / f32::NEG_INFINITY) as usize;
4747
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/ui/zero_div_zero.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![feature(f128)]
2+
#![feature(f16)]
13
#[allow(unused_variables, clippy::eq_op)]
24
#[warn(clippy::zero_divided_by_zero)]
35
fn main() {
@@ -13,6 +15,12 @@ fn main() {
1315
let one_more_f64_nan = 0.0f64 / 0.0f64;
1416
//~^ zero_divided_by_zero
1517

18+
let f16_nan = 0.0 / 0.0f16;
19+
//~^ zero_divided_by_zero
20+
21+
let f128_nan = 0.0 / 0.0f128;
22+
//~^ zero_divided_by_zero
23+
1624
let zero = 0.0;
1725
let other_zero = 0.0;
1826
let other_nan = zero / other_zero; // fine - this lint doesn't propagate constants.

tests/ui/zero_div_zero.stderr

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: constant division of `0.0` with `0.0` will always result in NaN
2-
--> tests/ui/zero_div_zero.rs:4:15
2+
--> tests/ui/zero_div_zero.rs:6:15
33
|
44
LL | let nan = 0.0 / 0.0;
55
| ^^^^^^^^^
@@ -9,28 +9,44 @@ LL | let nan = 0.0 / 0.0;
99
= help: to override `-D warnings` add `#[allow(clippy::zero_divided_by_zero)]`
1010

1111
error: constant division of `0.0` with `0.0` will always result in NaN
12-
--> tests/ui/zero_div_zero.rs:7:19
12+
--> tests/ui/zero_div_zero.rs:9:19
1313
|
1414
LL | let f64_nan = 0.0 / 0.0f64;
1515
| ^^^^^^^^^^^^
1616
|
1717
= help: consider using `f64::NAN` if you would like a constant representing NaN
1818

1919
error: constant division of `0.0` with `0.0` will always result in NaN
20-
--> tests/ui/zero_div_zero.rs:10:25
20+
--> tests/ui/zero_div_zero.rs:12:25
2121
|
2222
LL | let other_f64_nan = 0.0f64 / 0.0;
2323
| ^^^^^^^^^^^^
2424
|
2525
= help: consider using `f64::NAN` if you would like a constant representing NaN
2626

2727
error: constant division of `0.0` with `0.0` will always result in NaN
28-
--> tests/ui/zero_div_zero.rs:13:28
28+
--> tests/ui/zero_div_zero.rs:15:28
2929
|
3030
LL | let one_more_f64_nan = 0.0f64 / 0.0f64;
3131
| ^^^^^^^^^^^^^^^
3232
|
3333
= help: consider using `f64::NAN` if you would like a constant representing NaN
3434

35-
error: aborting due to 4 previous errors
35+
error: constant division of `0.0` with `0.0` will always result in NaN
36+
--> tests/ui/zero_div_zero.rs:18:19
37+
|
38+
LL | let f16_nan = 0.0 / 0.0f16;
39+
| ^^^^^^^^^^^^
40+
|
41+
= help: consider using `f16::NAN` if you would like a constant representing NaN
42+
43+
error: constant division of `0.0` with `0.0` will always result in NaN
44+
--> tests/ui/zero_div_zero.rs:21:20
45+
|
46+
LL | let f128_nan = 0.0 / 0.0f128;
47+
| ^^^^^^^^^^^^^
48+
|
49+
= help: consider using `f128::NAN` if you would like a constant representing NaN
50+
51+
error: aborting due to 6 previous errors
3652

0 commit comments

Comments
 (0)