about summary refs log tree commit diff
path: root/compiler/rustc_lint/src/reference_casting.rs
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2023-08-22 15:41:07 +0200
committerUrgau <urgau@numericable.fr>2023-08-22 15:47:29 +0200
commit7ee77b5d1b91adf4c683d0d871015fe68ebca9ea (patch)
tree2ecc51a3018c338eece2a707e6a79b6b199176e3 /compiler/rustc_lint/src/reference_casting.rs
parentb4d09f3b811cf9bb73288c054557f2c2436bb37d (diff)
downloadrust-7ee77b5d1b91adf4c683d0d871015fe68ebca9ea.tar.gz
rust-7ee77b5d1b91adf4c683d0d871015fe68ebca9ea.zip
Add support for ptr::write for the invalid_reference_casting lint
Diffstat (limited to 'compiler/rustc_lint/src/reference_casting.rs')
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs64
1 files changed, 47 insertions, 17 deletions
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 2577cabb3f0..883f6242b56 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -56,20 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        // &mut <expr>
-        let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind {
-            expr
-        // <expr> = ...
-        } else if let ExprKind::Assign(expr, _, _) = expr.kind {
-            expr
-        // <expr> += ...
-        } else if let ExprKind::AssignOp(_, expr, _) = expr.kind {
-            expr
-        } else {
-            return;
-        };
-
-        let ExprKind::Unary(UnOp::Deref, e) = &inner.kind else {
+        let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else {
             return;
         };
 
@@ -86,15 +73,58 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
         cx.emit_spanned_lint(
             INVALID_REFERENCE_CASTING,
             expr.span,
-            if matches!(expr.kind, ExprKind::AddrOf(..)) {
-                InvalidReferenceCastingDiag::BorrowAsMut { orig_cast }
-            } else {
+            if is_assignment {
                 InvalidReferenceCastingDiag::AssignToRef { orig_cast }
+            } else {
+                InvalidReferenceCastingDiag::BorrowAsMut { orig_cast }
             },
         );
     }
 }
 
+fn is_operation_we_care_about<'tcx>(
+    cx: &LateContext<'tcx>,
+    e: &'tcx Expr<'tcx>,
+) -> Option<(bool, &'tcx Expr<'tcx>)> {
+    fn deref_assign_or_addr_of<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(bool, &'tcx Expr<'tcx>)> {
+        // &mut <expr>
+        let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind {
+            expr
+        // <expr> = ...
+        } else if let ExprKind::Assign(expr, _, _) = expr.kind {
+            expr
+        // <expr> += ...
+        } else if let ExprKind::AssignOp(_, expr, _) = expr.kind {
+            expr
+        } else {
+            return None;
+        };
+
+        if let ExprKind::Unary(UnOp::Deref, e) = &inner.kind {
+            Some((!matches!(expr.kind, ExprKind::AddrOf(..)), e))
+        } else {
+            None
+        }
+    }
+
+    fn ptr_write<'tcx>(
+        cx: &LateContext<'tcx>,
+        e: &'tcx Expr<'tcx>,
+    ) -> Option<(bool, &'tcx Expr<'tcx>)> {
+        if let ExprKind::Call(path, [arg_ptr, _arg_val]) = e.kind
+            && let ExprKind::Path(ref qpath) = path.kind
+            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+            && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_write | sym::ptr_write_volatile | sym::ptr_write_unaligned))
+        {
+            Some((true, arg_ptr))
+        } else {
+            None
+        }
+    }
+
+    deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e))
+}
+
 fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
     let e = e.peel_blocks();