about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-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.rs8
-rw-r--r--clippy_lints/src/declared_lints.rs2
-rw-r--r--tests/ui/confusing_method_to_numeric_cast.fixed14
-rw-r--r--tests/ui/confusing_method_to_numeric_cast.rs14
-rw-r--r--tests/ui/confusing_method_to_numeric_cast.stderr100
-rw-r--r--tests/ui/primitive_method_to_numeric_cast.fixed5
-rw-r--r--tests/ui/primitive_method_to_numeric_cast.rs5
-rw-r--r--tests/ui/primitive_method_to_numeric_cast.stderr15
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
-