about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/casts/borrow_as_ptr.rs35
-rw-r--r--clippy_lints/src/casts/mod.rs19
-rw-r--r--clippy_utils/src/msrvs.rs4
-rw-r--r--tests/ui/borrow_and_ref_as_ptr.fixed11
-rw-r--r--tests/ui/borrow_and_ref_as_ptr.rs11
-rw-r--r--tests/ui/borrow_and_ref_as_ptr.stderr17
-rw-r--r--tests/ui/borrow_as_ptr_raw_ref.fixed19
-rw-r--r--tests/ui/borrow_as_ptr_raw_ref.rs19
-rw-r--r--tests/ui/borrow_as_ptr_raw_ref.stderr17
9 files changed, 133 insertions, 19 deletions
diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs
index 4dd51dcbc9a..67aa33ca06c 100644
--- a/clippy_lints/src/casts/borrow_as_ptr.rs
+++ b/clippy_lints/src/casts/borrow_as_ptr.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::Msrv;
 use clippy_utils::source::snippet_with_context;
-use clippy_utils::std_or_core;
+use clippy_utils::{is_lint_allowed, msrvs, std_or_core};
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind};
 use rustc_lint::LateContext;
@@ -13,15 +14,12 @@ pub(super) fn check<'tcx>(
     expr: &'tcx Expr<'_>,
     cast_expr: &'tcx Expr<'_>,
     cast_to: &'tcx Ty<'_>,
-) {
+    msrv: &Msrv,
+) -> bool {
     if matches!(cast_to.kind, TyKind::Ptr(_))
         && let ExprKind::AddrOf(BorrowKind::Ref, mutability, e) = cast_expr.kind
-        && let Some(std_or_core) = std_or_core(cx)
+        && !is_lint_allowed(cx, BORROW_AS_PTR, expr.hir_id)
     {
-        let macro_name = match mutability {
-            Mutability::Not => "addr_of",
-            Mutability::Mut => "addr_of_mut",
-        };
         let mut app = Applicability::MachineApplicable;
         let snip = snippet_with_context(cx, e.span, cast_expr.span.ctxt(), "..", &mut app).0;
         // Fix #9884
@@ -31,17 +29,36 @@ pub(super) fn check<'tcx>(
                 .get(base.hir_id)
                 .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
         }) {
-            return;
+            return false;
         }
 
+        let suggestion = if msrv.meets(msrvs::RAW_REF_OP) {
+            let operator_kind = match mutability {
+                Mutability::Not => "const",
+                Mutability::Mut => "mut",
+            };
+            format!("&raw {operator_kind} {snip}")
+        } else {
+            let Some(std_or_core) = std_or_core(cx) else {
+                return false;
+            };
+            let macro_name = match mutability {
+                Mutability::Not => "addr_of",
+                Mutability::Mut => "addr_of_mut",
+            };
+            format!("{std_or_core}::ptr::{macro_name}!({snip})")
+        };
+
         span_lint_and_sugg(
             cx,
             BORROW_AS_PTR,
             expr.span,
             "borrow as raw pointer",
             "try",
-            format!("{std_or_core}::ptr::{macro_name}!({snip})"),
+            suggestion,
             Applicability::MachineApplicable,
         );
+        return true;
     }
+    false
 }
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index 8b884399f92..84fab9cb75f 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -574,13 +574,13 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for the usage of `&expr as *const T` or
-    /// `&mut expr as *mut T`, and suggest using `ptr::addr_of` or
-    /// `ptr::addr_of_mut` instead.
+    /// `&mut expr as *mut T`, and suggest using `&raw const` or
+    /// `&raw mut` instead.
     ///
     /// ### Why is this bad?
     /// This would improve readability and avoid creating a reference
     /// that points to an uninitialized value or unaligned place.
-    /// Read the `ptr::addr_of` docs for more information.
+    /// Read the `&raw` explanation in the Reference for more information.
     ///
     /// ### Example
     /// ```no_run
@@ -593,10 +593,10 @@ declare_clippy_lint! {
     /// Use instead:
     /// ```no_run
     /// let val = 1;
-    /// let p = std::ptr::addr_of!(val);
+    /// let p = &raw const val;
     ///
     /// let mut val_mut = 1;
-    /// let p_mut = std::ptr::addr_of_mut!(val_mut);
+    /// let p_mut = &raw mut val_mut;
     /// ```
     #[clippy::version = "1.60.0"]
     pub BORROW_AS_PTR,
@@ -806,10 +806,13 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
 
             as_underscore::check(cx, expr, cast_to_hir);
 
-            if self.msrv.meets(msrvs::PTR_FROM_REF) {
+            let was_borrow_as_ptr_emitted = if self.msrv.meets(msrvs::BORROW_AS_PTR) {
+                borrow_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir, &self.msrv)
+            } else {
+                false
+            };
+            if self.msrv.meets(msrvs::PTR_FROM_REF) && !was_borrow_as_ptr_emitted {
                 ref_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
-            } else if self.msrv.meets(msrvs::BORROW_AS_PTR) {
-                borrow_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
             }
         }
 
diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs
index 1eb7d54e133..f0381760709 100644
--- a/clippy_utils/src/msrvs.rs
+++ b/clippy_utils/src/msrvs.rs
@@ -19,9 +19,9 @@ macro_rules! msrv_aliases {
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
     1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY }
-    1,82,0 { IS_NONE_OR, REPEAT_N }
+    1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP }
     1,81,0 { LINT_REASONS_STABILIZATION }
-    1,80,0 { BOX_INTO_ITER}
+    1,80,0 { BOX_INTO_ITER }
     1,77,0 { C_STR_LITERALS }
     1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
     1,73,0 { MANUAL_DIV_CEIL }
diff --git a/tests/ui/borrow_and_ref_as_ptr.fixed b/tests/ui/borrow_and_ref_as_ptr.fixed
new file mode 100644
index 00000000000..2950b158deb
--- /dev/null
+++ b/tests/ui/borrow_and_ref_as_ptr.fixed
@@ -0,0 +1,11 @@
+// Make sure that `ref_as_ptr` is not emitted when `borrow_as_ptr` is.
+
+#![warn(clippy::ref_as_ptr, clippy::borrow_as_ptr)]
+
+fn f<T>(_: T) {}
+
+fn main() {
+    let mut val = 0;
+    f(&raw const val);
+    f(&raw mut val);
+}
diff --git a/tests/ui/borrow_and_ref_as_ptr.rs b/tests/ui/borrow_and_ref_as_ptr.rs
new file mode 100644
index 00000000000..19eb8f29233
--- /dev/null
+++ b/tests/ui/borrow_and_ref_as_ptr.rs
@@ -0,0 +1,11 @@
+// Make sure that `ref_as_ptr` is not emitted when `borrow_as_ptr` is.
+
+#![warn(clippy::ref_as_ptr, clippy::borrow_as_ptr)]
+
+fn f<T>(_: T) {}
+
+fn main() {
+    let mut val = 0;
+    f(&val as *const _);
+    f(&mut val as *mut i32);
+}
diff --git a/tests/ui/borrow_and_ref_as_ptr.stderr b/tests/ui/borrow_and_ref_as_ptr.stderr
new file mode 100644
index 00000000000..82a27af303c
--- /dev/null
+++ b/tests/ui/borrow_and_ref_as_ptr.stderr
@@ -0,0 +1,17 @@
+error: borrow as raw pointer
+  --> tests/ui/borrow_and_ref_as_ptr.rs:9:7
+   |
+LL |     f(&val as *const _);
+   |       ^^^^^^^^^^^^^^^^ help: try: `&raw const val`
+   |
+   = note: `-D clippy::borrow-as-ptr` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]`
+
+error: borrow as raw pointer
+  --> tests/ui/borrow_and_ref_as_ptr.rs:10:7
+   |
+LL |     f(&mut val as *mut i32);
+   |       ^^^^^^^^^^^^^^^^^^^^ help: try: `&raw mut val`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/borrow_as_ptr_raw_ref.fixed b/tests/ui/borrow_as_ptr_raw_ref.fixed
new file mode 100644
index 00000000000..d6842e60a3e
--- /dev/null
+++ b/tests/ui/borrow_as_ptr_raw_ref.fixed
@@ -0,0 +1,19 @@
+#![warn(clippy::borrow_as_ptr)]
+#![allow(clippy::useless_vec)]
+
+fn a() -> i32 {
+    0
+}
+
+#[clippy::msrv = "1.82"]
+fn main() {
+    let val = 1;
+    let _p = &raw const val;
+    let _p = &0 as *const i32;
+    let _p = &a() as *const i32;
+    let vec = vec![1];
+    let _p = &vec.len() as *const usize;
+
+    let mut val_mut = 1;
+    let _p_mut = &raw mut val_mut;
+}
diff --git a/tests/ui/borrow_as_ptr_raw_ref.rs b/tests/ui/borrow_as_ptr_raw_ref.rs
new file mode 100644
index 00000000000..3c9daed18f1
--- /dev/null
+++ b/tests/ui/borrow_as_ptr_raw_ref.rs
@@ -0,0 +1,19 @@
+#![warn(clippy::borrow_as_ptr)]
+#![allow(clippy::useless_vec)]
+
+fn a() -> i32 {
+    0
+}
+
+#[clippy::msrv = "1.82"]
+fn main() {
+    let val = 1;
+    let _p = &val as *const i32;
+    let _p = &0 as *const i32;
+    let _p = &a() as *const i32;
+    let vec = vec![1];
+    let _p = &vec.len() as *const usize;
+
+    let mut val_mut = 1;
+    let _p_mut = &mut val_mut as *mut i32;
+}
diff --git a/tests/ui/borrow_as_ptr_raw_ref.stderr b/tests/ui/borrow_as_ptr_raw_ref.stderr
new file mode 100644
index 00000000000..5611fcae8d4
--- /dev/null
+++ b/tests/ui/borrow_as_ptr_raw_ref.stderr
@@ -0,0 +1,17 @@
+error: borrow as raw pointer
+  --> tests/ui/borrow_as_ptr_raw_ref.rs:11:14
+   |
+LL |     let _p = &val as *const i32;
+   |              ^^^^^^^^^^^^^^^^^^ help: try: `&raw const val`
+   |
+   = note: `-D clippy::borrow-as-ptr` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]`
+
+error: borrow as raw pointer
+  --> tests/ui/borrow_as_ptr_raw_ref.rs:18:18
+   |
+LL |     let _p_mut = &mut val_mut as *mut i32;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&raw mut val_mut`
+
+error: aborting due to 2 previous errors
+