Change:
Configure flags (I suspect is the only relevant one, though of course I recommend passing for bootstrapping): Steps to reproduce:
indicates that this was injected by (PR ); cc
I didn't fully check the validity of the rest of the code, I thought it was correct modulo initial starting data. Maybe it doesn't round up to the struct's own alignment? Resulting in a smaller size passed to jemalloc.
Stepping through a variant of the code, I'm certainly observing a discrepancy where we pass a small size to allocate and a larger size to deallocate.
Code: some data from : In particular, the input to is 128, while the at deallocation is claimed to be 136.
(note that the code I posted is not printing the actually relevant sizes, since it seems to me like our issue is with the size of the array in the , but that code is only printing the size of the itself. Whoops.) After fixing that, reports 112 for the size of the and the ; of course the actually value being allocated is an , which adds an additional pair of fields to the structure, so we end up with 112 + 16 = 128. Not sure yet where the 136 is coming from; perhaps we are adding another 8 somewhere?
On the other hand, manually breaking on (instantiated to ), and walking through it indicates that it is definitely returning 136. Here's the LLVM IR for the generated code for that routine: (I haven't yet validated where its getting 8 and 24 from in that computation, but if nothing else:
Hmm maybe we are double-counting the contribution when we calculate ?
In particular, where we recurse: that is recurring on the last field that is immediately present in the struct, causing us to add 8. But the already computed prefix size (24 in this case) actually includes_ the prefix that is in that last field, I think
Does instead of the last field work? If the intention is to find the nested-most field, that is. Although, I'm not entirely sure that would work well due to alignment. Come to think of it, is this because includes nested prefixes, and we don't want that? It should be easy enough to completely ignore the last field, instead of it'd be
yeah that sounds promising (that is, to not use at all) Update: Initial results look good, at least in terms of fixing this particular bug.

Discussion:
let layout = ccx.layout_of(t); debug!("DST {} layout: {:?}", t, layout); <ins> // Returns size in bytes of all fields except the last one // (we will be recursing on the last one). fn local_prefix_bytes(variant: &ty::layout::Struct) -> u64 { let fields = variant.offset_after_field.len(); if fields > 1 { variant.offset_after_field[fields - 2].bytes() } else { 0 } } </ins> let (sized_size, sized_align) = match *layout { ty::layout::Layout::Univariant { ref variant, .. } => { <del> (variant.min_size().bytes(), variant.align.abi()) </del> <ins> (local_prefix_bytes(variant), variant.align.abi()) </ins> } _ => { bug!("size_and_align_of_dst: expcted Univariant for `{}`, found {:#?}",

<ins> // Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Issue 36278: On an unsized struct with >1 level of nontrivial // nesting, ensure we are computing dynamic size of prefix correctly. use std::mem; const SZ: usize = 100; struct P<T: ?Sized>([u8; SZ], T); type Ack<T> = P<P<T>>; fn main() { let size_of_sized; let size_of_unsized; let x: Box<Ack<[u8; 0]>> = Box::new(P([0; SZ], P([0; SZ], [0; 0]))); size_of_sized = mem::size_of_val::<Ack<_>>(&x); let y: Box<Ack<[u8   ]>> = x; size_of_unsized = mem::size_of_val::<Ack<_>>(&y); assert_eq!(size_of_sized, size_of_unsized); } </ins>