diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 7b93d3e795e..72daa0beb09 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -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` 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); } diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 68e30227185..fc97e350ad2 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -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; } }