about summary refs log tree commit diff
path: root/compiler/rustc_lint/src/ptr_nulls.rs
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2023-07-13 14:13:08 +0200
committerUrgau <urgau@numericable.fr>2023-08-03 10:52:15 +0200
commit4b3dadbe5a9f3dd06932a9099abd37bae751cdd3 (patch)
tree194edafcf22e303b1e9b1fa8aaafa097b01ae24f /compiler/rustc_lint/src/ptr_nulls.rs
parent0b9529cca39d86138066012e85cae96ba4a7c253 (diff)
downloadrust-4b3dadbe5a9f3dd06932a9099abd37bae751cdd3.tar.gz
rust-4b3dadbe5a9f3dd06932a9099abd37bae751cdd3.zip
Also lint on cast/cast_mut and ptr::from_mut/ptr::from_ref
Diffstat (limited to 'compiler/rustc_lint/src/ptr_nulls.rs')
-rw-r--r--compiler/rustc_lint/src/ptr_nulls.rs52
1 files changed, 36 insertions, 16 deletions
diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs
index b2138c42224..64b86fec46b 100644
--- a/compiler/rustc_lint/src/ptr_nulls.rs
+++ b/compiler/rustc_lint/src/ptr_nulls.rs
@@ -31,25 +31,45 @@ declare_lint! {
 
 declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS]);
 
-fn incorrect_check<'a>(cx: &LateContext<'a>, expr: &Expr<'_>) -> Option<PtrNullChecksDiag<'a>> {
-    let mut expr = expr.peel_blocks();
+/// This function detects and returns the original expression from a series of consecutive casts,
+/// ie. `(my_fn as *const _ as *mut _).cast_mut()` would return the expression for `my_fn`.
+fn ptr_cast_chain<'a>(cx: &'a LateContext<'_>, mut e: &'a Expr<'a>) -> Option<&'a Expr<'a>> {
     let mut had_at_least_one_cast = false;
-    while let ExprKind::Cast(cast_expr, cast_ty) = expr.kind
-            && let TyKind::Ptr(_) = cast_ty.kind {
-        expr = cast_expr.peel_blocks();
-        had_at_least_one_cast = true;
+    loop {
+        e = e.peel_blocks();
+        e = if let ExprKind::Cast(expr, t) = e.kind
+            && let TyKind::Ptr(_) = t.kind {
+            had_at_least_one_cast = true;
+            expr
+        } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
+            && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
+            && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_cast | sym::ptr_cast_mut)) {
+            had_at_least_one_cast = true;
+            expr
+        } else if let ExprKind::Call(path, [arg]) = 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_from_ref | sym::ptr_from_mut)) {
+            had_at_least_one_cast = true;
+            arg
+        } else if had_at_least_one_cast {
+            return Some(e);
+        } else {
+            return None;
+        };
     }
-    if !had_at_least_one_cast {
-        None
+}
+
+fn incorrect_check<'a>(cx: &LateContext<'a>, expr: &Expr<'_>) -> Option<PtrNullChecksDiag<'a>> {
+    let expr = ptr_cast_chain(cx, expr)?;
+
+    let orig_ty = cx.typeck_results().expr_ty(expr);
+    if orig_ty.is_fn() {
+        Some(PtrNullChecksDiag::FnPtr)
+    } else if orig_ty.is_ref() {
+        Some(PtrNullChecksDiag::Ref { orig_ty, label: expr.span })
     } else {
-        let orig_ty = cx.typeck_results().expr_ty(expr);
-        if orig_ty.is_fn() {
-            Some(PtrNullChecksDiag::FnPtr)
-        } else if orig_ty.is_ref() {
-            Some(PtrNullChecksDiag::Ref { orig_ty, label: expr.span })
-        } else {
-            None
-        }
+        None
     }
 }