about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/casts/borrow_as_ptr.rs29
-rw-r--r--clippy_lints/src/casts/mod.rs7
-rw-r--r--tests/ui/borrow_as_ptr.fixed8
-rw-r--r--tests/ui/borrow_as_ptr.rs8
-rw-r--r--tests/ui/borrow_as_ptr.stderr14
5 files changed, 47 insertions, 19 deletions
diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs
index 67aa33ca06c..6057144bc6a 100644
--- a/clippy_lints/src/casts/borrow_as_ptr.rs
+++ b/clippy_lints/src/casts/borrow_as_ptr.rs
@@ -1,11 +1,13 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::Msrv;
-use clippy_utils::source::snippet_with_context;
+use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
+use clippy_utils::sugg::has_enclosing_paren;
 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;
 use rustc_middle::ty::adjustment::Adjust;
+use rustc_span::BytePos;
 
 use super::BORROW_AS_PTR;
 
@@ -32,12 +34,21 @@ pub(super) fn check<'tcx>(
             return false;
         }
 
-        let suggestion = if msrv.meets(msrvs::RAW_REF_OP) {
+        let (suggestion, span) = if msrv.meets(msrvs::RAW_REF_OP) {
             let operator_kind = match mutability {
                 Mutability::Not => "const",
                 Mutability::Mut => "mut",
             };
-            format!("&raw {operator_kind} {snip}")
+            // Make sure that the span to be replaced doesn't include parentheses, that could break the
+            // suggestion.
+            let span = if has_enclosing_paren(snippet_with_applicability(cx, expr.span, "", &mut app)) {
+                expr.span
+                    .with_lo(expr.span.lo() + BytePos(1))
+                    .with_hi(expr.span.hi() - BytePos(1))
+            } else {
+                expr.span
+            };
+            (format!("&raw {operator_kind} {snip}"), span)
         } else {
             let Some(std_or_core) = std_or_core(cx) else {
                 return false;
@@ -46,18 +57,10 @@ pub(super) fn check<'tcx>(
                 Mutability::Not => "addr_of",
                 Mutability::Mut => "addr_of_mut",
             };
-            format!("{std_or_core}::ptr::{macro_name}!({snip})")
+            (format!("{std_or_core}::ptr::{macro_name}!({snip})"), expr.span)
         };
 
-        span_lint_and_sugg(
-            cx,
-            BORROW_AS_PTR,
-            expr.span,
-            "borrow as raw pointer",
-            "try",
-            suggestion,
-            Applicability::MachineApplicable,
-        );
+        span_lint_and_sugg(cx, BORROW_AS_PTR, span, "borrow as raw pointer", "try", suggestion, app);
         return true;
     }
     false
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index c64c0e15144..d90cf124fe4 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -836,11 +836,8 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             as_underscore::check(cx, expr, cast_to_hir);
             as_pointer_underscore::check(cx, cast_to, cast_to_hir);
 
-            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
-            };
+            let was_borrow_as_ptr_emitted = self.msrv.meets(msrvs::BORROW_AS_PTR)
+                && borrow_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir, &self.msrv);
             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);
             }
diff --git a/tests/ui/borrow_as_ptr.fixed b/tests/ui/borrow_as_ptr.fixed
index 289a5ef38b8..5365f3dd443 100644
--- a/tests/ui/borrow_as_ptr.fixed
+++ b/tests/ui/borrow_as_ptr.fixed
@@ -16,4 +16,12 @@ fn main() {
 
     let mut val_mut = 1;
     let _p_mut = std::ptr::addr_of_mut!(val_mut);
+
+    let mut x: [i32; 2] = [42, 43];
+    let _raw = std::ptr::addr_of_mut!(x[1]).wrapping_offset(-1);
+}
+
+fn issue_13882() {
+    let mut x: [i32; 2] = [42, 43];
+    let _raw = (&raw mut x[1]).wrapping_offset(-1);
 }
diff --git a/tests/ui/borrow_as_ptr.rs b/tests/ui/borrow_as_ptr.rs
index b5328cb22dc..261894f1341 100644
--- a/tests/ui/borrow_as_ptr.rs
+++ b/tests/ui/borrow_as_ptr.rs
@@ -16,4 +16,12 @@ fn main() {
 
     let mut val_mut = 1;
     let _p_mut = &mut val_mut as *mut i32;
+
+    let mut x: [i32; 2] = [42, 43];
+    let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1);
+}
+
+fn issue_13882() {
+    let mut x: [i32; 2] = [42, 43];
+    let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1);
 }
diff --git a/tests/ui/borrow_as_ptr.stderr b/tests/ui/borrow_as_ptr.stderr
index ea618b06e2c..4595fa4f248 100644
--- a/tests/ui/borrow_as_ptr.stderr
+++ b/tests/ui/borrow_as_ptr.stderr
@@ -13,5 +13,17 @@ error: borrow as raw pointer
 LL |     let _p_mut = &mut val_mut as *mut i32;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(val_mut)`
 
-error: aborting due to 2 previous errors
+error: borrow as raw pointer
+  --> tests/ui/borrow_as_ptr.rs:21:16
+   |
+LL |     let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(x[1])`
+
+error: borrow as raw pointer
+  --> tests/ui/borrow_as_ptr.rs:26:17
+   |
+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