enable A<Struct> -> A<Trait> downcasting
This commit is contained in:
parent
d5e44712a4
commit
145cbf844c
2 changed files with 19 additions and 2 deletions
|
@ -627,6 +627,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
let src_pointee_ty = pointee_type(src_ty).unwrap();
|
let src_pointee_ty = pointee_type(src_ty).unwrap();
|
||||||
let dest_pointee_ty = pointee_type(dest_ty).unwrap();
|
let dest_pointee_ty = pointee_type(dest_ty).unwrap();
|
||||||
|
|
||||||
|
// A<Struct> -> A<Trait> 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) {
|
match (&src_pointee_ty.sty, &dest_pointee_ty.sty) {
|
||||||
(&ty::TyArray(_, length), &ty::TySlice(_)) => {
|
(&ty::TyArray(_, length), &ty::TySlice(_)) => {
|
||||||
self.memory.write_usize(extra, length as u64)?;
|
self.memory.write_usize(extra, length as u64)?;
|
||||||
|
@ -881,7 +884,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
|
|
||||||
use rustc::mir::repr::ProjectionElem::*;
|
use rustc::mir::repr::ProjectionElem::*;
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
Field(field, _) => {
|
Field(field, field_ty) => {
|
||||||
use rustc::ty::layout::Layout::*;
|
use rustc::ty::layout::Layout::*;
|
||||||
let variant = match *base_layout {
|
let variant = match *base_layout {
|
||||||
Univariant { ref variant, .. } => variant,
|
Univariant { ref variant, .. } => variant,
|
||||||
|
@ -901,7 +904,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let offset = variant.field_offset(field.index()).bytes();
|
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) => {
|
Downcast(_, variant) => {
|
||||||
|
@ -922,6 +933,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
|
|
||||||
Deref => {
|
Deref => {
|
||||||
let pointee_ty = pointee_type(base_ty).expect("Deref of non-pointer");
|
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 ptr = self.memory.read_ptr(base.ptr)?;
|
||||||
let extra = match pointee_ty.sty {
|
let extra = match pointee_ty.sty {
|
||||||
ty::TySlice(_) | ty::TyStr => {
|
ty::TySlice(_) | ty::TyStr => {
|
||||||
|
|
|
@ -10,9 +10,14 @@ impl Trait for Struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Foo<T: ?Sized>(T);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let y: &Trait = &Struct(42);
|
let y: &Trait = &Struct(42);
|
||||||
y.method();
|
y.method();
|
||||||
|
let x: Foo<Struct> = Foo(Struct(42));
|
||||||
|
let y: &Foo<Trait> = &x;
|
||||||
|
y.0.method();
|
||||||
/*
|
/*
|
||||||
let x: Box<Fn(i32) -> i32> = Box::new(|x| x * 2);
|
let x: Box<Fn(i32) -> i32> = Box::new(|x| x * 2);
|
||||||
assert_eq!(x(21), 42);
|
assert_eq!(x(21), 42);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue