diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 9338044e534..60f5a75d46c 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -627,6 +627,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let src_pointee_ty = pointee_type(src_ty).unwrap(); let dest_pointee_ty = pointee_type(dest_ty).unwrap(); + // A -> A conversion + let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails(src_pointee_ty, dest_pointee_ty); + match (&src_pointee_ty.sty, &dest_pointee_ty.sty) { (&ty::TyArray(_, length), &ty::TySlice(_)) => { self.memory.write_usize(extra, length as u64)?; @@ -881,7 +884,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { use rustc::mir::repr::ProjectionElem::*; match proj.elem { - Field(field, _) => { + Field(field, field_ty) => { use rustc::ty::layout::Layout::*; let variant = match *base_layout { Univariant { ref variant, .. } => variant, @@ -901,7 +904,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { }; let offset = variant.field_offset(field.index()).bytes(); - base.ptr.offset(offset as isize) + let ptr = base.ptr.offset(offset as isize); + match (&field_ty.sty, base.extra) { + (&ty::TyTrait(_), extra @ LvalueExtra::Vtable(_)) => return Ok(Lvalue { + ptr: ptr, + extra: extra, + }), + (&ty::TyTrait(_), _) => bug!("trait field without vtable"), + _ => ptr, + } }, Downcast(_, variant) => { @@ -922,6 +933,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Deref => { let pointee_ty = pointee_type(base_ty).expect("Deref of non-pointer"); + let pointee_ty = self.tcx.struct_tail(pointee_ty); let ptr = self.memory.read_ptr(base.ptr)?; let extra = match pointee_ty.sty { ty::TySlice(_) | ty::TyStr => { diff --git a/tests/run-pass/traits.rs b/tests/run-pass/traits.rs index acef02d2bc8..e3d93957fd9 100644 --- a/tests/run-pass/traits.rs +++ b/tests/run-pass/traits.rs @@ -10,9 +10,14 @@ impl Trait for Struct { } } +struct Foo(T); + fn main() { let y: &Trait = &Struct(42); y.method(); + let x: Foo = Foo(Struct(42)); + let y: &Foo = &x; + y.0.method(); /* let x: Box i32> = Box::new(|x| x * 2); assert_eq!(x(21), 42);