about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs20
-rw-r--r--src/test/ui/box/issue-95036.rs22
2 files changed, 35 insertions, 7 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 2b8fa3be56d..17cfb6c5dfb 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -441,11 +441,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     .find(|elem| matches!(elem.1, mir::ProjectionElem::Deref))
                 {
                     base = elem.0 + 1;
-                    self.codegen_consume(
+                    let cg_base = self.codegen_consume(
                         bx,
                         mir::PlaceRef { projection: &place_ref.projection[..elem.0], ..place_ref },
-                    )
-                    .deref(bx.cx())
+                    );
+
+                    // a box with a non-zst allocator should not be directly dereferenced
+                    if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
+                        let ptr = cg_base.extract_field(bx, 0).extract_field(bx, 0);
+
+                        ptr.deref(bx.cx())
+                    } else {
+                        cg_base.deref(bx.cx())
+                    }
                 } else {
                     bug!("using operand local {:?} as place", place_ref);
                 }
@@ -454,10 +462,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         for elem in place_ref.projection[base..].iter() {
             cg_base = match elem.clone() {
                 mir::ProjectionElem::Deref => {
-                    // custom allocators can change box's abi, making it unable to be derefed directly
-                    if cg_base.layout.ty.is_box()
-                        && matches!(cg_base.layout.abi, Abi::Aggregate { .. } | Abi::Uninhabited)
-                    {
+                    // a box with a non-zst allocator should not be directly dereferenced
+                    if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
                         let ptr = cg_base.project_field(bx, 0).project_field(bx, 0);
 
                         bx.load_operand(ptr).deref(bx.cx())
diff --git a/src/test/ui/box/issue-95036.rs b/src/test/ui/box/issue-95036.rs
new file mode 100644
index 00000000000..c2d4275aa49
--- /dev/null
+++ b/src/test/ui/box/issue-95036.rs
@@ -0,0 +1,22 @@
+// compile-flags: -O
+// build-pass
+
+#![feature(allocator_api, bench_black_box)]
+
+#[inline(never)]
+pub fn by_ref(node: &mut Box<[u8; 1], &std::alloc::Global>) {
+    node[0] = 9u8;
+}
+
+pub fn main() {
+    let mut node = Box::new_in([5u8], &std::alloc::Global);
+    node[0] = 7u8;
+
+    std::hint::black_box(node);
+
+    let mut node = Box::new_in([5u8], &std::alloc::Global);
+
+    by_ref(&mut node);
+
+    std::hint::black_box(node);
+}