about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/casts/ptr_as_ptr.rs64
-rw-r--r--tests/ui/ptr_as_ptr.fixed16
-rw-r--r--tests/ui/ptr_as_ptr.rs16
-rw-r--r--tests/ui/ptr_as_ptr.stderr28
4 files changed, 82 insertions, 42 deletions
diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs
index 15ffb00da88..181dbcf6e9a 100644
--- a/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -1,9 +1,7 @@
-use std::borrow::Cow;
-
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
 use rustc_lint::LateContext;
@@ -16,33 +14,41 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
         return;
     }
 
-    if_chain! {
-        if let ExprKind::Cast(cast_expr, cast_to_hir_ty) = expr.kind;
-        let (cast_from, cast_to) = (cx.typeck_results().expr_ty(cast_expr), cx.typeck_results().expr_ty(expr));
-        if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind();
-        if let ty::RawPtr(TypeAndMut { ty: to_pointee_ty, mutbl: to_mutbl }) = cast_to.kind();
-        if matches!((from_mutbl, to_mutbl),
-            (Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut));
+    if let ExprKind::Cast(cast_expr, cast_to_hir_ty) = expr.kind
+        && let (cast_from, cast_to) = (cx.typeck_results().expr_ty(cast_expr), cx.typeck_results().expr_ty(expr))
+        && let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind()
+        && let ty::RawPtr(TypeAndMut { ty: to_pointee_ty, mutbl: to_mutbl }) = cast_to.kind()
+        && matches!((from_mutbl, to_mutbl),
+            (Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut))
         // The `U` in `pointer::cast` have to be `Sized`
         // as explained here: https://github.com/rust-lang/rust/issues/60602.
-        if to_pointee_ty.is_sized(cx.tcx, cx.param_env);
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut applicability);
-            let turbofish = match &cast_to_hir_ty.kind {
-                    TyKind::Infer => Cow::Borrowed(""),
-                    TyKind::Ptr(mut_ty) if matches!(mut_ty.ty.kind, TyKind::Infer) => Cow::Borrowed(""),
-                    _ => Cow::Owned(format!("::<{to_pointee_ty}>")),
-                };
-            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()),
-                applicability,
-            );
-        }
+        && 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) => {
+                if matches!(mut_ty.ty.kind, TyKind::Infer) {
+                    String::new()
+                } else {
+                    format!(
+                        "::<{}>",
+                        snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app)
+                    )
+                }
+            },
+            _ => return,
+        };
+
+        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()),
+            app,
+        );
     }
 }
diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed
index 26a64c861cf..84babb97416 100644
--- a/tests/ui/ptr_as_ptr.fixed
+++ b/tests/ui/ptr_as_ptr.fixed
@@ -3,8 +3,22 @@
 
 #![warn(clippy::ptr_as_ptr)]
 
+#[macro_use]
 extern crate proc_macros;
-use proc_macros::{external, inline_macros};
+
+mod issue_11278_a {
+    #[derive(Debug)]
+    pub struct T<D: std::fmt::Debug + ?Sized> {
+        pub p: D,
+    }
+}
+
+mod issue_11278_b {
+    pub fn f(o: &mut super::issue_11278_a::T<dyn std::fmt::Debug>) -> super::issue_11278_a::T<String> {
+        // Retain `super`
+        *unsafe { Box::from_raw(Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()) }
+    }
+}
 
 #[inline_macros]
 fn main() {
diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs
index ea40d494733..34fd76428b2 100644
--- a/tests/ui/ptr_as_ptr.rs
+++ b/tests/ui/ptr_as_ptr.rs
@@ -3,8 +3,22 @@
 
 #![warn(clippy::ptr_as_ptr)]
 
+#[macro_use]
 extern crate proc_macros;
-use proc_macros::{external, inline_macros};
+
+mod issue_11278_a {
+    #[derive(Debug)]
+    pub struct T<D: std::fmt::Debug + ?Sized> {
+        pub p: D,
+    }
+}
+
+mod issue_11278_b {
+    pub fn f(o: &mut super::issue_11278_a::T<dyn std::fmt::Debug>) -> super::issue_11278_a::T<String> {
+        // Retain `super`
+        *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
+    }
+}
 
 #[inline_macros]
 fn main() {
diff --git a/tests/ui/ptr_as_ptr.stderr b/tests/ui/ptr_as_ptr.stderr
index 78d733994ac..e64f3351505 100644
--- a/tests/ui/ptr_as_ptr.stderr
+++ b/tests/ui/ptr_as_ptr.stderr
@@ -1,37 +1,43 @@
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:14:13
+  --> $DIR/ptr_as_ptr.rs:19:33
    |
-LL |     let _ = ptr as *const i32;
-   |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
+LL |         *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()`
    |
    = note: `-D clippy::ptr-as-ptr` implied by `-D warnings`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:15:13
+  --> $DIR/ptr_as_ptr.rs:28:13
+   |
+LL |     let _ = ptr as *const i32;
+   |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:29:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:20:17
+  --> $DIR/ptr_as_ptr.rs:34:17
    |
 LL |         let _ = *ptr_ptr as *const i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:33:25
+  --> $DIR/ptr_as_ptr.rs:47:25
    |
 LL |     let _: *const i32 = ptr as *const _;
    |                         ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:34:23
+  --> $DIR/ptr_as_ptr.rs:48:23
    |
 LL |     let _: *mut i32 = mut_ptr as _;
    |                       ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:37:21
+  --> $DIR/ptr_as_ptr.rs:51:21
    |
 LL |     let _ = inline!($ptr as *const i32);
    |                     ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
@@ -39,16 +45,16 @@ LL |     let _ = inline!($ptr as *const i32);
    = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:58:13
+  --> $DIR/ptr_as_ptr.rs:72:13
    |
 LL |     let _ = ptr as *const i32;
    |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:59:13
+  --> $DIR/ptr_as_ptr.rs:73:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors