From 1844381ad024f322f7427d03ac261d131eb0e86b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 9 Feb 2017 08:38:01 +0100 Subject: [PATCH] compute the offset of dst fields by checking the vtable --- src/lvalue.rs | 11 ++++++++++- src/terminator/intrinsic.rs | 2 +- tests/run-pass/dst-field-align.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 tests/run-pass/dst-field-align.rs diff --git a/src/lvalue.rs b/src/lvalue.rs index d54c27904763..2cce67689d72 100644 --- a/src/lvalue.rs +++ b/src/lvalue.rs @@ -214,7 +214,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { _ => bug!("field access on non-product type: {:?}", base_layout), }; - let ptr = base_ptr.offset(offset.bytes()); + let offset = match base_extra { + LvalueExtra::Vtable(tab) => { + let (_, align) = self.size_and_align_of_dst(base_ty, Value::ByValPair(PrimVal::Ptr(base_ptr), PrimVal::Ptr(tab)))?; + // magical formula taken from rustc + (offset.bytes() + (align - 1)) & (-(align as i64) as u64) + } + _ => offset.bytes(), + }; + + let ptr = base_ptr.offset(offset); if packed { let size = self.type_size(field_ty)?.expect("packed struct must be sized"); diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 811ae7888d72..44a636997d95 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -405,7 +405,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok(()) } - fn size_and_align_of_dst( + pub fn size_and_align_of_dst( &self, ty: ty::Ty<'tcx>, value: Value, diff --git a/tests/run-pass/dst-field-align.rs b/tests/run-pass/dst-field-align.rs new file mode 100644 index 000000000000..ce3fb82cb3f2 --- /dev/null +++ b/tests/run-pass/dst-field-align.rs @@ -0,0 +1,30 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +struct Foo { + a: u16, + b: T +} + +trait Bar { + fn get(&self) -> usize; +} + +impl Bar for usize { + fn get(&self) -> usize { *self } +} + +fn main() { + let f : Foo = Foo { a: 0, b: 11 }; + let f : &Foo = &f; + assert_eq!(f.b.get(), 11); +}