Skip to content

Unboxed closures #14539

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/libcore/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -749,19 +749,23 @@ pub trait DerefMut<Result>: Deref<Result> {
#[lang="fn"]
pub trait Fn<Args,Result> {
/// This is called when the call operator is used.
#[rust_call_abi_hack]
fn call(&self, args: Args) -> Result;
}

/// A version of the call operator that takes a mutable receiver.
#[lang="fn_mut"]
pub trait FnMut<Args,Result> {
/// This is called when the call operator is used.
#[rust_call_abi_hack]
fn call_mut(&mut self, args: Args) -> Result;
}

/// A version of the call operator that takes a by-value receiver.
#[lang="fn_once"]
pub trait FnOnce<Args,Result> {
/// This is called when the call operator is used.
#[rust_call_abi_hack]
fn call_once(self, args: Args) -> Result;
}

1 change: 1 addition & 0 deletions src/libcore/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop, Deref, DerefMut};
pub use ops::{Shl, Shr};
pub use ops::{Index, IndexMut};
pub use ops::{Fn, FnMut, FnOnce};
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};

Expand Down
7 changes: 7 additions & 0 deletions src/librustc/front/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
("quad_precision_float", Removed),

("rustc_diagnostic_macros", Active),
("unboxed_closures", Active),

// A temporary feature gate used to enable parser extensions needed
// to bootstrap fix for #5723.
Expand Down Expand Up @@ -327,6 +328,12 @@ impl<'a> Visitor<()> for Context<'a> {
ast::ExprUnary(ast::UnBox, _) => {
self.gate_box(e.span);
}
ast::ExprUnboxedFn(..) => {
self.gate_feature("unboxed_closures",
e.span,
"unboxed closures are a work-in-progress \
feature with known bugs");
}
_ => {}
}
visit::walk_expr(self, e, ());
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,9 @@ impl LintPass for Stability {
typeck::MethodStatic(def_id) => {
def_id
}
typeck::MethodStaticUnboxedClosure(def_id) => {
def_id
}
typeck::MethodParam(typeck::MethodParam {
trait_id: trait_id,
method_num: index,
Expand Down
18 changes: 11 additions & 7 deletions src/librustc/metadata/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,11 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
tag_table_vtable_map = 0x50,
tag_table_adjustments = 0x51,
tag_table_moves_map = 0x52,
tag_table_capture_map = 0x53
tag_table_capture_map = 0x53,
tag_table_unboxed_closure_type = 0x54,
}
static first_astencode_tag: uint = tag_ast as uint;
static last_astencode_tag: uint = tag_table_capture_map as uint;
static last_astencode_tag: uint = tag_table_unboxed_closure_type as uint;
impl astencode_tag {
pub fn from_uint(value : uint) -> Option<astencode_tag> {
let is_a_tag = first_astencode_tag <= value && value <= last_astencode_tag;
Expand All @@ -155,6 +156,10 @@ pub static tag_item_trait_method_sort: uint = 0x60;

pub static tag_item_impl_type_basename: uint = 0x61;

pub static tag_crate_triple: uint = 0x66;

pub static tag_dylib_dependency_formats: uint = 0x67;

// Language items are a top-level directory (for speed). Hierarchy:
//
// tag_lang_items
Expand Down Expand Up @@ -199,10 +204,6 @@ pub static tag_plugin_registrar_fn: uint = 0x8b;
pub static tag_exported_macros: uint = 0x8c;
pub static tag_macro_def: uint = 0x8d;

pub static tag_crate_triple: uint = 0x66;

pub static tag_dylib_dependency_formats: uint = 0x67;

pub static tag_method_argument_names: uint = 0x8e;
pub static tag_method_argument_name: uint = 0x8f;

Expand All @@ -211,7 +212,6 @@ pub static tag_reachable_extern_fn_id: uint = 0x91;

pub static tag_items_data_item_stability: uint = 0x92;


#[deriving(Clone, Show)]
pub struct LinkMeta {
pub crate_name: String,
Expand All @@ -223,3 +223,7 @@ pub static tag_region_param_def_ident: uint = 0x91;
pub static tag_region_param_def_def_id: uint = 0x92;
pub static tag_region_param_def_space: uint = 0x93;
pub static tag_region_param_def_index: uint = 0x94;

pub static tag_unboxed_closures: uint = 0x95;
pub static tag_unboxed_closure: uint = 0x96;
pub static tag_unboxed_closure_type: uint = 0x97;
40 changes: 40 additions & 0 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,18 @@ fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
ebml_w.end_tag();
}

pub fn write_closure_type(ecx: &EncodeContext,
ebml_w: &mut Encoder,
closure_type: &ty::ClosureTy) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_closure_ty(ebml_w.writer, ty_str_ctxt, closure_type);
}

pub fn write_type(ecx: &EncodeContext,
ebml_w: &mut Encoder,
typ: ty::t) {
Expand Down Expand Up @@ -1618,6 +1630,26 @@ fn encode_macro_defs(ecx: &EncodeContext,
ebml_w.end_tag();
}

fn encode_unboxed_closures<'a>(
ecx: &'a EncodeContext,
ebml_w: &'a mut Encoder) {
ebml_w.start_tag(tag_unboxed_closures);
for (unboxed_closure_id, unboxed_closure_type) in
ecx.tcx.unboxed_closure_types.borrow().iter() {
if unboxed_closure_id.krate != LOCAL_CRATE {
continue
}

ebml_w.start_tag(tag_unboxed_closure);
encode_def_id(ebml_w, *unboxed_closure_id);
ebml_w.start_tag(tag_unboxed_closure_type);
write_closure_type(ecx, ebml_w, unboxed_closure_type);
ebml_w.end_tag();
ebml_w.end_tag();
}
ebml_w.end_tag();
}

struct ImplVisitor<'a,'b,'c> {
ecx: &'a EncodeContext<'b>,
ebml_w: &'a mut Encoder<'c>,
Expand Down Expand Up @@ -1787,6 +1819,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
native_lib_bytes: u64,
plugin_registrar_fn_bytes: u64,
macro_defs_bytes: u64,
unboxed_closure_bytes: u64,
impl_bytes: u64,
misc_bytes: u64,
item_bytes: u64,
Expand All @@ -1801,6 +1834,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
native_lib_bytes: 0,
plugin_registrar_fn_bytes: 0,
macro_defs_bytes: 0,
unboxed_closure_bytes: 0,
impl_bytes: 0,
misc_bytes: 0,
item_bytes: 0,
Expand Down Expand Up @@ -1873,6 +1907,11 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
encode_macro_defs(&ecx, krate, &mut ebml_w);
stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;

// Encode the types of all unboxed closures in this crate.
i = ebml_w.writer.tell().unwrap();
encode_unboxed_closures(&ecx, &mut ebml_w);
stats.unboxed_closure_bytes = ebml_w.writer.tell().unwrap() - i;

// Encode the def IDs of impls, for coherence checking.
i = ebml_w.writer.tell().unwrap();
encode_impls(&ecx, krate, &mut ebml_w);
Expand Down Expand Up @@ -1911,6 +1950,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
println!(" native bytes: {}", stats.native_lib_bytes);
println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
println!(" macro def bytes: {}", stats.macro_defs_bytes);
println!(" unboxed closure bytes: {}", stats.unboxed_closure_bytes);
println!(" impl bytes: {}", stats.impl_bytes);
println!(" misc bytes: {}", stats.misc_bytes);
println!(" item bytes: {}", stats.item_bytes);
Expand Down
18 changes: 17 additions & 1 deletion src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ fn data_log_string(data: &[u8], pos: uint) -> String {
buf
}

pub fn parse_ty_closure_data(data: &[u8],
crate_num: ast::CrateNum,
pos: uint,
tcx: &ty::ctxt,
conv: conv_did)
-> ty::ClosureTy {
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
parse_closure_ty(&mut st, conv)
}

pub fn parse_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
conv: conv_did) -> ty::t {
debug!("parse_ty_data {}", data_log_string(data, pos));
Expand Down Expand Up @@ -420,6 +430,10 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
assert_eq!(next(st), ']');
return ty::mk_struct(st.tcx, did, substs);
}
'k' => {
let did = parse_def(st, NominalType, |x,y| conv(x,y));
return ty::mk_unboxed_closure(st.tcx, did);
}
'e' => {
return ty::mk_err();
}
Expand Down Expand Up @@ -502,12 +516,14 @@ fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy {
let store = parse_trait_store(st, |x,y| conv(x,y));
let bounds = parse_bounds(st, |x,y| conv(x,y));
let sig = parse_sig(st, |x,y| conv(x,y));
let abi = parse_abi_set(st);
ty::ClosureTy {
fn_style: fn_style,
onceness: onceness,
store: store,
bounds: bounds.builtin_bounds,
sig: sig
sig: sig,
abi: abi,
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_unboxed_closure(def) => {
mywrite!(w, "k{}", (cx.ds)(def));
}
ty::ty_err => {
mywrite!(w, "e");
}
Expand Down Expand Up @@ -316,14 +319,15 @@ pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::BareFnTy) {
enc_fn_sig(w, cx, &ft.sig);
}

fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
pub fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
enc_fn_style(w, ft.fn_style);
enc_onceness(w, ft.onceness);
enc_trait_store(w, cx, ft.store);
let bounds = ty::ParamBounds {builtin_bounds: ft.bounds,
trait_bounds: Vec::new()};
enc_bounds(w, cx, &bounds);
enc_fn_sig(w, cx, &ft.sig);
enc_abi(w, ft.abi);
}

fn enc_fn_sig(w: &mut MemWriter, cx: &ctxt, fsig: &ty::FnSig) {
Expand Down
Loading