librustc: Create unboxing shims as necessary for unboxed closures.
Closes #16591.
This commit is contained in:
parent
4444aec142
commit
6049b628ad
@ -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")
|
||||
|
@ -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());
|
||||
}
|
||||
|
19
src/test/run-pass/unboxed-closures-unboxing-shim.rs
Normal file
19
src/test/run-pass/unboxed-closures-unboxing-shim.rs
Normal file
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user