about summary refs log tree commit diff
diff options
context:
space:
mode:
authoryanglsh <yanglsh@shanghaitech.edu.cn>2025-07-16 22:56:49 +0800
committeryanglsh <yanglsh@shanghaitech.edu.cn>2025-07-16 22:56:49 +0800
commitdf529eb8cc6182a1e2bf0d80be7426d68c6d071e (patch)
tree5992cb5ee6d5776b0a2e61425d5bf80f190290cf
parente1be06240d2be922d7cd20226ebb9b6d0051d311 (diff)
downloadrust-df529eb8cc6182a1e2bf0d80be7426d68c6d071e.tar.gz
rust-df529eb8cc6182a1e2bf0d80be7426d68c6d071e.zip
fix: `ptr_as_ptr` suggests wrongly with turbo fish
-rw-r--r--clippy_lints/src/casts/ptr_as_ptr.rs16
-rw-r--r--tests/ui/ptr_as_ptr.fixed8
-rw-r--r--tests/ui/ptr_as_ptr.rs8
-rw-r--r--tests/ui/ptr_as_ptr.stderr8
4 files changed, 36 insertions, 4 deletions
diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs
index 6f944914b8f..ee0f3fa81c6 100644
--- a/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -4,10 +4,9 @@ use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Mutability, QPath, TyKind};
-use rustc_hir_pretty::qpath_to_string;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::sym;
+use rustc_span::{Span, sym};
 
 use super::PTR_AS_PTR;
 
@@ -74,7 +73,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) {
 
         let (help, final_suggestion) = if let Some(method) = omit_cast.corresponding_item() {
             // don't force absolute path
-            let method = qpath_to_string(&cx.tcx, method);
+            let method = snippet_with_applicability(cx, qpath_span_without_turbofish(method), "..", &mut app);
             ("try call directly", format!("{method}{turbofish}()"))
         } else {
             let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
@@ -96,3 +95,14 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) {
         );
     }
 }
+
+fn qpath_span_without_turbofish(qpath: &QPath<'_>) -> Span {
+    if let QPath::Resolved(_, path) = qpath
+        && let [.., last_ident] = path.segments
+        && last_ident.args.is_some()
+    {
+        return qpath.span().shrink_to_lo().to(last_ident.ident.span);
+    }
+
+    qpath.span()
+}
diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed
index 2033f31c1ee..71fea6144e7 100644
--- a/tests/ui/ptr_as_ptr.fixed
+++ b/tests/ui/ptr_as_ptr.fixed
@@ -219,3 +219,11 @@ mod null_entire_infer {
         //~^ ptr_as_ptr
     }
 }
+
+#[allow(clippy::transmute_null_to_fn)]
+fn issue15283() {
+    unsafe {
+        let _: fn() = std::mem::transmute(std::ptr::null::<u8>());
+        //~^ ptr_as_ptr
+    }
+}
diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs
index 224d09b0eb6..4d507592a1e 100644
--- a/tests/ui/ptr_as_ptr.rs
+++ b/tests/ui/ptr_as_ptr.rs
@@ -219,3 +219,11 @@ mod null_entire_infer {
         //~^ ptr_as_ptr
     }
 }
+
+#[allow(clippy::transmute_null_to_fn)]
+fn issue15283() {
+    unsafe {
+        let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8);
+        //~^ ptr_as_ptr
+    }
+}
diff --git a/tests/ui/ptr_as_ptr.stderr b/tests/ui/ptr_as_ptr.stderr
index 66dae8e0135..adad159bb0f 100644
--- a/tests/ui/ptr_as_ptr.stderr
+++ b/tests/ui/ptr_as_ptr.stderr
@@ -201,5 +201,11 @@ error: `as` casting between raw pointers without changing their constness
 LL |         core::ptr::null() as _
    |         ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
 
-error: aborting due to 33 previous errors
+error: `as` casting between raw pointers without changing their constness
+  --> tests/ui/ptr_as_ptr.rs:226:43
+   |
+LL |         let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8);
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u8>()`
+
+error: aborting due to 34 previous errors