diff options
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | clippy_lints/src/casts/confusing_method_to_numeric_cast.rs (renamed from clippy_lints/src/casts/primitive_method_to_numeric_cast.rs) | 51 | ||||
| -rw-r--r-- | clippy_lints/src/casts/mod.rs | 8 | ||||
| -rw-r--r-- | clippy_lints/src/declared_lints.rs | 2 | ||||
| -rw-r--r-- | tests/ui/confusing_method_to_numeric_cast.fixed | 14 | ||||
| -rw-r--r-- | tests/ui/confusing_method_to_numeric_cast.rs | 14 | ||||
| -rw-r--r-- | tests/ui/confusing_method_to_numeric_cast.stderr | 100 | ||||
| -rw-r--r-- | tests/ui/primitive_method_to_numeric_cast.fixed | 5 | ||||
| -rw-r--r-- | tests/ui/primitive_method_to_numeric_cast.rs | 5 | ||||
| -rw-r--r-- | tests/ui/primitive_method_to_numeric_cast.stderr | 15 |
10 files changed, 172 insertions, 44 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index ca2e7389790..6ab4cffb0cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5594,6 +5594,7 @@ Released 2018-09-13 [`collection_is_never_read`]: https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read [`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain [`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty +[`confusing_method_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#confusing_method_to_numeric_cast [`const_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_is_empty [`const_static_lifetime`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_static_lifetime [`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator @@ -6068,7 +6069,6 @@ Released 2018-09-13 [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma [`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence [`precedence_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence_bits -[`primitive_method_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#primitive_method_to_numeric_cast [`print_in_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_in_format_impl [`print_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_literal [`print_stderr`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr diff --git a/clippy_lints/src/casts/primitive_method_to_numeric_cast.rs b/clippy_lints/src/casts/confusing_method_to_numeric_cast.rs index 380fa98cd15..31cdd078f45 100644 --- a/clippy_lints/src/casts/primitive_method_to_numeric_cast.rs +++ b/clippy_lints/src/casts/confusing_method_to_numeric_cast.rs @@ -1,12 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::match_def_path; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, GenericArg, Ty}; +use rustc_span::def_id::DefId; +use rustc_span::{Symbol, sym}; -use super::PRIMITIVE_METHOD_TO_NUMERIC_CAST; +use super::CONFUSING_METHOD_TO_NUMERIC_CAST; fn get_primitive_ty_name(ty: Ty<'_>) -> Option<&'static str> { match ty.kind() { @@ -18,6 +19,37 @@ fn get_primitive_ty_name(ty: Ty<'_>) -> Option<&'static str> { } } +fn get_const_name_and_ty_name( + cx: &LateContext<'_>, + method_name: Symbol, + method_def_id: DefId, + generics: &[GenericArg<'_>], +) -> Option<(&'static str, &'static str)> { + let method_name = method_name.as_str(); + let diagnostic_name = cx.tcx.get_diagnostic_name(method_def_id); + + let ty_name = if diagnostic_name.is_some_and(|diag| diag == sym::cmp_ord_min || diag == sym::cmp_ord_max) { + // We get the type on which the `min`/`max` method of the `Ord` trait is implemented. + if let [ty] = generics + && let Some(ty) = ty.as_type() + { + get_primitive_ty_name(ty)? + } else { + return None; + } + } else if let Some(impl_id) = cx.tcx.impl_of_method(method_def_id) + && let Some(ty_name) = get_primitive_ty_name(cx.tcx.type_of(impl_id).instantiate_identity()) + && ["min", "max", "minimum", "maximum", "min_value", "max_value"].contains(&method_name) + { + ty_name + } else { + return None; + }; + + let const_name = if method_name.starts_with("max") { "MAX" } else { "MIN" }; + Some((const_name, ty_name)) +} + pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { // We allow casts from any function type to any function type. match cast_to.kind() { @@ -27,28 +59,21 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, if let ty::FnDef(def_id, generics) = cast_from.kind() && let Some(method_name) = cx.tcx.opt_item_name(*def_id) - && let method_name = method_name.as_str() - && (method_name == "min" || method_name == "max") - // We get the type on which the `min`/`max` method of the `Ord` trait is implemented. - && let [ty] = generics.as_slice() - && let Some(ty) = ty.as_type() - // We get its name in case it's a primitive with an associated MIN/MAX constant. - && let Some(ty_name) = get_primitive_ty_name(ty) - && match_def_path(cx, *def_id, &["core", "cmp", "Ord", method_name]) + && let Some((const_name, ty_name)) = get_const_name_and_ty_name(cx, method_name, *def_id, generics.as_slice()) { let mut applicability = Applicability::MaybeIncorrect; let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability); span_lint_and_then( cx, - PRIMITIVE_METHOD_TO_NUMERIC_CAST, + CONFUSING_METHOD_TO_NUMERIC_CAST, expr.span, format!("casting function pointer `{from_snippet}` to `{cast_to}`"), |diag| { diag.span_suggestion_verbose( expr.span, "did you mean to use the associated constant?", - format!("{ty_name}::{} as {cast_to}", method_name.to_ascii_uppercase()), + format!("{ty_name}::{const_name} as {cast_to}"), applicability, ); }, diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 7c8fa0b4d92..6eac7ad438b 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -14,11 +14,11 @@ mod cast_sign_loss; mod cast_slice_different_sizes; mod cast_slice_from_raw_parts; mod char_lit_as_u8; +mod confusing_method_to_numeric_cast; mod fn_to_numeric_cast; mod fn_to_numeric_cast_any; mod fn_to_numeric_cast_with_truncation; mod manual_dangling_ptr; -mod primitive_method_to_numeric_cast; mod ptr_as_ptr; mod ptr_cast_constness; mod ref_as_ptr; @@ -808,7 +808,7 @@ declare_clippy_lint! { /// let _ = u16::MAX as usize; /// ``` #[clippy::version = "1.86.0"] - pub PRIMITIVE_METHOD_TO_NUMERIC_CAST, + pub CONFUSING_METHOD_TO_NUMERIC_CAST, suspicious, "casting a primitive method pointer to any integer type" } @@ -850,7 +850,7 @@ impl_lint_pass!(Casts => [ REF_AS_PTR, AS_POINTER_UNDERSCORE, MANUAL_DANGLING_PTR, - PRIMITIVE_METHOD_TO_NUMERIC_CAST, + CONFUSING_METHOD_TO_NUMERIC_CAST, ]); impl<'tcx> LateLintPass<'tcx> for Casts { @@ -875,7 +875,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { ptr_cast_constness::check(cx, expr, cast_from_expr, cast_from, cast_to, self.msrv); as_ptr_cast_mut::check(cx, expr, cast_from_expr, cast_to); fn_to_numeric_cast_any::check(cx, expr, cast_from_expr, cast_from, cast_to); - primitive_method_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to); + confusing_method_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to); fn_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to); fn_to_numeric_cast_with_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to); zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir); diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 1d4c75dafa3..472d0f732ac 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -64,11 +64,11 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::casts::CAST_SLICE_DIFFERENT_SIZES_INFO, crate::casts::CAST_SLICE_FROM_RAW_PARTS_INFO, crate::casts::CHAR_LIT_AS_U8_INFO, + crate::casts::CONFUSING_METHOD_TO_NUMERIC_CAST_INFO, crate::casts::FN_TO_NUMERIC_CAST_INFO, crate::casts::FN_TO_NUMERIC_CAST_ANY_INFO, crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO, crate::casts::MANUAL_DANGLING_PTR_INFO, - crate::casts::PRIMITIVE_METHOD_TO_NUMERIC_CAST_INFO, crate::casts::PTR_AS_PTR_INFO, crate::casts::PTR_CAST_CONSTNESS_INFO, crate::casts::REF_AS_PTR_INFO, diff --git a/tests/ui/confusing_method_to_numeric_cast.fixed b/tests/ui/confusing_method_to_numeric_cast.fixed new file mode 100644 index 00000000000..e698b99edd5 --- /dev/null +++ b/tests/ui/confusing_method_to_numeric_cast.fixed @@ -0,0 +1,14 @@ +#![feature(float_minimum_maximum)] +#![warn(clippy::confusing_method_to_numeric_cast)] + +fn main() { + let _ = u16::MAX as usize; //~ confusing_method_to_numeric_cast + let _ = u16::MIN as usize; //~ confusing_method_to_numeric_cast + let _ = u16::MAX as usize; //~ confusing_method_to_numeric_cast + let _ = u16::MIN as usize; //~ confusing_method_to_numeric_cast + + let _ = f32::MAX as usize; //~ confusing_method_to_numeric_cast + let _ = f32::MAX as usize; //~ confusing_method_to_numeric_cast + let _ = f32::MIN as usize; //~ confusing_method_to_numeric_cast + let _ = f32::MIN as usize; //~ confusing_method_to_numeric_cast +} diff --git a/tests/ui/confusing_method_to_numeric_cast.rs b/tests/ui/confusing_method_to_numeric_cast.rs new file mode 100644 index 00000000000..ef65c21563d --- /dev/null +++ b/tests/ui/confusing_method_to_numeric_cast.rs @@ -0,0 +1,14 @@ +#![feature(float_minimum_maximum)] +#![warn(clippy::confusing_method_to_numeric_cast)] + +fn main() { + let _ = u16::max as usize; //~ confusing_method_to_numeric_cast + let _ = u16::min as usize; //~ confusing_method_to_numeric_cast + let _ = u16::max_value as usize; //~ confusing_method_to_numeric_cast + let _ = u16::min_value as usize; //~ confusing_method_to_numeric_cast + + let _ = f32::maximum as usize; //~ confusing_method_to_numeric_cast + let _ = f32::max as usize; //~ confusing_method_to_numeric_cast + let _ = f32::minimum as usize; //~ confusing_method_to_numeric_cast + let _ = f32::min as usize; //~ confusing_method_to_numeric_cast +} diff --git a/tests/ui/confusing_method_to_numeric_cast.stderr b/tests/ui/confusing_method_to_numeric_cast.stderr new file mode 100644 index 00000000000..ba90df2059a --- /dev/null +++ b/tests/ui/confusing_method_to_numeric_cast.stderr @@ -0,0 +1,100 @@ +error: casting function pointer `u16::max` to `usize` + --> tests/ui/confusing_method_to_numeric_cast.rs:5:13 + | +LL | let _ = u16::max as usize; + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::confusing-method-to-numeric-cast` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::confusing_method_to_numeric_cast)]` +help: did you mean to use the associated constant? + | +LL - let _ = u16::max as usize; +LL + let _ = u16::MAX as usize; + | + +error: casting function pointer `u16::min` to `usize` + --> tests/ui/confusing_method_to_numeric_cast.rs:6:13 + | +LL | let _ = u16::min as usize; + | ^^^^^^^^^^^^^^^^^ + | +help: did you mean to use the associated constant? + | +LL - let _ = u16::min as usize; +LL + let _ = u16::MIN as usize; + | + +error: casting function pointer `u16::max_value` to `usize` + --> tests/ui/confusing_method_to_numeric_cast.rs:7:13 + | +LL | let _ = u16::max_value as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: did you mean to use the associated constant? + | +LL - let _ = u16::max_value as usize; +LL + let _ = u16::MAX as usize; + | + +error: casting function pointer `u16::min_value` to `usize` + --> tests/ui/confusing_method_to_numeric_cast.rs:8:13 + | +LL | let _ = u16::min_value as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: did you mean to use the associated constant? + | +LL - let _ = u16::min_value as usize; +LL + let _ = u16::MIN as usize; + | + +error: casting function pointer `f32::maximum` to `usize` + --> tests/ui/confusing_method_to_numeric_cast.rs:10:13 + | +LL | let _ = f32::maximum as usize; + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: did you mean to use the associated constant? + | +LL - let _ = f32::maximum as usize; +LL + let _ = f32::MAX as usize; + | + +error: casting function pointer `f32::max` to `usize` + --> tests/ui/confusing_method_to_numeric_cast.rs:11:13 + | +LL | let _ = f32::max as usize; + | ^^^^^^^^^^^^^^^^^ + | +help: did you mean to use the associated constant? + | +LL - let _ = f32::max as usize; +LL + let _ = f32::MAX as usize; + | + +error: casting function pointer `f32::minimum` to `usize` + --> tests/ui/confusing_method_to_numeric_cast.rs:12:13 + | +LL | let _ = f32::minimum as usize; + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: did you mean to use the associated constant? + | +LL - let _ = f32::minimum as usize; +LL + let _ = f32::MIN as usize; + | + +error: casting function pointer `f32::min` to `usize` + --> tests/ui/confusing_method_to_numeric_cast.rs:13:13 + | +LL | let _ = f32::min as usize; + | ^^^^^^^^^^^^^^^^^ + | +help: did you mean to use the associated constant? + | +LL - let _ = f32::min as usize; +LL + let _ = f32::MIN as usize; + | + +error: aborting due to 8 previous errors + diff --git a/tests/ui/primitive_method_to_numeric_cast.fixed b/tests/ui/primitive_method_to_numeric_cast.fixed deleted file mode 100644 index 1ebb52618f1..00000000000 --- a/tests/ui/primitive_method_to_numeric_cast.fixed +++ /dev/null @@ -1,5 +0,0 @@ -#![warn(clippy::primitive_method_to_numeric_cast)] - -fn main() { - let _ = u16::MAX as usize; //~ primitive_method_to_numeric_cast -} diff --git a/tests/ui/primitive_method_to_numeric_cast.rs b/tests/ui/primitive_method_to_numeric_cast.rs deleted file mode 100644 index 89b0bfa84fe..00000000000 --- a/tests/ui/primitive_method_to_numeric_cast.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![warn(clippy::primitive_method_to_numeric_cast)] - -fn main() { - let _ = u16::max as usize; //~ primitive_method_to_numeric_cast -} diff --git a/tests/ui/primitive_method_to_numeric_cast.stderr b/tests/ui/primitive_method_to_numeric_cast.stderr deleted file mode 100644 index 5515dc646ce..00000000000 --- a/tests/ui/primitive_method_to_numeric_cast.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: casting function pointer `u16::max` to `usize` - --> tests/ui/primitive_method_to_numeric_cast.rs:4:13 - | -LL | let _ = u16::max as usize; - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::primitive-method-to-numeric-cast` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::primitive_method_to_numeric_cast)]` -help: did you mean to use the associated constant? - | -LL | let _ = u16::MAX as usize; - | ~~~~~~~~~~~~~~~~~ - -error: aborting due to 1 previous error - |
