mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 15:11:30 +00:00
add cast-nan-to-int
lint
This commit is contained in:
parent
854015c33c
commit
e4c80f2bba
10 changed files with 143 additions and 0 deletions
|
@ -3773,6 +3773,7 @@ Released 2018-09-13
|
|||
[`cast_enum_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_constructor
|
||||
[`cast_enum_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_truncation
|
||||
[`cast_lossless`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_lossless
|
||||
[`cast_nan_to_int`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_nan_to_int
|
||||
[`cast_possible_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_truncation
|
||||
[`cast_possible_wrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_wrap
|
||||
[`cast_precision_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
|
||||
|
|
28
clippy_lints/src/casts/cast_nan_to_int.rs
Normal file
28
clippy_lints/src/casts/cast_nan_to_int.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use super::CAST_NAN_TO_INT;
|
||||
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_note;
|
||||
use rustc_hir::Expr;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::Ty;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, from_ty: Ty<'_>, to_ty: Ty<'_>) {
|
||||
if from_ty.is_floating_point() && to_ty.is_integral() && is_known_nan(cx, cast_expr) {
|
||||
span_lint_and_note(
|
||||
cx,
|
||||
CAST_NAN_TO_INT,
|
||||
expr.span,
|
||||
&format!("casting a known NaN to {to_ty}"),
|
||||
None,
|
||||
"this always evaluates to 0",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_known_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
||||
match constant(cx, cx.typeck_results(), e) {
|
||||
Some((Constant::F64(n), _)) => n.is_nan(),
|
||||
Some((Constant::F32(n), _)) => n.is_nan(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ mod borrow_as_ptr;
|
|||
mod cast_abs_to_unsigned;
|
||||
mod cast_enum_constructor;
|
||||
mod cast_lossless;
|
||||
mod cast_nan_to_int;
|
||||
mod cast_possible_truncation;
|
||||
mod cast_possible_wrap;
|
||||
mod cast_precision_loss;
|
||||
|
@ -570,6 +571,7 @@ declare_clippy_lint! {
|
|||
pedantic,
|
||||
"borrowing just to cast to a raw pointer"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for a raw slice being cast to a slice pointer
|
||||
|
@ -623,6 +625,28 @@ declare_clippy_lint! {
|
|||
"casting the result of the `&self`-taking `as_ptr` to a mutabe pointer"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for a known NaN float being cast to an integer
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// NaNs are cast into zero, so one could simply use this and make the
|
||||
/// code more readable. The lint could also hint at a programmer error.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust,ignore
|
||||
/// let _: (0.0_f32 / 0.0) as u64;
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust,ignore
|
||||
/// let _: = 0_u64;
|
||||
/// ```
|
||||
#[clippy::version = "1.64.0"]
|
||||
pub CAST_NAN_TO_INT,
|
||||
suspicious,
|
||||
"casting a known floating-point NaN into an integer"
|
||||
}
|
||||
|
||||
pub struct Casts {
|
||||
msrv: Option<RustcVersion>,
|
||||
}
|
||||
|
@ -656,6 +680,7 @@ impl_lint_pass!(Casts => [
|
|||
BORROW_AS_PTR,
|
||||
CAST_SLICE_FROM_RAW_PARTS,
|
||||
AS_PTR_CAST_MUT,
|
||||
CAST_NAN_TO_INT,
|
||||
]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Casts {
|
||||
|
@ -693,6 +718,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
|
|||
cast_precision_loss::check(cx, expr, cast_from, cast_to);
|
||||
cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to);
|
||||
cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv);
|
||||
cast_nan_to_int::check(cx, expr, cast_expr, cast_from, cast_to);
|
||||
}
|
||||
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv);
|
||||
cast_enum_constructor::check(cx, expr, cast_expr, cast_from);
|
||||
|
|
|
@ -25,6 +25,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
|
|||
LintId::of(casts::CAST_ABS_TO_UNSIGNED),
|
||||
LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
|
||||
LintId::of(casts::CAST_ENUM_TRUNCATION),
|
||||
LintId::of(casts::CAST_NAN_TO_INT),
|
||||
LintId::of(casts::CAST_REF_TO_MUT),
|
||||
LintId::of(casts::CAST_SLICE_DIFFERENT_SIZES),
|
||||
LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
|
||||
|
|
|
@ -73,6 +73,7 @@ store.register_lints(&[
|
|||
casts::CAST_ENUM_CONSTRUCTOR,
|
||||
casts::CAST_ENUM_TRUNCATION,
|
||||
casts::CAST_LOSSLESS,
|
||||
casts::CAST_NAN_TO_INT,
|
||||
casts::CAST_POSSIBLE_TRUNCATION,
|
||||
casts::CAST_POSSIBLE_WRAP,
|
||||
casts::CAST_PRECISION_LOSS,
|
||||
|
|
|
@ -11,6 +11,7 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec!
|
|||
LintId::of(casts::CAST_ABS_TO_UNSIGNED),
|
||||
LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
|
||||
LintId::of(casts::CAST_ENUM_TRUNCATION),
|
||||
LintId::of(casts::CAST_NAN_TO_INT),
|
||||
LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
|
||||
LintId::of(crate_in_macro_def::CRATE_IN_MACRO_DEF),
|
||||
LintId::of(drop_forget_ref::DROP_NON_DROP),
|
||||
|
|
|
@ -61,6 +61,7 @@ docs! {
|
|||
"cast_enum_constructor",
|
||||
"cast_enum_truncation",
|
||||
"cast_lossless",
|
||||
"cast_nan_to_int",
|
||||
"cast_possible_truncation",
|
||||
"cast_possible_wrap",
|
||||
"cast_precision_loss",
|
||||
|
|
15
src/docs/cast_nan_to_int.txt
Normal file
15
src/docs/cast_nan_to_int.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
### What it does
|
||||
Checks for a known NaN float being cast to an integer
|
||||
|
||||
### Why is this bad?
|
||||
NaNs are cast into zero, so one could simply use this and make the
|
||||
code more readable. The lint could also hint at a programmer error.
|
||||
|
||||
### Example
|
||||
```
|
||||
let _: (0.0_f32 / 0.0) as u64;
|
||||
```
|
||||
Use instead:
|
||||
```
|
||||
let _: = 0_u64;
|
||||
```
|
18
tests/ui/cast_nan_to_int.rs
Normal file
18
tests/ui/cast_nan_to_int.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
#![warn(clippy::cast_nan_to_int)]
|
||||
#![allow(clippy::eq_op)]
|
||||
|
||||
fn main() {
|
||||
let _ = (0.0_f32 / -0.0) as usize;
|
||||
let _ = (f64::INFINITY * -0.0) as usize;
|
||||
let _ = (0.0 * f32::INFINITY) as usize;
|
||||
|
||||
let _ = (f64::INFINITY + f64::NEG_INFINITY) as usize;
|
||||
let _ = (f32::INFINITY - f32::INFINITY) as usize;
|
||||
let _ = (f32::INFINITY / f32::NEG_INFINITY) as usize;
|
||||
|
||||
// those won't be linted:
|
||||
let _ = (1.0_f32 / 0.0) as usize;
|
||||
let _ = (f32::INFINITY * f32::NEG_INFINITY) as usize;
|
||||
let _ = (f32::INFINITY - f32::NEG_INFINITY) as usize;
|
||||
let _ = (f64::INFINITY - 0.0) as usize;
|
||||
}
|
51
tests/ui/cast_nan_to_int.stderr
Normal file
51
tests/ui/cast_nan_to_int.stderr
Normal file
|
@ -0,0 +1,51 @@
|
|||
error: casting a known NaN to usize
|
||||
--> $DIR/cast_nan_to_int.rs:5:13
|
||||
|
|
||||
LL | let _ = (0.0_f32 / -0.0) as usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this always evaluates to 0
|
||||
= note: `-D clippy::cast-nan-to-int` implied by `-D warnings`
|
||||
|
||||
error: casting a known NaN to usize
|
||||
--> $DIR/cast_nan_to_int.rs:6:13
|
||||
|
|
||||
LL | let _ = (f64::INFINITY * -0.0) as usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this always evaluates to 0
|
||||
|
||||
error: casting a known NaN to usize
|
||||
--> $DIR/cast_nan_to_int.rs:7:13
|
||||
|
|
||||
LL | let _ = (0.0 * f32::INFINITY) as usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this always evaluates to 0
|
||||
|
||||
error: casting a known NaN to usize
|
||||
--> $DIR/cast_nan_to_int.rs:9:13
|
||||
|
|
||||
LL | let _ = (f64::INFINITY + f64::NEG_INFINITY) as usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this always evaluates to 0
|
||||
|
||||
error: casting a known NaN to usize
|
||||
--> $DIR/cast_nan_to_int.rs:10:13
|
||||
|
|
||||
LL | let _ = (f32::INFINITY - f32::INFINITY) as usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this always evaluates to 0
|
||||
|
||||
error: casting a known NaN to usize
|
||||
--> $DIR/cast_nan_to_int.rs:11:13
|
||||
|
|
||||
LL | let _ = (f32::INFINITY / f32::NEG_INFINITY) as usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this always evaluates to 0
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
Loading…
Reference in a new issue