about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-03-14 16:21:02 +0100
committerSamuel Tardieu <sam@rfc1149.net>2025-03-24 09:47:40 +0100
commit78d456a647c73bfdf933b806080e6e1a06b37c06 (patch)
treee285a8bb531f3ca76332e883d8e8f222e9d339f8
parent4d0d6f591dc903ba151735e246005c354eb8f4ee (diff)
downloadrust-78d456a647c73bfdf933b806080e6e1a06b37c06.tar.gz
rust-78d456a647c73bfdf933b806080e6e1a06b37c06.zip
Make `borrow_as_ptr` flag implicit casts as well
-rw-r--r--clippy_lints/src/casts/borrow_as_ptr.rs27
-rw-r--r--clippy_lints/src/casts/mod.rs3
-rw-r--r--clippy_lints/src/non_copy_const.rs2
-rw-r--r--tests/ui/borrow_as_ptr.fixed18
-rw-r--r--tests/ui/borrow_as_ptr.rs18
-rw-r--r--tests/ui/borrow_as_ptr.stderr35
6 files changed, 99 insertions, 4 deletions
diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs
index 0c9639f3ea6..ad0a4f8cdf3 100644
--- a/clippy_lints/src/casts/borrow_as_ptr.rs
+++ b/clippy_lints/src/casts/borrow_as_ptr.rs
@@ -1,11 +1,12 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::msrvs::Msrv;
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::{is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core};
+use clippy_utils::{get_parent_expr, is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core};
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind};
 use rustc_lint::LateContext;
+use rustc_middle::ty::adjustment::{Adjust, AutoBorrow};
 use rustc_span::BytePos;
 
 use super::BORROW_AS_PTR;
@@ -55,3 +56,25 @@ pub(super) fn check<'tcx>(
     }
     false
 }
+
+/// Check for an implicit cast from reference to raw pointer outside an explicit `as`.
+pub(super) fn check_implicit_cast(cx: &LateContext<'_>, expr: &Expr<'_>) {
+    if !expr.span.from_expansion()
+        && let ExprKind::AddrOf(BorrowKind::Ref, _, pointee) = expr.kind
+        && !matches!(get_parent_expr(cx, expr).map(|e| e.kind), Some(ExprKind::Cast(..)))
+        && let [deref, borrow] = cx.typeck_results().expr_adjustments(expr)
+        && matches!(deref.kind, Adjust::Deref(..))
+        && let Adjust::Borrow(AutoBorrow::RawPtr(mutability)) = borrow.kind
+        // Do not suggest taking a raw pointer to a temporary value
+        && !is_expr_temporary_value(cx, pointee)
+    {
+        span_lint_and_then(cx, BORROW_AS_PTR, expr.span, "implicit borrow as raw pointer", |diag| {
+            diag.span_suggestion_verbose(
+                expr.span.until(pointee.span),
+                "use a raw pointer instead",
+                format!("&raw {} ", mutability.ptr_str()),
+                Applicability::MachineApplicable,
+            );
+        });
+    }
+}
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index dc2a1fa85bf..b56a4180e6c 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -846,6 +846,9 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             }
         }
 
+        if self.msrv.meets(cx, msrvs::RAW_REF_OP) {
+            borrow_as_ptr::check_implicit_cast(cx, expr);
+        }
         cast_ptr_alignment::check(cx, expr);
         char_lit_as_u8::check(cx, expr);
         ptr_as_ptr::check(cx, expr, self.msrv);
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index d4da12451f1..12efdaeb81e 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -449,7 +449,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
 
                             dereferenced_expr = parent_expr;
                         },
-                        ExprKind::Index(e, _, _) if ptr::eq(&**e, cur_expr) => {
+                        ExprKind::Index(e, _, _) if ptr::eq(&raw const **e, cur_expr) => {
                             // `e[i]` => desugared to `*Index::index(&e, i)`,
                             // meaning `e` must be referenced.
                             // no need to go further up since a method call is involved now.
diff --git a/tests/ui/borrow_as_ptr.fixed b/tests/ui/borrow_as_ptr.fixed
index 3dca06fce4b..3ba2eea59f0 100644
--- a/tests/ui/borrow_as_ptr.fixed
+++ b/tests/ui/borrow_as_ptr.fixed
@@ -29,3 +29,21 @@ fn issue_13882() {
     let _raw = (&raw mut x[1]).wrapping_offset(-1);
     //~^ borrow_as_ptr
 }
+
+fn implicit_cast() {
+    let val = 1;
+    let p: *const i32 = &raw const val;
+    //~^ borrow_as_ptr
+
+    let mut val = 1;
+    let p: *mut i32 = &raw mut val;
+    //~^ borrow_as_ptr
+
+    let mut val = 1;
+    // Only lint the leftmost argument, the rightmost is ref to a temporary
+    core::ptr::eq(&raw const val, &1);
+    //~^ borrow_as_ptr
+
+    // Do not lint references to temporaries
+    core::ptr::eq(&0i32, &1i32);
+}
diff --git a/tests/ui/borrow_as_ptr.rs b/tests/ui/borrow_as_ptr.rs
index 3559dc23d01..8cdd0512da5 100644
--- a/tests/ui/borrow_as_ptr.rs
+++ b/tests/ui/borrow_as_ptr.rs
@@ -29,3 +29,21 @@ fn issue_13882() {
     let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1);
     //~^ borrow_as_ptr
 }
+
+fn implicit_cast() {
+    let val = 1;
+    let p: *const i32 = &val;
+    //~^ borrow_as_ptr
+
+    let mut val = 1;
+    let p: *mut i32 = &mut val;
+    //~^ borrow_as_ptr
+
+    let mut val = 1;
+    // Only lint the leftmost argument, the rightmost is ref to a temporary
+    core::ptr::eq(&val, &1);
+    //~^ borrow_as_ptr
+
+    // Do not lint references to temporaries
+    core::ptr::eq(&0i32, &1i32);
+}
diff --git a/tests/ui/borrow_as_ptr.stderr b/tests/ui/borrow_as_ptr.stderr
index 4a9f2ed4aa0..b1fcce49403 100644
--- a/tests/ui/borrow_as_ptr.stderr
+++ b/tests/ui/borrow_as_ptr.stderr
@@ -25,5 +25,38 @@ error: borrow as raw pointer
 LL |     let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1);
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: try: `&raw mut x[1]`
 
-error: aborting due to 4 previous errors
+error: implicit borrow as raw pointer
+  --> tests/ui/borrow_as_ptr.rs:35:25
+   |
+LL |     let p: *const i32 = &val;
+   |                         ^^^^
+   |
+help: use a raw pointer instead
+   |
+LL |     let p: *const i32 = &raw const val;
+   |                          +++++++++
+
+error: implicit borrow as raw pointer
+  --> tests/ui/borrow_as_ptr.rs:39:23
+   |
+LL |     let p: *mut i32 = &mut val;
+   |                       ^^^^^^^^
+   |
+help: use a raw pointer instead
+   |
+LL |     let p: *mut i32 = &raw mut val;
+   |                        +++
+
+error: implicit borrow as raw pointer
+  --> tests/ui/borrow_as_ptr.rs:44:19
+   |
+LL |     core::ptr::eq(&val, &1);
+   |                   ^^^^
+   |
+help: use a raw pointer instead
+   |
+LL |     core::ptr::eq(&raw const val, &1);
+   |                    +++++++++
+
+error: aborting due to 7 previous errors