about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/casts/mod.rs5
-rw-r--r--clippy_lints/src/casts/ptr_cast_constness.rs27
-rw-r--r--tests/ui/ptr_cast_constness.fixed4
-rw-r--r--tests/ui/ptr_cast_constness.rs4
-rw-r--r--tests/ui/ptr_cast_constness.stderr24
5 files changed, 62 insertions, 2 deletions
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index fccddf558ed..39f50a347c0 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -419,6 +419,8 @@ declare_clippy_lint! {
     /// let ptr = mut_ptr as *const u32;
     /// let ptr1 = std::ptr::null::<u32>() as *mut u32;
     /// let ptr2 = std::ptr::null_mut::<u32>() as *const u32;
+    /// let ptr3 = std::ptr::null::<u32>().cast_mut();
+    /// let ptr4 = std::ptr::null_mut::<u32>().cast_const();
     /// ```
     /// Use instead:
     /// ```no_run
@@ -427,6 +429,8 @@ declare_clippy_lint! {
     /// let ptr = mut_ptr.cast_const();
     /// let ptr1 = std::ptr::null_mut::<u32>();
     /// let ptr2 = std::ptr::null::<u32>();
+    /// let ptr3 = std::ptr::null_mut::<u32>();
+    /// let ptr4 = std::ptr::null::<u32>();
     /// ```
     #[clippy::version = "1.72.0"]
     pub PTR_CAST_CONSTNESS,
@@ -813,6 +817,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
         char_lit_as_u8::check(cx, expr);
         ptr_as_ptr::check(cx, expr, &self.msrv);
         cast_slice_different_sizes::check(cx, expr, &self.msrv);
+        ptr_cast_constness::check_null_ptr_cast_method(cx, expr);
     }
 
     extract_msrv_attr!(LateContext);
diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs
index 98bc38ed134..7518dd2435a 100644
--- a/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -71,3 +71,30 @@ pub(super) fn check<'tcx>(
         }
     }
 }
+
+pub(super) fn check_null_ptr_cast_method(cx: &LateContext<'_>, expr: &Expr<'_>) {
+    if let ExprKind::MethodCall(method, cast_expr, [], _) = expr.kind
+        && let ExprKind::Call(func, []) = cast_expr.kind
+        && let ExprKind::Path(QPath::Resolved(None, path)) = func.kind
+        && let Some(defid) = path.res.opt_def_id()
+        && let method = match (cx.tcx.get_diagnostic_name(defid), method.ident.as_str()) {
+            (Some(sym::ptr_null), "cast_mut") => "null_mut",
+            (Some(sym::ptr_null_mut), "cast_const") => "null",
+            _ => return,
+        }
+        && let Some(prefix) = std_or_core(cx)
+        && let mut app = Applicability::MachineApplicable
+        && let sugg = format!("{}", Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app))
+        && let Some((_, after_lt)) = sugg.split_once("::<")
+    {
+        span_lint_and_sugg(
+            cx,
+            PTR_CAST_CONSTNESS,
+            expr.span,
+            "changing constness of a null pointer",
+            format!("use `{method}()` directly instead"),
+            format!("{prefix}::ptr::{method}::<{after_lt}"),
+            app,
+        );
+    }
+}
diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed
index 5bf9a30b016..9a5272c7adc 100644
--- a/tests/ui/ptr_cast_constness.fixed
+++ b/tests/ui/ptr_cast_constness.fixed
@@ -74,10 +74,14 @@ fn null_pointers() {
     use std::ptr;
     let _ = std::ptr::null_mut::<String>();
     let _ = std::ptr::null::<u32>();
+    let _ = std::ptr::null_mut::<u32>();
+    let _ = std::ptr::null::<u32>();
 
     // Make sure the lint is triggered inside a macro
     let _ = inline!(std::ptr::null_mut::<u32>());
+    let _ = inline!(std::ptr::null_mut::<u32>());
 
     // Do not lint inside macros from external crates
     let _ = external!(ptr::null::<u32>() as *mut u32);
+    let _ = external!(ptr::null::<u32>().cast_mut());
 }
diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs
index 2575a5923e1..43ab5f5ba7c 100644
--- a/tests/ui/ptr_cast_constness.rs
+++ b/tests/ui/ptr_cast_constness.rs
@@ -74,10 +74,14 @@ fn null_pointers() {
     use std::ptr;
     let _ = ptr::null::<String>() as *mut String;
     let _ = ptr::null_mut::<u32>() as *const u32;
+    let _ = ptr::null::<u32>().cast_mut();
+    let _ = ptr::null_mut::<u32>().cast_const();
 
     // Make sure the lint is triggered inside a macro
     let _ = inline!(ptr::null::<u32>() as *mut u32);
+    let _ = inline!(ptr::null::<u32>().cast_mut());
 
     // Do not lint inside macros from external crates
     let _ = external!(ptr::null::<u32>() as *mut u32);
+    let _ = external!(ptr::null::<u32>().cast_mut());
 }
diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr
index 0806ca62806..a693793a4ae 100644
--- a/tests/ui/ptr_cast_constness.stderr
+++ b/tests/ui/ptr_cast_constness.stderr
@@ -55,13 +55,33 @@ error: `as` casting to make a mutable null pointer into a const null pointer
 LL |     let _ = ptr::null_mut::<u32>() as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()`
 
+error: changing constness of a null pointer
+  --> tests/ui/ptr_cast_constness.rs:77:13
+   |
+LL |     let _ = ptr::null::<u32>().cast_mut();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
+
+error: changing constness of a null pointer
+  --> tests/ui/ptr_cast_constness.rs:78:13
+   |
+LL |     let _ = ptr::null_mut::<u32>().cast_const();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()`
+
 error: `as` casting to make a const null pointer into a mutable null pointer
-  --> tests/ui/ptr_cast_constness.rs:79:21
+  --> tests/ui/ptr_cast_constness.rs:81:21
    |
 LL |     let _ = inline!(ptr::null::<u32>() as *mut u32);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
    |
    = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 10 previous errors
+error: changing constness of a null pointer
+  --> tests/ui/ptr_cast_constness.rs:82:21
+   |
+LL |     let _ = inline!(ptr::null::<u32>().cast_mut());
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
+   |
+   = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 13 previous errors