about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-12-06 13:53:07 +0000
committerbors <bors@rust-lang.org>2023-12-06 13:53:07 +0000
commit2793e8d103f7f977f8b672558c18f6ab1dc4a578 (patch)
tree477b3d28ec288f190c75b37ebab33bfbdd71559b
parent4a56563154f9c93708ec5ff9ba94d69a0203765e (diff)
parent8eea8b1577bb4ca81149f81f5b5abbc12bee2204 (diff)
downloadrust-2793e8d103f7f977f8b672558c18f6ab1dc4a578.tar.gz
rust-2793e8d103f7f977f8b672558c18f6ab1dc4a578.zip
Auto merge of #11913 - KisaragiEffective:fix/ptr-as-ptr-with-null, r=llogiq
fix(ptr_as_ptr): handle `std::ptr::null{_mut}`

close rust-lang#11066
close rust-lang#11665
close rust-lang#11911

*Please write a short comment explaining your change (or "none" for internal only changes)*

changelog: [`ptr_as_ptr`]: handle `std::ptr::null` and `std::ptr::null_mut`
-rw-r--r--clippy_lints/src/casts/ptr_as_ptr.rs55
-rw-r--r--tests/ui/ptr_as_ptr.fixed115
-rw-r--r--tests/ui/ptr_as_ptr.rs115
-rw-r--r--tests/ui/ptr_as_ptr.stderr146
4 files changed, 426 insertions, 5 deletions
diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs
index 0c555c1acc5..35e36e9ef3f 100644
--- a/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -3,12 +3,29 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
+use rustc_hir::{Expr, ExprKind, Mutability, QPath, TyKind};
+use rustc_hir_pretty::qpath_to_string;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, TypeAndMut};
+use rustc_span::sym;
 
 use super::PTR_AS_PTR;
 
+enum OmitFollowedCastReason<'a> {
+    None,
+    Null(&'a QPath<'a>),
+    NullMut(&'a QPath<'a>),
+}
+
+impl OmitFollowedCastReason<'_> {
+    fn corresponding_item(&self) -> Option<&QPath<'_>> {
+        match self {
+            OmitFollowedCastReason::None => None,
+            OmitFollowedCastReason::Null(x) | OmitFollowedCastReason::NullMut(x) => Some(*x),
+        }
+    }
+}
+
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
     if !msrv.meets(msrvs::POINTER_CAST) {
         return;
@@ -25,7 +42,6 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
         && to_pointee_ty.is_sized(cx.tcx, cx.param_env)
     {
         let mut app = Applicability::MachineApplicable;
-        let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
         let turbofish = match &cast_to_hir_ty.kind {
             TyKind::Infer => String::new(),
             TyKind::Ptr(mut_ty) => {
@@ -41,13 +57,44 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
             _ => return,
         };
 
+        // following `cast` does not compile because it fails to infer what type is expected
+        // as type argument to `std::ptr::ptr_null` or `std::ptr::ptr_null_mut`, so
+        // we omit following `cast`:
+        let omit_cast = if let ExprKind::Call(func, []) = cast_expr.kind
+            && let ExprKind::Path(ref qpath @ QPath::Resolved(None, path)) = func.kind
+        {
+            let method_defid = path.res.def_id();
+            if cx.tcx.is_diagnostic_item(sym::ptr_null, method_defid) {
+                OmitFollowedCastReason::Null(qpath)
+            } else if cx.tcx.is_diagnostic_item(sym::ptr_null_mut, method_defid) {
+                OmitFollowedCastReason::NullMut(qpath)
+            } else {
+                OmitFollowedCastReason::None
+            }
+        } else {
+            OmitFollowedCastReason::None
+        };
+
+        let (help, final_suggestion) = if let Some(method) = omit_cast.corresponding_item() {
+            // don't force absolute path
+            let method = qpath_to_string(method);
+            ("try call directly", format!("{method}{turbofish}()"))
+        } else {
+            let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
+
+            (
+                "try `pointer::cast`, a safer alternative",
+                format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()),
+            )
+        };
+
         span_lint_and_sugg(
             cx,
             PTR_AS_PTR,
             expr.span,
             "`as` casting between raw pointers without changing its mutability",
-            "try `pointer::cast`, a safer alternative",
-            format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()),
+            help,
+            final_suggestion,
             app,
         );
     }
diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed
index ca13b52ae3b..fa15c323540 100644
--- a/tests/ui/ptr_as_ptr.fixed
+++ b/tests/ui/ptr_as_ptr.fixed
@@ -71,3 +71,118 @@ fn _msrv_1_38() {
     let _ = ptr.cast::<i32>();
     let _ = mut_ptr.cast::<i32>();
 }
+
+#[allow(clippy::unnecessary_cast)]
+mod null {
+    fn use_path_mut() -> *mut u32 {
+        use std::ptr;
+        ptr::null_mut::<u32>()
+    }
+
+    fn full_path_mut() -> *mut u32 {
+        std::ptr::null_mut::<u32>()
+    }
+
+    fn core_path_mut() -> *mut u32 {
+        use core::ptr;
+        ptr::null_mut::<u32>()
+    }
+
+    fn full_core_path_mut() -> *mut u32 {
+        core::ptr::null_mut::<u32>()
+    }
+
+    fn use_path() -> *const u32 {
+        use std::ptr;
+        ptr::null::<u32>()
+    }
+
+    fn full_path() -> *const u32 {
+        std::ptr::null::<u32>()
+    }
+
+    fn core_path() -> *const u32 {
+        use core::ptr;
+        ptr::null::<u32>()
+    }
+
+    fn full_core_path() -> *const u32 {
+        core::ptr::null::<u32>()
+    }
+}
+
+mod null_ptr_infer {
+    fn use_path_mut() -> *mut u32 {
+        use std::ptr;
+        ptr::null_mut()
+    }
+
+    fn full_path_mut() -> *mut u32 {
+        std::ptr::null_mut()
+    }
+
+    fn core_path_mut() -> *mut u32 {
+        use core::ptr;
+        ptr::null_mut()
+    }
+
+    fn full_core_path_mut() -> *mut u32 {
+        core::ptr::null_mut()
+    }
+
+    fn use_path() -> *const u32 {
+        use std::ptr;
+        ptr::null()
+    }
+
+    fn full_path() -> *const u32 {
+        std::ptr::null()
+    }
+
+    fn core_path() -> *const u32 {
+        use core::ptr;
+        ptr::null()
+    }
+
+    fn full_core_path() -> *const u32 {
+        core::ptr::null()
+    }
+}
+
+mod null_entire_infer {
+    fn use_path_mut() -> *mut u32 {
+        use std::ptr;
+        ptr::null_mut()
+    }
+
+    fn full_path_mut() -> *mut u32 {
+        std::ptr::null_mut()
+    }
+
+    fn core_path_mut() -> *mut u32 {
+        use core::ptr;
+        ptr::null_mut()
+    }
+
+    fn full_core_path_mut() -> *mut u32 {
+        core::ptr::null_mut()
+    }
+
+    fn use_path() -> *const u32 {
+        use std::ptr;
+        ptr::null()
+    }
+
+    fn full_path() -> *const u32 {
+        std::ptr::null()
+    }
+
+    fn core_path() -> *const u32 {
+        use core::ptr;
+        ptr::null()
+    }
+
+    fn full_core_path() -> *const u32 {
+        core::ptr::null()
+    }
+}
diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs
index 942c8734444..7ab52e63da5 100644
--- a/tests/ui/ptr_as_ptr.rs
+++ b/tests/ui/ptr_as_ptr.rs
@@ -71,3 +71,118 @@ fn _msrv_1_38() {
     let _ = ptr as *const i32;
     let _ = mut_ptr as *mut i32;
 }
+
+#[allow(clippy::unnecessary_cast)]
+mod null {
+    fn use_path_mut() -> *mut u32 {
+        use std::ptr;
+        ptr::null_mut() as *mut u32
+    }
+
+    fn full_path_mut() -> *mut u32 {
+        std::ptr::null_mut() as *mut u32
+    }
+
+    fn core_path_mut() -> *mut u32 {
+        use core::ptr;
+        ptr::null_mut() as *mut u32
+    }
+
+    fn full_core_path_mut() -> *mut u32 {
+        core::ptr::null_mut() as *mut u32
+    }
+
+    fn use_path() -> *const u32 {
+        use std::ptr;
+        ptr::null() as *const u32
+    }
+
+    fn full_path() -> *const u32 {
+        std::ptr::null() as *const u32
+    }
+
+    fn core_path() -> *const u32 {
+        use core::ptr;
+        ptr::null() as *const u32
+    }
+
+    fn full_core_path() -> *const u32 {
+        core::ptr::null() as *const u32
+    }
+}
+
+mod null_ptr_infer {
+    fn use_path_mut() -> *mut u32 {
+        use std::ptr;
+        ptr::null_mut() as *mut _
+    }
+
+    fn full_path_mut() -> *mut u32 {
+        std::ptr::null_mut() as *mut _
+    }
+
+    fn core_path_mut() -> *mut u32 {
+        use core::ptr;
+        ptr::null_mut() as *mut _
+    }
+
+    fn full_core_path_mut() -> *mut u32 {
+        core::ptr::null_mut() as *mut _
+    }
+
+    fn use_path() -> *const u32 {
+        use std::ptr;
+        ptr::null() as *const _
+    }
+
+    fn full_path() -> *const u32 {
+        std::ptr::null() as *const _
+    }
+
+    fn core_path() -> *const u32 {
+        use core::ptr;
+        ptr::null() as *const _
+    }
+
+    fn full_core_path() -> *const u32 {
+        core::ptr::null() as *const _
+    }
+}
+
+mod null_entire_infer {
+    fn use_path_mut() -> *mut u32 {
+        use std::ptr;
+        ptr::null_mut() as _
+    }
+
+    fn full_path_mut() -> *mut u32 {
+        std::ptr::null_mut() as _
+    }
+
+    fn core_path_mut() -> *mut u32 {
+        use core::ptr;
+        ptr::null_mut() as _
+    }
+
+    fn full_core_path_mut() -> *mut u32 {
+        core::ptr::null_mut() as _
+    }
+
+    fn use_path() -> *const u32 {
+        use std::ptr;
+        ptr::null() as _
+    }
+
+    fn full_path() -> *const u32 {
+        std::ptr::null() as _
+    }
+
+    fn core_path() -> *const u32 {
+        use core::ptr;
+        ptr::null() as _
+    }
+
+    fn full_core_path() -> *const u32 {
+        core::ptr::null() as _
+    }
+}
diff --git a/tests/ui/ptr_as_ptr.stderr b/tests/ui/ptr_as_ptr.stderr
index c0ce69b4357..ef64347e935 100644
--- a/tests/ui/ptr_as_ptr.stderr
+++ b/tests/ui/ptr_as_ptr.stderr
@@ -57,5 +57,149 @@ error: `as` casting between raw pointers without changing its mutability
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
-error: aborting due to 9 previous errors
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:79:9
+   |
+LL |         ptr::null_mut() as *mut u32
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:83:9
+   |
+LL |         std::ptr::null_mut() as *mut u32
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::<u32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:88:9
+   |
+LL |         ptr::null_mut() as *mut u32
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:92:9
+   |
+LL |         core::ptr::null_mut() as *mut u32
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::<u32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:97:9
+   |
+LL |         ptr::null() as *const u32
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:101:9
+   |
+LL |         std::ptr::null() as *const u32
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:106:9
+   |
+LL |         ptr::null() as *const u32
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:110:9
+   |
+LL |         core::ptr::null() as *const u32
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::<u32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:117:9
+   |
+LL |         ptr::null_mut() as *mut _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:121:9
+   |
+LL |         std::ptr::null_mut() as *mut _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:126:9
+   |
+LL |         ptr::null_mut() as *mut _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:130:9
+   |
+LL |         core::ptr::null_mut() as *mut _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:135:9
+   |
+LL |         ptr::null() as *const _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:139:9
+   |
+LL |         std::ptr::null() as *const _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:144:9
+   |
+LL |         ptr::null() as *const _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:148:9
+   |
+LL |         core::ptr::null() as *const _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:155:9
+   |
+LL |         ptr::null_mut() as _
+   |         ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:159:9
+   |
+LL |         std::ptr::null_mut() as _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:164:9
+   |
+LL |         ptr::null_mut() as _
+   |         ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:168:9
+   |
+LL |         core::ptr::null_mut() as _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:173:9
+   |
+LL |         ptr::null() as _
+   |         ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:177:9
+   |
+LL |         std::ptr::null() as _
+   |         ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:182:9
+   |
+LL |         ptr::null() as _
+   |         ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:186:9
+   |
+LL |         core::ptr::null() as _
+   |         ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
+
+error: aborting due to 33 previous errors