Change:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --Only when building with or do I trigger this issue. Found while working on . Compile test that triggers the issue: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
modify labels: +A-allocators +A-lto
claim
claim
Hey thanks for looking into this bug (and for fixing my last reports as well :)). I've figured out some more information since first posting this. I'm able to reproduce the bug in a single crate when compiling with 1 and further minimized the triggering code: The bug seems to be specifically triggered when the allocator is non zero-sized, it doesn't matter whether it's a reference or not. Additionally if the boxed type is a struct or tuple, only accessing past the first non-zero field triggers the bug. Attempting to disassemble the bitcode dumped with with gives the same error, unless I pass the flag which causes the disassembly to succeed. The offending store instruction is encoded as follows: Unfortunately the flag strips all pointer types from the input, turning them to in the output, so I do not know what the original type was that is causing the issue. Using the following which doesn't trigger the issue: without gives:
Thanks for the info and minimized code! That's gonna make this easier.
I still don't know how this actually happens, I just know that the change in fixes it. I suspect it's some code assuming that a wide box is always a wide pointer, but I don't know where...
I think you're right about that assumption, using a wide pointer in the box has no issues:

Discussion:
.find(|elem| matches!(elem.1, mir::ProjectionElem::Deref)) { base = elem.0 + 1; <del> self.codegen_consume( </del> <ins> let cg_base = self.codegen_consume( </ins> bx, mir::PlaceRef { projection: &place_ref.projection[..elem.0], ..place_ref }, <del> ) .deref(bx.cx()) </del> <ins> ); // 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()) } </ins> } else { bug!("using operand local {:?} as place", place_ref); }

for elem in place_ref.projection[base..].iter() { cg_base = match elem.clone() { mir::ProjectionElem::Deref => { <del> // 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) { </del> <ins> // 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() { </ins> let ptr = cg_base.project_field(bx, 0).project_field(bx, 0); bx.load_operand(ptr).deref(bx.cx())

<ins> // 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); } </ins>