about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-08-22 13:35:51 +0000
committerbors <bors@rust-lang.org>2014-08-22 13:35:51 +0000
commitc9cf3b3cc4d1d4eed359be54f08ba2b5fe961bf1 (patch)
tree669ce48a3bd9ad7ff747100e51eddf4399a0ef0f
parentb9326ca91c9515ae1b1ba48c2a942d5bd65a3bab (diff)
parent6049b628ad734dd49add077f81a22b713ed495de (diff)
downloadrust-c9cf3b3cc4d1d4eed359be54f08ba2b5fe961bf1.tar.gz
rust-c9cf3b3cc4d1d4eed359be54f08ba2b5fe961bf1.zip
auto merge of #16655 : pcwalton/rust/unboxed-closures-unboxing-shims, r=luqmana
Closes #16591.

r? @luqmana
-rw-r--r--src/librustc/middle/trans/callee.rs16
-rw-r--r--src/librustc/middle/trans/meth.rs58
-rw-r--r--src/test/run-pass/unboxed-closures-unboxing-shim.rs19
3 files changed, 82 insertions, 11 deletions
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index e397ee94c8a..d50b30c7545 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -288,7 +288,7 @@ fn resolve_default_method_vtables(bcx: &Block,
 /// `Trait` so that a by-value self method can be called.
 pub fn trans_unboxing_shim(bcx: &Block,
                            llshimmedfn: ValueRef,
-                           method: &ty::Method,
+                           fty: &ty::BareFnTy,
                            method_id: ast::DefId,
                            substs: subst::Substs)
                            -> ValueRef {
@@ -297,29 +297,29 @@ pub fn trans_unboxing_shim(bcx: &Block,
     let tcx = bcx.tcx();
 
     // Transform the self type to `Box<self_type>`.
-    let self_type = *method.fty.sig.inputs.get(0);
+    let self_type = *fty.sig.inputs.get(0);
     let boxed_self_type = ty::mk_uniq(tcx, self_type);
     let boxed_function_type = ty::FnSig {
-        binder_id: method.fty.sig.binder_id,
-        inputs: method.fty.sig.inputs.iter().enumerate().map(|(i, typ)| {
+        binder_id: fty.sig.binder_id,
+        inputs: fty.sig.inputs.iter().enumerate().map(|(i, typ)| {
             if i == 0 {
                 boxed_self_type
             } else {
                 *typ
             }
         }).collect(),
-        output: method.fty.sig.output,
+        output: fty.sig.output,
         variadic: false,
     };
     let boxed_function_type = ty::BareFnTy {
-        fn_style: method.fty.fn_style,
-        abi: method.fty.abi,
+        fn_style: fty.fn_style,
+        abi: fty.abi,
         sig: boxed_function_type,
     };
     let boxed_function_type =
         ty::mk_bare_fn(tcx, boxed_function_type).subst(tcx, &substs);
     let function_type =
-        ty::mk_bare_fn(tcx, method.fty.clone()).subst(tcx, &substs);
+        ty::mk_bare_fn(tcx, (*fty).clone()).subst(tcx, &substs);
 
     let function_name = ty::with_path(tcx, method_id, |path| {
         link::mangle_internal_name_by_path_and_seq(path, "unboxing_shim")
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 31f2a3df662..a9a308fc16d 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -515,13 +515,65 @@ fn get_vtable(bcx: &Block,
                         bcx,
                         closure_def_id);
 
-                let llfn = trans_fn_ref_with_vtables(
+                let mut llfn = trans_fn_ref_with_vtables(
                     bcx,
                     closure_def_id,
                     ExprId(0),
-                    callee_substs,
+                    callee_substs.clone(),
                     VecPerParamSpace::empty());
 
+                {
+                    let unboxed_closures = bcx.tcx()
+                                              .unboxed_closures
+                                              .borrow();
+                    let closure_info =
+                        unboxed_closures.find(&closure_def_id)
+                                        .expect("get_vtable(): didn't find \
+                                                 unboxed closure");
+                    if closure_info.kind == ty::FnOnceUnboxedClosureKind {
+                        // Untuple the arguments and create an unboxing shim.
+                        let mut new_inputs = vec![
+                            ty::mk_unboxed_closure(bcx.tcx(),
+                                                   closure_def_id,
+                                                   ty::ReStatic)
+                        ];
+                        match ty::get(closure_info.closure_type
+                                                  .sig
+                                                  .inputs[0]).sty {
+                            ty::ty_tup(ref elements) => {
+                                for element in elements.iter() {
+                                    new_inputs.push(*element)
+                                }
+                            }
+                            ty::ty_nil => {}
+                            _ => {
+                                bcx.tcx().sess.bug("get_vtable(): closure \
+                                                    type wasn't a tuple")
+                            }
+                        }
+
+                        let closure_type = ty::BareFnTy {
+                            fn_style: closure_info.closure_type.fn_style,
+                            abi: Rust,
+                            sig: ty::FnSig {
+                                binder_id: closure_info.closure_type
+                                                       .sig
+                                                       .binder_id,
+                                inputs: new_inputs,
+                                output: closure_info.closure_type.sig.output,
+                                variadic: false,
+                            },
+                        };
+                        debug!("get_vtable(): closure type is {}",
+                               closure_type.repr(bcx.tcx()));
+                        llfn = trans_unboxing_shim(bcx,
+                                                   llfn,
+                                                   &closure_type,
+                                                   closure_def_id,
+                                                   callee_substs);
+                    }
+                }
+
                 (vec!(llfn)).move_iter()
             }
             _ => ccx.sess().bug("get_vtable: expected a static origin"),
@@ -603,7 +655,7 @@ fn emit_vtable_methods(bcx: &Block,
                     if m.explicit_self == ty::ByValueExplicitSelfCategory {
                         fn_ref = trans_unboxing_shim(bcx,
                                                      fn_ref,
-                                                     &*m,
+                                                     &m.fty,
                                                      m_id,
                                                      substs.clone());
                     }
diff --git a/src/test/run-pass/unboxed-closures-unboxing-shim.rs b/src/test/run-pass/unboxed-closures-unboxing-shim.rs
new file mode 100644
index 00000000000..0a7baa3ba36
--- /dev/null
+++ b/src/test/run-pass/unboxed-closures-unboxing-shim.rs
@@ -0,0 +1,19 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unboxed_closures, unboxed_closure_sugar)]
+
+use std::ops::FnOnce;
+
+fn main() {
+    let task: Box<|: int| -> int> = box |: x| x;
+    assert!(task.call_once((1234i,)) == 1234i);
+}
+