mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 05:33:27 +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_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_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_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_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_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
|
[`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_abs_to_unsigned;
|
||||||
mod cast_enum_constructor;
|
mod cast_enum_constructor;
|
||||||
mod cast_lossless;
|
mod cast_lossless;
|
||||||
|
mod cast_nan_to_int;
|
||||||
mod cast_possible_truncation;
|
mod cast_possible_truncation;
|
||||||
mod cast_possible_wrap;
|
mod cast_possible_wrap;
|
||||||
mod cast_precision_loss;
|
mod cast_precision_loss;
|
||||||
|
@ -570,6 +571,7 @@ declare_clippy_lint! {
|
||||||
pedantic,
|
pedantic,
|
||||||
"borrowing just to cast to a raw pointer"
|
"borrowing just to cast to a raw pointer"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
/// Checks for a raw slice being cast to a slice pointer
|
/// 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"
|
"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 {
|
pub struct Casts {
|
||||||
msrv: Option<RustcVersion>,
|
msrv: Option<RustcVersion>,
|
||||||
}
|
}
|
||||||
|
@ -656,6 +680,7 @@ impl_lint_pass!(Casts => [
|
||||||
BORROW_AS_PTR,
|
BORROW_AS_PTR,
|
||||||
CAST_SLICE_FROM_RAW_PARTS,
|
CAST_SLICE_FROM_RAW_PARTS,
|
||||||
AS_PTR_CAST_MUT,
|
AS_PTR_CAST_MUT,
|
||||||
|
CAST_NAN_TO_INT,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Casts {
|
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_precision_loss::check(cx, expr, cast_from, cast_to);
|
||||||
cast_sign_loss::check(cx, expr, cast_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_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_lossless::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv);
|
||||||
cast_enum_constructor::check(cx, expr, cast_expr, cast_from);
|
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_ABS_TO_UNSIGNED),
|
||||||
LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
|
LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
|
||||||
LintId::of(casts::CAST_ENUM_TRUNCATION),
|
LintId::of(casts::CAST_ENUM_TRUNCATION),
|
||||||
|
LintId::of(casts::CAST_NAN_TO_INT),
|
||||||
LintId::of(casts::CAST_REF_TO_MUT),
|
LintId::of(casts::CAST_REF_TO_MUT),
|
||||||
LintId::of(casts::CAST_SLICE_DIFFERENT_SIZES),
|
LintId::of(casts::CAST_SLICE_DIFFERENT_SIZES),
|
||||||
LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
|
LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
|
||||||
|
|
|
@ -73,6 +73,7 @@ store.register_lints(&[
|
||||||
casts::CAST_ENUM_CONSTRUCTOR,
|
casts::CAST_ENUM_CONSTRUCTOR,
|
||||||
casts::CAST_ENUM_TRUNCATION,
|
casts::CAST_ENUM_TRUNCATION,
|
||||||
casts::CAST_LOSSLESS,
|
casts::CAST_LOSSLESS,
|
||||||
|
casts::CAST_NAN_TO_INT,
|
||||||
casts::CAST_POSSIBLE_TRUNCATION,
|
casts::CAST_POSSIBLE_TRUNCATION,
|
||||||
casts::CAST_POSSIBLE_WRAP,
|
casts::CAST_POSSIBLE_WRAP,
|
||||||
casts::CAST_PRECISION_LOSS,
|
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_ABS_TO_UNSIGNED),
|
||||||
LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
|
LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
|
||||||
LintId::of(casts::CAST_ENUM_TRUNCATION),
|
LintId::of(casts::CAST_ENUM_TRUNCATION),
|
||||||
|
LintId::of(casts::CAST_NAN_TO_INT),
|
||||||
LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
|
LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
|
||||||
LintId::of(crate_in_macro_def::CRATE_IN_MACRO_DEF),
|
LintId::of(crate_in_macro_def::CRATE_IN_MACRO_DEF),
|
||||||
LintId::of(drop_forget_ref::DROP_NON_DROP),
|
LintId::of(drop_forget_ref::DROP_NON_DROP),
|
||||||
|
|
|
@ -61,6 +61,7 @@ docs! {
|
||||||
"cast_enum_constructor",
|
"cast_enum_constructor",
|
||||||
"cast_enum_truncation",
|
"cast_enum_truncation",
|
||||||
"cast_lossless",
|
"cast_lossless",
|
||||||
|
"cast_nan_to_int",
|
||||||
"cast_possible_truncation",
|
"cast_possible_truncation",
|
||||||
"cast_possible_wrap",
|
"cast_possible_wrap",
|
||||||
"cast_precision_loss",
|
"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