]> git.lizzy.rs Git - rust.git/commitdiff
Implement by-value trait object method call.
authorMasaki Hara <ackie.h.gmai@gmail.com>
Tue, 11 Sep 2018 14:32:18 +0000 (23:32 +0900)
committerMasaki Hara <ackie.h.gmai@gmail.com>
Wed, 24 Oct 2018 12:59:07 +0000 (21:59 +0900)
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/mir/block.rs

index 7b93d3e795ed8f29c41132a2ba11f65e87b1ccb6..72daa0beb0982168d80df93718ddbe0d6c2da4b6 100644 (file)
@@ -305,17 +305,17 @@ fn new_vtable(cx: &CodegenCx<'ll, '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);
             }
index 68e30227185c0ba68c22ca50b705fb6c8d671432..fc97e350ad243fe70f28b20d76a45e7aa5f3eafc 100644 (file)
@@ -651,6 +651,12 @@ fn codegen_terminator(&mut self,
                                 .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;
                         }
                     }