about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-05-09 06:04:40 +0200
committerGitHub <noreply@github.com>2024-05-09 06:04:40 +0200
commit48b1e1a280284766ab50720cb71a27451c8a512b (patch)
tree10d47ba6a33fc3857dfc987b593ee1955bafd3fe
parentc49436df4c7d59af58a11b9bf30292853ef48008 (diff)
parent0ca1a94b2bd58d19a1bd492300abd5bffe5263fb (diff)
downloadrust-48b1e1a280284766ab50720cb71a27451c8a512b.tar.gz
rust-48b1e1a280284766ab50720cb71a27451c8a512b.zip
Rollup merge of #124908 - saethlin:ref-casting_bigger_place_projection, r=fee1-dead
Handle field projections like slice indexing in invalid_reference_casting

r? `@Urgau`

I saw the implementation in https://github.com/rust-lang/rust/pull/124761, and I was wondering if we also need to handle field access. We do. Without this PR, we get this errant diagnostic:
```
error: casting references to a bigger memory layout than the backing allocation is undefined behavior, even if the reference is unused
  --> /home/ben/rust/tests/ui/lint/reference_casting.rs:262:18
   |
LL |         let r = &mut v.0;
   |                      --- backing allocation comes from here
LL |         let ptr = r as *mut i32 as *mut Vec3<i32>;
   |                   ------------------------------- casting happend here
LL |         unsafe { *ptr = Vec3(0, 0, 0) }
   |                  ^^^^^^^^^^^^^^^^^^^^
   |
   = note: casting from `i32` (4 bytes) to `Vec3<i32>` (12 bytes)
```
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs3
-rw-r--r--tests/ui/lint/reference_casting.rs6
2 files changed, 8 insertions, 1 deletions
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 63d55a73a98..b80e90c25a3 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -202,7 +202,8 @@ fn is_cast_to_bigger_memory_layout<'tcx>(
 
     // if the current expr looks like this `&mut expr[index]` then just looking
     // at `expr[index]` won't give us the underlying allocation, so we just skip it
-    if let ExprKind::Index(..) = e_alloc.kind {
+    // the same logic applies field access like `&mut expr.field`
+    if let ExprKind::Index(..) | ExprKind::Field(..) = e_alloc.kind {
         return None;
     }
 
diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs
index 3d0c36ca118..87a682249b0 100644
--- a/tests/ui/lint/reference_casting.rs
+++ b/tests/ui/lint/reference_casting.rs
@@ -255,6 +255,12 @@ unsafe fn bigger_layout() {
         let a3 = a2 as *mut u64;
         unsafe { *a3 = 3 };
     }
+
+    unsafe fn field_access(v: &mut Vec3<i32>) {
+        let r = &mut v.0;
+        let ptr = r as *mut i32 as *mut Vec3<i32>;
+        unsafe { *ptr = Vec3(0, 0, 0) }
+    }
 }
 
 const RAW_PTR: *mut u8 = 1 as *mut u8;