1
Fork 0

deprecate fn exprs and the fn() type, preferring fn@ and native fn

This commit is contained in:
Niko Matsakis 2012-01-11 09:58:05 -08:00
parent d2be5b6c7a
commit 455f8b0d45
50 changed files with 177 additions and 175 deletions

View file

@ -564,8 +564,7 @@ fn link_binary(sess: session,
lm: link_meta) { lm: link_meta) {
// Converts a library file name into a gcc -l argument // Converts a library file name into a gcc -l argument
fn unlib(config: @session::config, filename: str) -> str { fn unlib(config: @session::config, filename: str) -> str {
let rmlib = let rmlib = fn@(filename: str) -> str {
bind fn (config: @session::config, filename: str) -> str {
if config.os == session::os_macos || if config.os == session::os_macos ||
(config.os == session::os_linux || (config.os == session::os_linux ||
config.os == session::os_freebsd) && config.os == session::os_freebsd) &&
@ -573,7 +572,7 @@ fn link_binary(sess: session,
ret str::slice(filename, 3u, ret str::slice(filename, 3u,
str::byte_len(filename)); str::byte_len(filename));
} else { ret filename; } } else { ret filename; }
}(config, _); };
fn rmext(filename: str) -> str { fn rmext(filename: str) -> str {
let parts = str::split(filename, '.' as u8); let parts = str::split(filename, '.' as u8);
vec::pop(parts); vec::pop(parts);

View file

@ -43,13 +43,13 @@ fn find_linkage_metas(attrs: [ast::attribute]) -> [@ast::meta_item] {
// Search a list of attributes and return only those with a specific name // Search a list of attributes and return only those with a specific name
fn find_attrs_by_name(attrs: [ast::attribute], name: ast::ident) -> fn find_attrs_by_name(attrs: [ast::attribute], name: ast::ident) ->
[ast::attribute] { [ast::attribute] {
let filter = let filter = (
bind fn (a: ast::attribute, name: ast::ident) -> fn@(a: ast::attribute) -> option::t<ast::attribute> {
option::t<ast::attribute> {
if get_attr_name(a) == name { if get_attr_name(a) == name {
option::some(a) option::some(a)
} else { option::none } } else { option::none }
}(_, name); }
);
ret vec::filter_map(attrs, filter); ret vec::filter_map(attrs, filter);
} }
@ -59,13 +59,11 @@ fn get_attr_name(attr: ast::attribute) -> ast::ident {
fn find_meta_items_by_name(metas: [@ast::meta_item], name: ast::ident) -> fn find_meta_items_by_name(metas: [@ast::meta_item], name: ast::ident) ->
[@ast::meta_item] { [@ast::meta_item] {
let filter = let filter = fn@(&&m: @ast::meta_item) -> option::t<@ast::meta_item> {
bind fn (&&m: @ast::meta_item, name: ast::ident) ->
option::t<@ast::meta_item> {
if get_meta_item_name(m) == name { if get_meta_item_name(m) == name {
option::some(m) option::some(m)
} else { option::none } } else { option::none }
}(_, name); };
ret vec::filter_map(metas, filter); ret vec::filter_map(metas, filter);
} }
@ -178,13 +176,11 @@ fn sort_meta_items(items: [@ast::meta_item]) -> [@ast::meta_item] {
fn remove_meta_items_by_name(items: [@ast::meta_item], name: str) -> fn remove_meta_items_by_name(items: [@ast::meta_item], name: str) ->
[@ast::meta_item] { [@ast::meta_item] {
let filter = let filter = fn@(&&item: @ast::meta_item) -> option::t<@ast::meta_item> {
bind fn (&&item: @ast::meta_item, name: str) ->
option::t<@ast::meta_item> {
if get_meta_item_name(item) != name { if get_meta_item_name(item) != name {
option::some(item) option::some(item)
} else { option::none } } else { option::none }
}(_, name); };
ret vec::filter_map(items, filter); ret vec::filter_map(items, filter);
} }

View file

@ -465,7 +465,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
// Path and definition ID indexing // Path and definition ID indexing
fn create_index<T: copy>(index: [entry<T>], hash_fn: fn(T) -> uint) -> fn create_index<T: copy>(index: [entry<T>], hash_fn: fn@(T) -> uint) ->
[@[entry<T>]] { [@[entry<T>]] {
let buckets: [@mutable [entry<T>]] = []; let buckets: [@mutable [entry<T>]] = [];
uint::range(0u, 256u) {|_i| buckets += [@mutable []]; }; uint::range(0u, 256u) {|_i| buckets += [@mutable []]; };
@ -482,8 +482,8 @@ fn create_index<T: copy>(index: [entry<T>], hash_fn: fn(T) -> uint) ->
} }
fn encode_index<T>(ebml_w: ebml::writer, buckets: [@[entry<T>]], fn encode_index<T>(ebml_w: ebml::writer, buckets: [@[entry<T>]],
write_fn: fn(io::writer, T)) { write_fn: block(io::writer, T)) {
let writer = ebml_w.writer; let writer = io::new_writer(ebml_w.writer);
ebml::start_tag(ebml_w, tag_index); ebml::start_tag(ebml_w, tag_index);
let bucket_locs: [uint] = []; let bucket_locs: [uint] = [];
ebml::start_tag(ebml_w, tag_index_buckets); ebml::start_tag(ebml_w, tag_index_buckets);

View file

@ -18,7 +18,7 @@ export enc_bounds;
type ctxt = type ctxt =
// Def -> str Callback: // Def -> str Callback:
// The type context. // The type context.
{ds: fn(def_id) -> str, tcx: ty::ctxt, abbrevs: abbrev_ctxt}; {ds: fn@(def_id) -> str, tcx: ty::ctxt, abbrevs: abbrev_ctxt};
// Compact string representation for ty.t values. API ty_str & parse_from_str. // Compact string representation for ty.t values. API ty_str & parse_from_str.
// Extra parameters are for converting to/from def_ids in the string rep. // Extra parameters are for converting to/from def_ids in the string rep.

View file

@ -58,7 +58,7 @@ fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
// variables. `id` is the node_id for some expression that creates the // variables. `id` is the node_id for some expression that creates the
// closure. // closure.
fn with_appropriate_checker(cx: ctx, id: node_id, fn with_appropriate_checker(cx: ctx, id: node_id,
b: block(fn(ctx, ty::t, sp: span))) { b: block(fn@(ctx, ty::t, sp: span))) {
let fty = ty::node_id_to_monotype(cx.tcx, id); let fty = ty::node_id_to_monotype(cx.tcx, id);
alt ty::ty_fn_proto(cx.tcx, fty) { alt ty::ty_fn_proto(cx.tcx, fty) {
proto_uniq. { b(check_send); } proto_uniq. { b(check_send); }

View file

@ -1706,7 +1706,7 @@ fn add_name(ch: checker, sp: span, name: ident) {
fn ident_id(&&i: ident) -> ident { ret i; } fn ident_id(&&i: ident) -> ident { ret i; }
fn ensure_unique<T>(e: env, sp: span, elts: [T], id: fn(T) -> ident, fn ensure_unique<T>(e: env, sp: span, elts: [T], id: block(T) -> ident,
kind: str) { kind: str) {
let ch = checker(e, kind); let ch = checker(e, kind);
for elt: T in elts { add_name(ch, sp, id(elt)); } for elt: T in elts { add_name(ch, sp, id(elt)); }

View file

@ -1140,7 +1140,7 @@ fn declare_tydesc(cx: @local_ctxt, sp: span, t: ty::t, ty_params: [uint])
ret info; ret info;
} }
type glue_helper = fn(@block_ctxt, ValueRef, ty::t); type glue_helper = fn@(@block_ctxt, ValueRef, ty::t);
fn declare_generic_glue(cx: @local_ctxt, t: ty::t, llfnty: TypeRef, name: str) fn declare_generic_glue(cx: @local_ctxt, t: ty::t, llfnty: TypeRef, name: str)
-> ValueRef { -> ValueRef {
@ -1570,8 +1570,8 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
} }
} }
type val_pair_fn = fn(@block_ctxt, ValueRef, ValueRef) -> @block_ctxt; type val_pair_fn = fn@(@block_ctxt, ValueRef, ValueRef) -> @block_ctxt;
type val_and_ty_fn = fn(@block_ctxt, ValueRef, ty::t) -> @block_ctxt; type val_and_ty_fn = fn@(@block_ctxt, ValueRef, ty::t) -> @block_ctxt;
fn load_inbounds(cx: @block_ctxt, p: ValueRef, idxs: [int]) -> ValueRef { fn load_inbounds(cx: @block_ctxt, p: ValueRef, idxs: [int]) -> ValueRef {
ret Load(cx, GEPi(cx, p, idxs)); ret Load(cx, GEPi(cx, p, idxs));
@ -3268,7 +3268,7 @@ fn invoke_full(bcx: @block_ctxt, llfn: ValueRef, llargs: [ValueRef],
fn invoke_(bcx: @block_ctxt, llfn: ValueRef, llargs: [ValueRef], fn invoke_(bcx: @block_ctxt, llfn: ValueRef, llargs: [ValueRef],
to_zero: [{v: ValueRef, t: ty::t}], to_zero: [{v: ValueRef, t: ty::t}],
to_revoke: [{v: ValueRef, t: ty::t}], to_revoke: [{v: ValueRef, t: ty::t}],
invoker: fn(@block_ctxt, ValueRef, [ValueRef], invoker: block(@block_ctxt, ValueRef, [ValueRef],
BasicBlockRef, BasicBlockRef)) -> @block_ctxt { BasicBlockRef, BasicBlockRef)) -> @block_ctxt {
// FIXME: May be worth turning this into a plain call when there are no // FIXME: May be worth turning this into a plain call when there are no
// cleanups to run // cleanups to run

View file

@ -647,7 +647,7 @@ fn make_fn_glue(
cx: @block_ctxt, cx: @block_ctxt,
v: ValueRef, v: ValueRef,
t: ty::t, t: ty::t,
glue_fn: fn(@block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt) glue_fn: fn@(@block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt)
-> @block_ctxt { -> @block_ctxt {
let bcx = cx; let bcx = cx;
let tcx = bcx_tcx(cx); let tcx = bcx_tcx(cx);

View file

@ -237,14 +237,11 @@ fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhs: ValueRef,
let write_ptr_ptr = do_spill_noroot let write_ptr_ptr = do_spill_noroot
(bcx, get_dataptr(bcx, new_vec_ptr, llunitty)); (bcx, get_dataptr(bcx, new_vec_ptr, llunitty));
let copy_fn = let copy_fn = fn@(bcx: @block_ctxt, addr: ValueRef,
bind fn (bcx: @block_ctxt, addr: ValueRef, _ty: ty::t, _ty: ty::t) -> @block_ctxt {
write_ptr_ptr: ValueRef, unit_ty: ty::t, llunitsz: ValueRef)
-> @block_ctxt {
let ccx = bcx_ccx(bcx); let ccx = bcx_ccx(bcx);
let write_ptr = Load(bcx, write_ptr_ptr); let write_ptr = Load(bcx, write_ptr_ptr);
let bcx = let bcx = copy_val(bcx, INIT, write_ptr,
copy_val(bcx, INIT, write_ptr,
load_if_immediate(bcx, addr, unit_ty), unit_ty); load_if_immediate(bcx, addr, unit_ty), unit_ty);
let incr = let incr =
ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) ? ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) ?
@ -252,14 +249,14 @@ fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhs: ValueRef,
Store(bcx, InBoundsGEP(bcx, write_ptr, [incr]), Store(bcx, InBoundsGEP(bcx, write_ptr, [incr]),
write_ptr_ptr); write_ptr_ptr);
ret bcx; ret bcx;
}(_, _, _, write_ptr_ptr, unit_ty, llunitsz); };
let bcx = iter_vec_raw(bcx, lhs, vec_ty, lhs_fill, copy_fn); let bcx = iter_vec_raw(bcx, lhs, vec_ty, lhs_fill, copy_fn);
bcx = iter_vec_raw(bcx, rhs, vec_ty, rhs_fill, copy_fn); bcx = iter_vec_raw(bcx, rhs, vec_ty, rhs_fill, copy_fn);
ret trans::store_in_dest(bcx, new_vec_ptr, dest); ret trans::store_in_dest(bcx, new_vec_ptr, dest);
} }
type val_and_ty_fn = fn(@block_ctxt, ValueRef, ty::t) -> result; type val_and_ty_fn = fn@(@block_ctxt, ValueRef, ty::t) -> result;
type iter_vec_block = block(@block_ctxt, ValueRef, ty::t) -> @block_ctxt; type iter_vec_block = block(@block_ctxt, ValueRef, ty::t) -> @block_ctxt;

View file

@ -552,7 +552,7 @@ fn constraints(fcx: fn_ctxt) -> [norm_constraint] {
fn match_args(fcx: fn_ctxt, occs: @mutable [pred_args], fn match_args(fcx: fn_ctxt, occs: @mutable [pred_args],
occ: [@constr_arg_use]) -> uint { occ: [@constr_arg_use]) -> uint {
#debug("match_args: looking at %s", #debug("match_args: looking at %s",
constr_args_to_str(fn (i: inst) -> str { ret i.ident; }, occ)); constr_args_to_str(fn@(i: inst) -> str { ret i.ident; }, occ));
for pd: pred_args in *occs { for pd: pred_args in *occs {
log(debug, log(debug,
"match_args: candidate " + pred_args_to_str(pd)); "match_args: candidate " + pred_args_to_str(pd));
@ -633,7 +633,7 @@ fn expr_to_constr(tcx: ty::ctxt, e: @expr) -> sp_constr {
fn pred_args_to_str(p: pred_args) -> str { fn pred_args_to_str(p: pred_args) -> str {
"<" + uint::str(p.node.bit_num) + ", " + "<" + uint::str(p.node.bit_num) + ", " +
constr_args_to_str(fn (i: inst) -> str { ret i.ident; }, p.node.args) constr_args_to_str(fn@(i: inst) -> str { ret i.ident; }, p.node.args)
+ ">" + ">"
} }
@ -973,7 +973,8 @@ fn non_init_constraint_mentions(_fcx: fn_ctxt, c: norm_constraint, v: node_id)
}; };
} }
fn args_mention<T>(args: [@constr_arg_use], q: fn([T], node_id) -> bool, fn args_mention<T>(args: [@constr_arg_use],
q: block([T], node_id) -> bool,
s: [T]) -> bool { s: [T]) -> bool {
/* /*
FIXME FIXME

View file

@ -151,7 +151,7 @@ fn relax_precond_block(fcx: fn_ctxt, i: node_id, b: blk) {
visit_expr: relax_precond_expr, visit_expr: relax_precond_expr,
visit_stmt: relax_precond_stmt, visit_stmt: relax_precond_stmt,
visit_item: visit_item:
fn (_i: @item, _cx: relax_ctxt, _vt: visit::vt<relax_ctxt>) { }, fn@(_i: @item, _cx: relax_ctxt, _vt: visit::vt<relax_ctxt>) { },
visit_fn: bind do_nothing(_, _, _, _, _, _, _) visit_fn: bind do_nothing(_, _, _, _, _, _, _)
with *visitor}; with *visitor};
let v1 = visit::mk_vt(visitor); let v1 = visit::mk_vt(visitor);

View file

@ -1077,7 +1077,7 @@ fn type_is_native(cx: ctxt, ty: t) -> bool {
alt struct(cx, ty) { ty_native(_) { ret true; } _ { ret false; } } alt struct(cx, ty) { ty_native(_) { ret true; } _ { ret false; } }
} }
fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) -> fn type_structurally_contains(cx: ctxt, ty: t, test: block(sty) -> bool) ->
bool { bool {
let sty = struct(cx, ty); let sty = struct(cx, ty);
if test(sty) { ret true; } if test(sty) { ret true; }
@ -1121,20 +1121,20 @@ pure fn type_has_dynamic_size(cx: ctxt, ty: t) -> bool unchecked {
actually checkable. It seems to me like a lot of properties actually checkable. It seems to me like a lot of properties
that the type context tracks about types should be immutable.) that the type context tracks about types should be immutable.)
*/ */
type_structurally_contains(cx, ty, fn (sty: sty) -> bool { type_structurally_contains(cx, ty) {|sty|
alt sty { alt sty {
ty_param(_, _) { true } ty_param(_, _) { true }
_ { false } _ { false }
} }
}) }
} }
// Returns true for noncopyable types and types where a copy of a value can be // Returns true for noncopyable types and types where a copy of a value can be
// distinguished from the value itself. I.e. types with mutable content that's // distinguished from the value itself. I.e. types with mutable content that's
// not shared through a pointer. // not shared through a pointer.
fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool { fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool {
ret !type_structurally_contains(cx, ty, fn (sty: sty) -> bool { ret !type_structurally_contains(cx, ty, {|sty|
ret alt sty { alt sty {
ty_param(_, _) { true } ty_param(_, _) { true }
ty_vec(mt) { ty_vec(mt) {
mt.mut != ast::imm mt.mut != ast::imm
@ -1149,12 +1149,12 @@ fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool {
false false
} }
_ { false } _ { false }
}; }
}) && type_kind(cx, ty) != kind_noncopyable; }) && type_kind(cx, ty) != kind_noncopyable;
} }
fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool { fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
ret type_structurally_contains(cx, ty, fn (sty: sty) -> bool { ret type_structurally_contains(cx, ty, {|sty|
ret alt sty { ret alt sty {
ty_uniq(_) { ret true; } ty_uniq(_) { ret true; }
ty_vec(_) { true } ty_vec(_) { true }
@ -1414,7 +1414,9 @@ fn hash_type_structure(st: sty) -> uint {
fn hash_raw_ty(&&rt: @raw_t) -> uint { ret rt.hash; } fn hash_raw_ty(&&rt: @raw_t) -> uint { ret rt.hash; }
fn arg_eq<T>(eq: fn(T, T) -> bool, a: @sp_constr_arg<T>, b: @sp_constr_arg<T>) fn arg_eq<T>(eq: block(T, T) -> bool,
a: @sp_constr_arg<T>,
b: @sp_constr_arg<T>)
-> bool { -> bool {
alt a.node { alt a.node {
ast::carg_base. { ast::carg_base. {
@ -1431,7 +1433,8 @@ fn arg_eq<T>(eq: fn(T, T) -> bool, a: @sp_constr_arg<T>, b: @sp_constr_arg<T>)
} }
} }
fn args_eq<T>(eq: fn(T, T) -> bool, a: [@sp_constr_arg<T>], fn args_eq<T>(eq: block(T, T) -> bool,
a: [@sp_constr_arg<T>],
b: [@sp_constr_arg<T>]) -> bool { b: [@sp_constr_arg<T>]) -> bool {
let i: uint = 0u; let i: uint = 0u;
for arg: @sp_constr_arg<T> in a { for arg: @sp_constr_arg<T> in a {
@ -1752,12 +1755,13 @@ mod unify {
let root_a = ufind::find(vb.sets, set_a); let root_a = ufind::find(vb.sets, set_a);
let root_b = ufind::find(vb.sets, set_b); let root_b = ufind::find(vb.sets, set_b);
let replace_type = let replace_type = (
bind fn (vb: @var_bindings, t: t, set_a: uint, set_b: uint) { fn@(vb: @var_bindings, t: t) {
ufind::union(vb.sets, set_a, set_b); ufind::union(vb.sets, set_a, set_b);
let root_c: uint = ufind::find(vb.sets, set_a); let root_c: uint = ufind::find(vb.sets, set_a);
smallintmap::insert::<t>(vb.types, root_c, t); smallintmap::insert::<t>(vb.types, root_c, t);
}(_, _, set_a, set_b); }
);
alt smallintmap::find(vb.types, root_a) { alt smallintmap::find(vb.types, root_a) {

View file

@ -1450,7 +1450,7 @@ fn require_pure_call(ccx: @crate_ctxt, caller_purity: ast::purity,
} }
} }
type unifier = fn(@fn_ctxt, span, ty::t, ty::t) -> ty::t; type unifier = fn@(@fn_ctxt, span, ty::t, ty::t) -> ty::t;
fn check_expr(fcx: @fn_ctxt, expr: @ast::expr) -> bool { fn check_expr(fcx: @fn_ctxt, expr: @ast::expr) -> bool {
fn dummy_unify(_fcx: @fn_ctxt, _sp: span, _expected: ty::t, actual: ty::t) fn dummy_unify(_fcx: @fn_ctxt, _sp: span, _expected: ty::t, actual: ty::t)
@ -2886,7 +2886,7 @@ mod dict {
fn resolve_in_block(fcx: @fn_ctxt, bl: ast::blk) { fn resolve_in_block(fcx: @fn_ctxt, bl: ast::blk) {
visit::visit_block(bl, fcx, visit::mk_vt(@{ visit::visit_block(bl, fcx, visit::mk_vt(@{
visit_expr: resolve_expr, visit_expr: resolve_expr,
visit_item: fn(_i: @ast::item, &&_e: @fn_ctxt, visit_item: fn@(_i: @ast::item, &&_e: @fn_ctxt,
_v: visit::vt<@fn_ctxt>) {} _v: visit::vt<@fn_ctxt>) {}
with *visit::default_visitor() with *visit::default_visitor()
})); }));

View file

@ -32,7 +32,7 @@ fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
file.lines += [{ch: chpos, byte: byte_pos}]; file.lines += [{ch: chpos, byte: byte_pos}];
} }
type lookup_fn = fn(file_pos) -> uint; type lookup_fn = fn@(file_pos) -> uint;
fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc { fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
let len = vec::len(map.files); let len = vec::len(map.files);

View file

@ -532,7 +532,7 @@ fn block_to_ident(blk: blk_) -> option::t<ident> {
fn p_t_s_r_mac(cx: ext_ctxt, mac: ast::mac, s: selector, b: binders) { fn p_t_s_r_mac(cx: ext_ctxt, mac: ast::mac, s: selector, b: binders) {
fn select_pt_1(cx: ext_ctxt, m: matchable, fn select_pt_1(cx: ext_ctxt, m: matchable,
fn_m: fn(ast::mac) -> match_result) -> match_result { fn_m: block(ast::mac) -> match_result) -> match_result {
ret alt m { ret alt m {
match_expr(e) { match_expr(e) {
alt e.node { expr_mac(mac) { fn_m(mac) } _ { none } } alt e.node { expr_mac(mac) { fn_m(mac) } _ { none } }

View file

@ -480,14 +480,21 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
expect(p, token::RBRACKET); expect(p, token::RBRACKET);
} else if eat_word(p, "fn") { } else if eat_word(p, "fn") {
let proto = parse_fn_ty_proto(p); let proto = parse_fn_ty_proto(p);
alt proto {
ast::proto_bare. { p.warn("fn is deprecated, use native fn"); }
_ { /* fallthrough */ }
}
t = parse_ty_fn(proto, p); t = parse_ty_fn(proto, p);
} else if eat_word(p, "block") { } else if eat_word(p, "block") {
t = parse_ty_fn(ast::proto_block, p); t = parse_ty_fn(ast::proto_block, p);
} else if eat_word(p, "native") {
expect_word(p, "fn");
t = parse_ty_fn(ast::proto_bare, p);
} else if eat_word(p, "lambda") { } else if eat_word(p, "lambda") {
//(breaks prettyprinting!) p.warn("lambda is deprecated, use fn@"); p.warn("lambda is deprecated, use fn@");
t = parse_ty_fn(ast::proto_box, p); t = parse_ty_fn(ast::proto_box, p);
} else if eat_word(p, "sendfn") { } else if eat_word(p, "sendfn") {
//(breaks prettyprinting!) p.warn("sendfn is deprecated, use fn~"); p.warn("sendfn is deprecated, use fn~");
t = parse_ty_fn(ast::proto_uniq, p); t = parse_ty_fn(ast::proto_uniq, p);
} else if p.token == token::MOD_SEP || is_ident(p.token) { } else if p.token == token::MOD_SEP || is_ident(p.token) {
let path = parse_path(p); let path = parse_path(p);
@ -786,6 +793,10 @@ fn parse_bottom_expr(p: parser) -> pexpr {
ret pexpr(parse_alt_expr(p)); ret pexpr(parse_alt_expr(p));
} else if eat_word(p, "fn") { } else if eat_word(p, "fn") {
let proto = parse_fn_ty_proto(p); let proto = parse_fn_ty_proto(p);
alt proto {
ast::proto_bare. { p.warn("fn expr are deprecated, use fn@"); }
_ { /* fallthrough */ }
}
ret pexpr(parse_fn_expr(p, proto)); ret pexpr(parse_fn_expr(p, proto));
} else if eat_word(p, "block") { } else if eat_word(p, "block") {
ret pexpr(parse_fn_expr(p, ast::proto_block)); ret pexpr(parse_fn_expr(p, ast::proto_block));

View file

@ -194,7 +194,7 @@ fn synth_comment(s: ps, text: str) {
word(s.s, "*/"); word(s.s, "*/");
} }
fn commasep<IN>(s: ps, b: breaks, elts: [IN], op: fn(ps, IN)) { fn commasep<IN>(s: ps, b: breaks, elts: [IN], op: block(ps, IN)) {
box(s, 0u, b); box(s, 0u, b);
let first = true; let first = true;
for elt: IN in elts { for elt: IN in elts {
@ -205,8 +205,8 @@ fn commasep<IN>(s: ps, b: breaks, elts: [IN], op: fn(ps, IN)) {
} }
fn commasep_cmnt<IN>(s: ps, b: breaks, elts: [IN], op: fn(ps, IN), fn commasep_cmnt<IN>(s: ps, b: breaks, elts: [IN], op: block(ps, IN),
get_span: fn(IN) -> codemap::span) { get_span: block(IN) -> codemap::span) {
box(s, 0u, b); box(s, 0u, b);
let len = vec::len::<IN>(elts); let len = vec::len::<IN>(elts);
let i = 0u; let i = 0u;
@ -1246,7 +1246,7 @@ fn print_view_item(s: ps, item: @ast::view_item) {
for elt: ast::ident in *mod_path { word(s.s, elt); word(s.s, "::"); } for elt: ast::ident in *mod_path { word(s.s, elt); word(s.s, "::"); }
word(s.s, "{"); word(s.s, "{");
commasep(s, inconsistent, idents, commasep(s, inconsistent, idents,
fn (s: ps, w: ast::import_ident) { word(s.s, w.node.name) }); fn@(s: ps, w: ast::import_ident) { word(s.s, w.node.name) });
word(s.s, "}"); word(s.s, "}");
} }
ast::view_item_import_glob(ids, _) { ast::view_item_import_glob(ids, _) {
@ -1261,7 +1261,7 @@ fn print_view_item(s: ps, item: @ast::view_item) {
ast::view_item_export(ids, _) { ast::view_item_export(ids, _) {
head(s, "export"); head(s, "export");
commasep(s, inconsistent, ids, commasep(s, inconsistent, ids,
fn (s: ps, &&w: ast::ident) { word(s.s, w) }); fn@(s: ps, &&w: ast::ident) { word(s.s, w) });
} }
} }
word(s.s, ";"); word(s.s, ";");
@ -1604,7 +1604,7 @@ fn ast_fn_constrs_str(decl: ast::fn_decl, constrs: [@ast::constr]) -> str {
fn proto_to_str(p: ast::proto) -> str { fn proto_to_str(p: ast::proto) -> str {
ret alt p { ret alt p {
ast::proto_bare. { "fn" } ast::proto_bare. { "native fn" }
ast::proto_block. { "block" } ast::proto_block. { "block" }
ast::proto_uniq. { "fn~" } ast::proto_uniq. { "fn~" }
ast::proto_box. { "fn@" } ast::proto_box. { "fn@" }

View file

@ -391,21 +391,21 @@ type simple_visitor =
fn simple_ignore_ty(_t: @ty) {} fn simple_ignore_ty(_t: @ty) {}
fn default_simple_visitor() -> simple_visitor { fn default_simple_visitor() -> simple_visitor {
ret @{visit_mod: fn(_m: _mod, _sp: span) { }, ret @{visit_mod: fn@(_m: _mod, _sp: span) { },
visit_view_item: fn(_vi: @view_item) { }, visit_view_item: fn@(_vi: @view_item) { },
visit_native_item: fn(_ni: @native_item) { }, visit_native_item: fn@(_ni: @native_item) { },
visit_item: fn(_i: @item) { }, visit_item: fn@(_i: @item) { },
visit_local: fn(_l: @local) { }, visit_local: fn@(_l: @local) { },
visit_block: fn(_b: ast::blk) { }, visit_block: fn@(_b: ast::blk) { },
visit_stmt: fn(_s: @stmt) { }, visit_stmt: fn@(_s: @stmt) { },
visit_arm: fn(_a: arm) { }, visit_arm: fn@(_a: arm) { },
visit_pat: fn(_p: @pat) { }, visit_pat: fn@(_p: @pat) { },
visit_decl: fn(_d: @decl) { }, visit_decl: fn@(_d: @decl) { },
visit_expr: fn(_e: @expr) { }, visit_expr: fn@(_e: @expr) { },
visit_ty: simple_ignore_ty, visit_ty: simple_ignore_ty,
visit_ty_params: fn(_ps: [ty_param]) {}, visit_ty_params: fn@(_ps: [ty_param]) {},
visit_constr: fn(_p: @path, _sp: span, _id: node_id) { }, visit_constr: fn@(_p: @path, _sp: span, _id: node_id) { },
visit_fn: fn(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span, visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
_id: node_id) { } _id: node_id) { }
}; };
} }

View file

@ -120,7 +120,7 @@ fn spawn(+f: sendfn()) -> task {
spawn_inner(f, none) spawn_inner(f, none)
} }
fn spawn_inner(-f: sendfn(), fn spawn_inner(-f: fn~(),
notify: option<comm::chan<task_notification>>) -> task unsafe { notify: option<comm::chan<task_notification>>) -> task unsafe {
let closure: *rust_closure = unsafe::reinterpret_cast(ptr::addr_of(f)); let closure: *rust_closure = unsafe::reinterpret_cast(ptr::addr_of(f));
#debug("spawn: closure={%x,%x}", (*closure).fnptr, (*closure).envptr); #debug("spawn: closure={%x,%x}", (*closure).fnptr, (*closure).envptr);
@ -145,7 +145,7 @@ A task that sends notification upon termination
*/ */
type joinable_task = (task, comm::port<task_notification>); type joinable_task = (task, comm::port<task_notification>);
fn spawn_joinable(+f: sendfn()) -> joinable_task { fn spawn_joinable(+f: fn~()) -> joinable_task {
let notify_port = comm::port(); let notify_port = comm::port();
let notify_chan = comm::chan(notify_port); let notify_chan = comm::chan(notify_port);
let task = spawn_inner(f, some(notify_chan)); let task = spawn_inner(f, some(notify_chan));
@ -161,7 +161,7 @@ fn spawn_joinable(+f: sendfn()) -> joinable_task {
let notify_port = comm::port(); let notify_port = comm::port();
let notify_chan = comm::chan(notify_port); let notify_chan = comm::chan(notify_port);
let g = sendfn[copy notify_chan; move f]() { let g = fn~[copy notify_chan; move f]() {
let this_task = rustrt::get_task_id(); let this_task = rustrt::get_task_id();
let result = @mutable tr_failure; let result = @mutable tr_failure;
let _rsrc = notify_rsrc((notify_chan, this_task, result)); let _rsrc = notify_rsrc((notify_chan, this_task, result));
@ -203,7 +203,7 @@ supplied with a channel to send messages to the parent and a port to receive
messages from the parent. The type parameter `ToCh` is the type for messages messages from the parent. The type parameter `ToCh` is the type for messages
sent from the parent to the child and `FrCh` is the type for messages sent sent from the parent to the child and `FrCh` is the type for messages sent
from the child to the parent. */ from the child to the parent. */
type connected_fn<ToCh, FrCh> = sendfn(comm::port<ToCh>, comm::chan<FrCh>); type connected_fn<ToCh, FrCh> = fn~(comm::port<ToCh>, comm::chan<FrCh>);
/* /*
Type: connected_fn Type: connected_fn
@ -238,7 +238,7 @@ fn spawn_connected<ToCh:send, FrCh:send>(+f: connected_fn<ToCh, FrCh>)
let from_child_chan = comm::chan(from_child_port); let from_child_chan = comm::chan(from_child_port);
let get_to_child_port = comm::port::<comm::chan<ToCh>>(); let get_to_child_port = comm::port::<comm::chan<ToCh>>();
let get_to_child_chan = comm::chan(get_to_child_port); let get_to_child_chan = comm::chan(get_to_child_port);
let child_task = spawn(sendfn[move f]() { let child_task = spawn(fn~[move f]() {
let to_child_port = comm::port::<ToCh>(); let to_child_port = comm::port::<ToCh>();
comm::send(get_to_child_chan, comm::chan(to_child_port)); comm::send(get_to_child_chan, comm::chan(to_child_port));
f(to_child_port, from_child_chan); f(to_child_port, from_child_chan);

View file

@ -523,7 +523,7 @@ mod fsync {
type arg<t> = { type arg<t> = {
val: t, val: t,
opt_level: option::t<level>, opt_level: option::t<level>,
fsync_fn: fn(t, level) -> int fsync_fn: fn@(t, level) -> int
}; };
// fsync file after executing blk // fsync file after executing blk
@ -532,7 +532,7 @@ mod fsync {
blk: block(&&res<os::libc::FILE>)) { blk: block(&&res<os::libc::FILE>)) {
blk(res({ blk(res({
val: *file, opt_level: opt_level, val: *file, opt_level: opt_level,
fsync_fn: fn(&&file: os::libc::FILE, l: level) -> int { fsync_fn: fn@(&&file: os::libc::FILE, l: level) -> int {
ret os::fsync_fd(os::libc::fileno(file), l) as int; ret os::fsync_fd(os::libc::fileno(file), l) as int;
} }
})); }));
@ -543,7 +543,7 @@ mod fsync {
blk: block(&&res<fd_t>)) { blk: block(&&res<fd_t>)) {
blk(res({ blk(res({
val: *fd, opt_level: opt_level, val: *fd, opt_level: opt_level,
fsync_fn: fn(&&fd: fd_t, l: level) -> int { fsync_fn: fn@(&&fd: fd_t, l: level) -> int {
ret os::fsync_fd(fd, l) as int; ret os::fsync_fd(fd, l) as int;
} }
})); }));
@ -556,7 +556,7 @@ mod fsync {
fn obj_sync(&&o: t, opt_level: option::t<level>, blk: block(&&res<t>)) { fn obj_sync(&&o: t, opt_level: option::t<level>, blk: block(&&res<t>)) {
blk(res({ blk(res({
val: o, opt_level: opt_level, val: o, opt_level: opt_level,
fsync_fn: fn(&&o: t, l: level) -> int { ret o.fsync(l); } fsync_fn: fn@(&&o: t, l: level) -> int { ret o.fsync(l); }
})); }));
} }
} }

View file

@ -13,14 +13,14 @@ A function that returns a hash of a value.
The hash should concentrate entropy in the The hash should concentrate entropy in the
lower bits. lower bits.
*/ */
type hashfn<K> = fn(K) -> uint; type hashfn<K> = fn@(K) -> uint;
/* /*
Type: eqfn Type: eqfn
Equality Equality
*/ */
type eqfn<K> = fn(K, K) -> bool; type eqfn<K> = fn@(K, K) -> bool;
/* /*
Type: hashset Type: hashset

View file

@ -1,6 +1,6 @@
fn main() { fn main() {
let x = 3; let x = 3;
fn blah(_a: fn()) {} fn blah(_a: native fn()) {}
blah({|| blah({||
log(debug, x); //! ERROR attempted dynamic environment capture log(debug, x); //! ERROR attempted dynamic environment capture
}); });

View file

@ -1,5 +1,5 @@
fn main() { fn main() {
fn echo<T>(c: int, x: fn(T)) { #error("wee"); } fn echo<T>(c: int, x: native fn(T)) { #error("wee"); }
let y = bind echo(42, _); let y = bind echo(42, _);

View file

@ -1,6 +1,6 @@
use std; use std;
fn asSendfn( f : sendfn()->uint ) -> uint { fn asSendfn( f : fn~()->uint ) -> uint {
ret f(); ret f();
} }

View file

@ -1,6 +1,6 @@
fn force(f: block() -> int) -> int { ret f(); } fn force(f: block() -> int) -> int { ret f(); }
fn main() { fn main() {
let f = fn () -> int { ret 7 }; fn f() -> int { ret 7; }
assert (force(f) == 7); assert (force(f) == 7);
let g = bind force(f); let g = bind force(f);
assert (g() == 7); assert (g() == 7);

View file

@ -1,8 +1,7 @@
fn test_fn() { fn test_fn() {
type t = fn() -> int; type t = native fn() -> int;
fn ten() -> int { ret 10; } fn ten() -> int { ret 10; }
let rs: t = { ten }; let rs: t = { ten };
assert (rs() == 10); assert (rs() == 10);

View file

@ -1,8 +1,8 @@
fn fix_help<A, B>(f: fn(fn@(A) -> B, A) -> B, x: A) -> B { fn fix_help<A, B>(f: native fn(fn@(A) -> B, A) -> B, x: A) -> B {
ret f(bind fix_help(f, _), x); ret f(bind fix_help(f, _), x);
} }
fn fix<A, B>(f: fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B { fn fix<A, B>(f: native fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B {
ret bind fix_help(f, _); ret bind fix_help(f, _);
} }

View file

@ -1,8 +1,8 @@
fn fix_help<A, B: send>(f: fn(fn@(A) -> B, A) -> B, x: A) -> B { fn fix_help<A, B: send>(f: native fn(fn@(A) -> B, A) -> B, x: A) -> B {
ret f(bind fix_help(f, _), x); ret f(bind fix_help(f, _), x);
} }
fn fix<A, B: send>(f: fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B { fn fix<A, B: send>(f: native fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B {
ret bind fix_help(f, _); ret bind fix_help(f, _);
} }

View file

@ -1,7 +0,0 @@
fn main() {
let f: fn() = fn () {
#debug("This is a bare function")
};
let g;
g = f;
}

View file

@ -1,6 +0,0 @@
fn main() {
let f: fn() = fn () {
#debug("This is a bare function")
};
f();
}

View file

@ -3,7 +3,7 @@ fn f(i: int, &called: bool) {
called = true; called = true;
} }
fn g(f: fn(int, &bool), &called: bool) { fn g(f: native fn(int, &bool), &called: bool) {
f(10, called); f(10, called);
} }

View file

@ -1,6 +1,6 @@
// This is what the signature to spawn should look like with bare functions // This is what the signature to spawn should look like with bare functions
fn spawn<T: send>(val: T, f: fn(T)) { fn spawn<T: send>(val: T, f: native fn(T)) {
f(val); f(val);
} }
@ -10,7 +10,4 @@ fn f(&&i: int) {
fn main() { fn main() {
spawn(100, f); spawn(100, f);
spawn(100, fn(&&i: int) {
assert i == 100;
});
} }

View file

@ -3,5 +3,6 @@ type r = {
}; };
fn main() { fn main() {
let i: r = {field: fn() { }}; fn f() {}
let i: r = {field: f};
} }

View file

@ -1 +0,0 @@
fn main() { let x = fn (a: int) -> int { ret a + 1; }; assert (x(4) == 5); }

View file

@ -2,7 +2,7 @@
// -*- rust -*- // -*- rust -*-
fn foo(f: fn(int) -> int) { } fn foo(f: native fn(int) -> int) { }
fn id(x: int) -> int { ret x; } fn id(x: int) -> int { ret x; }

View file

@ -1,4 +1,4 @@
fn main() { fn main() {
// We should be able to type infer inside of fn@s. // We should be able to type infer inside of fn@s.
let f = fn () { let i = 10; }; let f = fn@() { let i = 10; };
} }

View file

@ -4,4 +4,8 @@
// -*- rust -*- // -*- rust -*-
fn f() -> int { ret 42; } fn f() -> int { ret 42; }
fn main() { let g: fn() -> int = f; let i: int = g(); assert (i == 42); } fn main() {
let g: native fn() -> int = f;
let i: int = g();
assert (i == 42);
}

View file

@ -4,10 +4,13 @@ fn mk() -> int { ret 1; }
fn chk(&&a: int) { log(debug, a); assert (a == 1); } fn chk(&&a: int) { log(debug, a); assert (a == 1); }
fn apply<T>(produce: fn() -> T, consume: fn(T)) { consume(produce()); } fn apply<T>(produce: native fn() -> T,
consume: native fn(T)) {
consume(produce());
}
fn main() { fn main() {
let produce: fn() -> int = mk; let produce: native fn() -> int = mk;
let consume: fn(&&int) = chk; let consume: native fn(&&int) = chk;
apply::<int>(produce, consume); apply::<int>(produce, consume);
} }

View file

@ -28,7 +28,7 @@ mod map_reduce {
type putter = fn@(str, str); type putter = fn@(str, str);
type mapper = fn(str, putter); type mapper = native fn(str, putter);
tag ctrl_proto { find_reducer([u8], chan<int>); mapper_done; } tag ctrl_proto { find_reducer([u8], chan<int>); mapper_done; }

View file

@ -2,7 +2,7 @@ fn even(&&e: int) -> bool {
e % 2 == 0 e % 2 == 0
} }
fn log_if<T>(c: fn(T)->bool, e: T) { fn log_if<T>(c: native fn(T)->bool, e: T) {
if c(e) { log(debug, e); } if c(e) { log(debug, e); }
} }

View file

@ -32,11 +32,11 @@ fn calllink08() { rustrt::get_task_id(); }
fn calllink09() { rustrt::sched_threads(); } fn calllink09() { rustrt::sched_threads(); }
fn calllink10() { rustrt::rust_get_task(); } fn calllink10() { rustrt::rust_get_task(); }
fn runtest(f: sendfn(), frame_backoff: u32) { fn runtest(f: fn~(), frame_backoff: u32) {
runtest2(f, frame_backoff, 0 as *u8); runtest2(f, frame_backoff, 0 as *u8);
} }
fn runtest2(f: sendfn(), frame_backoff: u32, last_stk: *u8) -> u32 { fn runtest2(f: fn~(), frame_backoff: u32, last_stk: *u8) -> u32 {
let curr_stk = rustrt::debug_get_stk_seg(); let curr_stk = rustrt::debug_get_stk_seg();
if (last_stk != curr_stk && last_stk != 0 as *u8) { if (last_stk != curr_stk && last_stk != 0 as *u8) {
// We switched stacks, go back and try to hit the dynamic linker // We switched stacks, go back and try to hit the dynamic linker

View file

@ -1,8 +1,10 @@
// Issue #922 // Issue #922
fn f2(-thing: fn()) { } fn f2(-thing: fn@()) { }
fn f(-thing: fn()) { f2(thing); } fn f(-thing: fn@()) {
f2(thing);
}
fn main() { fn main() {
f(fn(){}); f(fn@() {});
} }

View file

@ -1,4 +1,4 @@
tag mytype = {compute: fn(mytype) -> int, val: int}; tag mytype = {compute: native fn(mytype) -> int, val: int};
fn compute(i: mytype) -> int { ret i.val + 20; } fn compute(i: mytype) -> int { ret i.val + 20; }

View file

@ -1,4 +1,6 @@
resource finish<T>(arg: {val: T, fin: fn(T)}) { arg.fin(arg.val); } resource finish<T>(arg: {val: T, fin: native fn(T)}) {
arg.fin(arg.val);
}
fn main() { fn main() {
let box = @mutable 10; let box = @mutable 10;

View file

@ -5,11 +5,11 @@ import comm::send;
fn main() { test05(); } fn main() { test05(); }
fn mk_counter<A:copy>() -> sendfn(A) -> (A,uint) { fn mk_counter<A:copy>() -> fn~(A) -> (A,uint) {
// The only reason that the counter is generic is so that it closes // The only reason that the counter is generic is so that it closes
// over both a type descriptor and some data. // over both a type descriptor and some data.
let v = [mutable 0u]; let v = [mutable 0u];
ret sendfn(a: A) -> (A,uint) { ret fn~(a: A) -> (A,uint) {
let n = v[0]; let n = v[0];
v[0] = n + 1u; v[0] = n + 1u;
(a, n) (a, n)

View file

@ -11,7 +11,7 @@ fn make_generic_record<A: copy, B: copy>(a: A, b: B) -> pair<A,B> {
ret {a: a, b: b}; ret {a: a, b: b};
} }
fn test05_start(&&f: sendfn(&&float, &&str) -> pair<float, str>) { fn test05_start(&&f: fn~(&&float, &&str) -> pair<float, str>) {
let p = f(22.22f, "Hi"); let p = f(22.22f, "Hi");
log(debug, p); log(debug, p);
assert p.a == 22.22f; assert p.a == 22.22f;
@ -23,8 +23,8 @@ fn test05_start(&&f: sendfn(&&float, &&str) -> pair<float, str>) {
assert q.b == "Ho"; assert q.b == "Ho";
} }
fn spawn<A: copy, B: copy>(f: fn(sendfn(A,B)->pair<A,B>)) { fn spawn<A: copy, B: copy>(f: fn(fn~(A,B)->pair<A,B>)) {
let arg = sendfn(a: A, b: B) -> pair<A,B> { let arg = fn~(a: A, b: B) -> pair<A,B> {
ret make_generic_record(a, b); ret make_generic_record(a, b);
}; };
task::spawn {|| f(arg); }; task::spawn {|| f(arg); };

View file

@ -5,17 +5,17 @@ import comm::send;
fn main() { test05(); } fn main() { test05(); }
fn test05_start(&&f: sendfn(int)) { fn test05_start(&&f: fn~(int)) {
f(22); f(22);
} }
fn test05() { fn test05() {
let three = ~3; let three = ~3;
let fn_to_send = sendfn(n: int) { let fn_to_send = fn~(n: int) {
log(error, *three + n); // will copy x into the closure log(error, *three + n); // will copy x into the closure
assert(*three == 3); assert(*three == 3);
}; };
task::spawn(sendfn[move fn_to_send]() { task::spawn(fn~[move fn_to_send]() {
test05_start(fn_to_send); test05_start(fn_to_send);
}); });
} }

View file

@ -6,13 +6,13 @@ fn checktrue(rs: bool) -> bool { assert (rs); ret true; }
fn main() { let k = checktrue; evenk(42, k); oddk(45, k); } fn main() { let k = checktrue; evenk(42, k); oddk(45, k); }
fn evenk(n: int, k: fn(bool) -> bool) -> bool { fn evenk(n: int, k: native fn(bool) -> bool) -> bool {
#debug("evenk"); #debug("evenk");
log(debug, n); log(debug, n);
if n == 0 { be k(true); } else { be oddk(n - 1, k); } if n == 0 { be k(true); } else { be oddk(n - 1, k); }
} }
fn oddk(n: int, k: fn(bool) -> bool) -> bool { fn oddk(n: int, k: native fn(bool) -> bool) -> bool {
#debug("oddk"); #debug("oddk");
log(debug, n); log(debug, n);
if n == 0 { be k(false); } else { be evenk(n - 1, k); } if n == 0 { be k(false); } else { be evenk(n - 1, k); }

View file

@ -1,5 +1,5 @@
type lteq<T> = fn(T) -> bool; type lteq<T> = native fn(T) -> bool;
fn main(args: [str]) { } fn main(args: [str]) { }

View file

@ -5,7 +5,7 @@ fn range(lo: uint, hi: uint, it: block(uint)) {
while lo_ < hi { it(lo_); lo_ += 1u; } while lo_ < hi { it(lo_); lo_ += 1u; }
} }
fn create_index<T>(index: [{a: T, b: uint}], hash_fn: fn(T) -> uint) { fn create_index<T>(index: [{a: T, b: uint}], hash_fn: native fn(T) -> uint) {
range(0u, 256u) {|_i| let bucket: [T] = []; } range(0u, 256u) {|_i| let bucket: [T] = []; }
} }