Skip to content

Commit c9cf3b3

Browse files
committed
auto merge of #16655 : pcwalton/rust/unboxed-closures-unboxing-shims, r=luqmana
Closes #16591. r? @luqmana
2 parents b9326ca + 6049b62 commit c9cf3b3

File tree

3 files changed

+82
-11
lines changed

3 files changed

+82
-11
lines changed

src/librustc/middle/trans/callee.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ fn resolve_default_method_vtables(bcx: &Block,
288288
/// `Trait` so that a by-value self method can be called.
289289
pub fn trans_unboxing_shim(bcx: &Block,
290290
llshimmedfn: ValueRef,
291-
method: &ty::Method,
291+
fty: &ty::BareFnTy,
292292
method_id: ast::DefId,
293293
substs: subst::Substs)
294294
-> ValueRef {
@@ -297,29 +297,29 @@ pub fn trans_unboxing_shim(bcx: &Block,
297297
let tcx = bcx.tcx();
298298

299299
// Transform the self type to `Box<self_type>`.
300-
let self_type = *method.fty.sig.inputs.get(0);
300+
let self_type = *fty.sig.inputs.get(0);
301301
let boxed_self_type = ty::mk_uniq(tcx, self_type);
302302
let boxed_function_type = ty::FnSig {
303-
binder_id: method.fty.sig.binder_id,
304-
inputs: method.fty.sig.inputs.iter().enumerate().map(|(i, typ)| {
303+
binder_id: fty.sig.binder_id,
304+
inputs: fty.sig.inputs.iter().enumerate().map(|(i, typ)| {
305305
if i == 0 {
306306
boxed_self_type
307307
} else {
308308
*typ
309309
}
310310
}).collect(),
311-
output: method.fty.sig.output,
311+
output: fty.sig.output,
312312
variadic: false,
313313
};
314314
let boxed_function_type = ty::BareFnTy {
315-
fn_style: method.fty.fn_style,
316-
abi: method.fty.abi,
315+
fn_style: fty.fn_style,
316+
abi: fty.abi,
317317
sig: boxed_function_type,
318318
};
319319
let boxed_function_type =
320320
ty::mk_bare_fn(tcx, boxed_function_type).subst(tcx, &substs);
321321
let function_type =
322-
ty::mk_bare_fn(tcx, method.fty.clone()).subst(tcx, &substs);
322+
ty::mk_bare_fn(tcx, (*fty).clone()).subst(tcx, &substs);
323323

324324
let function_name = ty::with_path(tcx, method_id, |path| {
325325
link::mangle_internal_name_by_path_and_seq(path, "unboxing_shim")

src/librustc/middle/trans/meth.rs

+55-3
Original file line numberDiff line numberDiff line change
@@ -515,13 +515,65 @@ fn get_vtable(bcx: &Block,
515515
bcx,
516516
closure_def_id);
517517

518-
let llfn = trans_fn_ref_with_vtables(
518+
let mut llfn = trans_fn_ref_with_vtables(
519519
bcx,
520520
closure_def_id,
521521
ExprId(0),
522-
callee_substs,
522+
callee_substs.clone(),
523523
VecPerParamSpace::empty());
524524

525+
{
526+
let unboxed_closures = bcx.tcx()
527+
.unboxed_closures
528+
.borrow();
529+
let closure_info =
530+
unboxed_closures.find(&closure_def_id)
531+
.expect("get_vtable(): didn't find \
532+
unboxed closure");
533+
if closure_info.kind == ty::FnOnceUnboxedClosureKind {
534+
// Untuple the arguments and create an unboxing shim.
535+
let mut new_inputs = vec![
536+
ty::mk_unboxed_closure(bcx.tcx(),
537+
closure_def_id,
538+
ty::ReStatic)
539+
];
540+
match ty::get(closure_info.closure_type
541+
.sig
542+
.inputs[0]).sty {
543+
ty::ty_tup(ref elements) => {
544+
for element in elements.iter() {
545+
new_inputs.push(*element)
546+
}
547+
}
548+
ty::ty_nil => {}
549+
_ => {
550+
bcx.tcx().sess.bug("get_vtable(): closure \
551+
type wasn't a tuple")
552+
}
553+
}
554+
555+
let closure_type = ty::BareFnTy {
556+
fn_style: closure_info.closure_type.fn_style,
557+
abi: Rust,
558+
sig: ty::FnSig {
559+
binder_id: closure_info.closure_type
560+
.sig
561+
.binder_id,
562+
inputs: new_inputs,
563+
output: closure_info.closure_type.sig.output,
564+
variadic: false,
565+
},
566+
};
567+
debug!("get_vtable(): closure type is {}",
568+
closure_type.repr(bcx.tcx()));
569+
llfn = trans_unboxing_shim(bcx,
570+
llfn,
571+
&closure_type,
572+
closure_def_id,
573+
callee_substs);
574+
}
575+
}
576+
525577
(vec!(llfn)).move_iter()
526578
}
527579
_ => ccx.sess().bug("get_vtable: expected a static origin"),
@@ -603,7 +655,7 @@ fn emit_vtable_methods(bcx: &Block,
603655
if m.explicit_self == ty::ByValueExplicitSelfCategory {
604656
fn_ref = trans_unboxing_shim(bcx,
605657
fn_ref,
606-
&*m,
658+
&m.fty,
607659
m_id,
608660
substs.clone());
609661
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(unboxed_closures, unboxed_closure_sugar)]
12+
13+
use std::ops::FnOnce;
14+
15+
fn main() {
16+
let task: Box<|: int| -> int> = box |: x| x;
17+
assert!(task.call_once((1234i,)) == 1234i);
18+
}
19+

0 commit comments

Comments
 (0)