From 46dadfc1422ce98f4814441154d5fa765caeffe9 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Fri, 25 Mar 2022 23:14:30 -0700 Subject: [PATCH 1/4] widen special case on deref to all non-zst allocators --- compiler/rustc_codegen_ssa/src/mir/place.rs | 6 ++---- src/test/ui/box/issue-95036.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/box/issue-95036.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 2b8fa3be56d..12cdc2b2c7d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -454,10 +454,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, 0).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..e062599d74c --- /dev/null +++ b/src/test/ui/box/issue-95036.rs @@ -0,0 +1,10 @@ +// compile-flags: -O +// compile-pass + +#![feature(allocator_api, bench_black_box)] + +pub fn main() { + let mut node = Box::new_in([5u8], &std::alloc::Global); + node[0] = 7u8; + std::hint::black_box(node); +} From e9f08e709d471988fcf163779dec430cdcbf1193 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Fri, 25 Mar 2022 23:46:37 -0700 Subject: [PATCH 2/4] fix wrong header command --- src/test/ui/box/issue-95036.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/box/issue-95036.rs b/src/test/ui/box/issue-95036.rs index e062599d74c..e55a10af3d6 100644 --- a/src/test/ui/box/issue-95036.rs +++ b/src/test/ui/box/issue-95036.rs @@ -1,5 +1,5 @@ // compile-flags: -O -// compile-pass +// build-pass #![feature(allocator_api, bench_black_box)] From ece64ed3f56f811f2122dc3dcbff85bf47f8fee3 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Sat, 26 Mar 2022 00:08:51 -0700 Subject: [PATCH 3/4] check the the right field --- compiler/rustc_codegen_ssa/src/mir/place.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 12cdc2b2c7d..be8b0f3c991 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -455,7 +455,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_base = match elem.clone() { mir::ProjectionElem::Deref => { // a box with a non-zst allocator should not be directly dereferenced - if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 0).is_zst() { + 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()) From 09ccc63624f627e44f13c480c934b4d28a845258 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Sun, 27 Mar 2022 13:35:29 -0700 Subject: [PATCH 4/4] fix other source of box deref --- compiler/rustc_codegen_ssa/src/mir/place.rs | 14 +++++++++++--- src/test/ui/box/issue-95036.rs | 12 ++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index be8b0f3c991..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); } diff --git a/src/test/ui/box/issue-95036.rs b/src/test/ui/box/issue-95036.rs index e55a10af3d6..c2d4275aa49 100644 --- a/src/test/ui/box/issue-95036.rs +++ b/src/test/ui/box/issue-95036.rs @@ -3,8 +3,20 @@ #![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); }