Implement by-value trait object method call.

This commit is contained in:
Masaki Hara 2018-09-11 23:32:18 +09:00
parent f2ef005d1d
commit 5eceab02ec
2 changed files with 14 additions and 8 deletions

View File

@ -305,17 +305,17 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
// Don't pass the vtable, it's not an argument of the virtual fn.
// Instead, pass just the (thin pointer) first field of `*dyn Trait`.
if arg_idx == Some(0) {
if layout.is_unsized() {
unimplemented!("by-value trait object is not \
yet implemented in #![feature(unsized_locals)]");
}
// FIXME(eddyb) `layout.field(cx, 0)` is not enough because e.g.
// `Box<dyn Trait>` has a few newtype wrappers around the raw
// pointer, so we'd have to "dig down" to find `*dyn Trait`.
let pointee = layout.ty.builtin_deref(true)
.unwrap_or_else(|| {
bug!("FnType::new_vtable: non-pointer self {:?}", layout)
}).ty;
let pointee = if layout.is_unsized() {
layout.ty
} else {
layout.ty.builtin_deref(true)
.unwrap_or_else(|| {
bug!("FnType::new_vtable: non-pointer self {:?}", layout)
}).ty
};
let fat_ptr_ty = cx.tcx.mk_mut_ptr(pointee);
layout = cx.layout_of(fat_ptr_ty).field(cx, 0);
}

View File

@ -651,6 +651,12 @@ impl FunctionCx<'a, 'll, 'tcx> {
.get_fn(&bx, meta, &fn_ty));
llargs.push(data_ptr);
continue;
} else if let Ref(data_ptr, Some(meta), _) = op.val {
// by-value dynamic dispatch
llfn = Some(meth::VirtualIndex::from_index(idx)
.get_fn(&bx, meta, &fn_ty));
llargs.push(data_ptr);
continue;
}
}