Change:
On stable, beta, and nightly, the follow code prints followed by : CC
This is probably for drop flags, in which case it should get fixed by
Reduced:
where would there be a drop flag here?
My point isn't that there is, but that the code assumes all trait objects have drop flags. I could be wrong though, it might be a bug in the alignment logic.
Not fixed by , will have to investigate further.
Uhhhh, the computation starts with: Which is completely wrong, because you want no trailing padding, i.e. should be . EDIT: getting a field pointer might also be broken, needs looking into. EDIT2: to handle the "minimum size" needed to compute the field offset, so that works.

Discussion:
/// Returns true if the type is represented as a pair of immediates. pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { <del> let tcx = ccx.tcx(); let layout = tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| { match ty.layout(&infcx) { Ok(layout) => layout, Err(err) => { bug!("type_is_imm_pair: layout for `{:?}` failed: {}", ty, err); } } }); match *layout { </del> <ins> match *ccx.layout_of(ty) { </ins> Layout::FatPointer { .. } => true, Layout::Univariant { ref variant, .. } => { // There must be only 2 fields.

TypeOfDepthLock(self.local()) } <ins> pub fn layout_of(&self, ty: Ty<'tcx>) -> &'tcx ty::layout::Layout { self.tcx().normalizing_infer_ctxt(traits::Reveal::All).enter(|infcx| { ty.layout(&infcx).unwrap_or_else(|e| { bug!("failed to get layout for `{}`: {}", ty, e); }) }) } </ins> pub fn check_overflow(&self) -> bool { self.shared.check_overflow }

ty::TyStruct(def, substs) => { let ccx = bcx.ccx(); // First get the size of all statically known fields. <del> // Don't use type_of::sizing_type_of because that expects t to be sized. </del> <ins> // Don't use type_of::sizing_type_of because that expects t to be sized, // and it also rounds up to alignment, which we want to avoid, // as the unsized field's alignment could be smaller. </ins> assert!(!t.is_simd()); <del> let repr = adt::represent_type(ccx, t); let sizing_type = adt::sizing_type_of(ccx, &repr, true); debug!("DST {} sizing_type: {:?}", t, sizing_type); let sized_size = llsize_of_alloc(ccx, sizing_type); let sized_align = llalign_of_min(ccx, sizing_type); </del> <ins> let layout = ccx.layout_of(t); debug!("DST {} layout: {:?}", t, layout); let (sized_size, sized_align) = match *layout { ty::layout::Layout::Univariant { ref variant, .. } => { (variant.min_size().bytes(), variant.align.abi()) } _ => { bug!("size_and_align_of_dst: expcted Univariant for `{}`, found {:#?}", t, layout); } }; </ins> debug!("DST {} statically sized prefix size: {} align: {}", t, sized_size, sized_align); let sized_size = C_uint(ccx, sized_size);

use adt; use common::*; use machine; <del> use rustc::traits::Reveal; </del> use rustc::ty::{self, Ty, TypeFoldable}; use type_::Type;

cx.llsizingtypes().borrow_mut().insert(t, llsizingty); // FIXME(eddyb) Temporary sanity check for ty::layout. <del> let layout = cx.tcx().normalizing_infer_ctxt(Reveal::All).enter(|infcx| { t.layout(&infcx) }); match layout { Ok(layout) => { if !type_is_sized(cx.tcx(), t) { if !layout.is_unsized() { bug!("layout should be unsized for type `{}` / {:#?}", t, layout); } // Unsized types get turned into a fat pointer for LLVM. return llsizingty; } let r = layout.size(&cx.tcx().data_layout).bytes(); let l = machine::llsize_of_alloc(cx, llsizingty); if r != l { bug!("size differs (rustc: {}, llvm: {}) for type `{}` / {:#?}", r, l, t, layout); } let r = layout.align(&cx.tcx().data_layout).abi(); let l = machine::llalign_of_min(cx, llsizingty) as u64; if r != l { bug!("align differs (rustc: {}, llvm: {}) for type `{}` / {:#?}", r, l, t, layout); } } Err(e) => { bug!("failed to get layout for `{}`: {}", t, e); </del> <ins> let layout = cx.layout_of(t); if !type_is_sized(cx.tcx(), t) { if !layout.is_unsized() { bug!("layout should be unsized for type `{}` / {:#?}", t, layout); </ins> } <ins> // Unsized types get turned into a fat pointer for LLVM. return llsizingty; } let r = layout.size(&cx.tcx().data_layout).bytes(); let l = machine::llsize_of_alloc(cx, llsizingty); if r != l { bug!("size differs (rustc: {}, llvm: {}) for type `{}` / {:#?}", r, l, t, layout); </ins> } <ins> let r = layout.align(&cx.tcx().data_layout).abi(); let l = machine::llalign_of_min(cx, llsizingty) as u64; if r != l { bug!("align differs (rustc: {}, llvm: {}) for type `{}` / {:#?}", r, l, t, layout); } </ins> llsizingty }

<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. use std::mem; struct Foo<T: ?Sized> { a: i64, b: bool, c: T, } fn main() { let foo: &Foo<i32> = &Foo { a: 1, b: false, c: 2i32 }; let foo_unsized: &Foo<Send> = foo; assert_eq!(mem::size_of_val(foo), mem::size_of_val(foo_unsized)); } </ins>