compute the offset of dst fields by checking the vtable

This commit is contained in:
Oliver Schneider 2017-02-09 08:38:01 +01:00
parent 4beb774caa
commit 1844381ad0
3 changed files with 41 additions and 2 deletions

View file

@ -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");

View file

@ -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,

View file

@ -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 <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.
#![allow(dead_code)]
struct Foo<T: ?Sized> {
a: u16,
b: T
}
trait Bar {
fn get(&self) -> usize;
}
impl Bar for usize {
fn get(&self) -> usize { *self }
}
fn main() {
let f : Foo<usize> = Foo { a: 0, b: 11 };
let f : &Foo<Bar> = &f;
assert_eq!(f.b.get(), 11);
}