about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMasaki Hara <ackie.h.gmai@gmail.com>2018-09-11 23:32:18 +0900
committerMasaki Hara <ackie.h.gmai@gmail.com>2018-10-24 21:59:07 +0900
commit5eceab02ec2fcb53f855373929ea2364c12396b4 (patch)
treeb5384e3fe4efd0dae426cb97d4729b04b35fc562
parentf2ef005d1d9bfb6a594dc08805eef271fb9bbcd4 (diff)
downloadrust-5eceab02ec2fcb53f855373929ea2364c12396b4.tar.gz
rust-5eceab02ec2fcb53f855373929ea2364c12396b4.zip
Implement by-value trait object method call.
-rw-r--r--src/librustc_codegen_llvm/abi.rs16
-rw-r--r--src/librustc_codegen_llvm/mir/block.rs6
2 files changed, 14 insertions, 8 deletions
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<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);
             }
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;
                         }
                     }