From f9fbd86f52cf597b85359ade1ca60b8d6ebf7286 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 6 Oct 2011 12:26:12 +0200 Subject: [PATCH] Parse and typecheck by-value and by-ref arg specs Add sprinkle && throughout the compiler to make it typecheck again. Issue #1008 --- src/comp/front/attr.rs | 6 +- src/comp/front/config.rs | 43 +++++++------ src/comp/front/test.rs | 2 +- src/comp/lib/llvm.rs | 4 +- src/comp/metadata/common.rs | 2 +- src/comp/metadata/encoder.rs | 2 +- src/comp/metadata/tydecode.rs | 15 +++-- src/comp/metadata/tyencode.rs | 3 +- src/comp/middle/alias.rs | 4 +- src/comp/middle/ast_map.rs | 2 +- src/comp/middle/check_alt.rs | 4 +- src/comp/middle/freevars.rs | 4 +- src/comp/middle/mut.rs | 6 +- src/comp/middle/resolve.rs | 10 +-- src/comp/middle/trans.rs | 20 +++--- src/comp/middle/trans_objects.rs | 5 +- src/comp/middle/tstate/pre_post_conditions.rs | 10 +-- src/comp/middle/ty.rs | 34 +++++----- src/comp/middle/typeck.rs | 59 ++++++++++++------ src/comp/syntax/ast.rs | 2 +- src/comp/syntax/ast_util.rs | 4 +- src/comp/syntax/ext/simplext.rs | 4 +- src/comp/syntax/fold.rs | 62 +++++++++---------- src/comp/syntax/parse/parser.rs | 19 +++--- src/comp/syntax/print/pprust.rs | 30 ++++----- src/comp/syntax/visit.rs | 28 ++++----- src/comp/util/ppaux.rs | 4 +- src/lib/io.rs | 13 ++-- src/lib/list.rs | 2 +- src/lib/map.rs | 8 +-- src/lib/option.rs | 5 ++ src/lib/vec.rs | 11 ++++ 32 files changed, 230 insertions(+), 197 deletions(-) diff --git a/src/comp/front/attr.rs b/src/comp/front/attr.rs index a84c74b94f42..62c6a0282ce8 100644 --- a/src/comp/front/attr.rs +++ b/src/comp/front/attr.rs @@ -57,7 +57,7 @@ fn get_attr_name(attr: ast::attribute) -> ast::ident { fn find_meta_items_by_name(metas: [@ast::meta_item], name: ast::ident) -> [@ast::meta_item] { let filter = - bind fn (m: @ast::meta_item, name: ast::ident) -> + bind fn (&&m: @ast::meta_item, name: ast::ident) -> option::t<@ast::meta_item> { if get_meta_item_name(m) == name { option::some(m) @@ -134,7 +134,7 @@ fn contains_name(metas: [@ast::meta_item], name: ast::ident) -> bool { // FIXME: This needs to sort by meta_item variant in addition to the item name fn sort_meta_items(items: [@ast::meta_item]) -> [@ast::meta_item] { - fn lteq(ma: @ast::meta_item, mb: @ast::meta_item) -> bool { + fn lteq(&&ma: @ast::meta_item, &&mb: @ast::meta_item) -> bool { fn key(m: @ast::meta_item) -> ast::ident { alt m.node { ast::meta_word(name) { name } @@ -160,7 +160,7 @@ fn remove_meta_items_by_name(items: [@ast::meta_item], name: str) -> [@ast::meta_item] { let filter = - bind fn (item: @ast::meta_item, name: str) -> + bind fn (&&item: @ast::meta_item, name: str) -> option::t<@ast::meta_item> { if get_meta_item_name(item) != name { option::some(item) diff --git a/src/comp/front/config.rs b/src/comp/front/config.rs index cdd95bd6313a..cc2b35d8d9ec 100644 --- a/src/comp/front/config.rs +++ b/src/comp/front/config.rs @@ -20,7 +20,7 @@ fn strip_unconfigured_items(crate: @ast::crate) -> @ast::crate { ret res; } -fn filter_item(cfg: ast::crate_cfg, item: @ast::item) -> +fn filter_item(cfg: ast::crate_cfg, &&item: @ast::item) -> option::t<@ast::item> { if item_in_cfg(cfg, item) { option::some(item) } else { option::none } } @@ -29,11 +29,11 @@ fn fold_mod(cfg: ast::crate_cfg, m: ast::_mod, fld: fold::ast_fold) -> ast::_mod { let filter = bind filter_item(cfg, _); let filtered_items = vec::filter_map(filter, m.items); - ret {view_items: vec::map(fld.fold_view_item, m.view_items), - items: vec::map(fld.fold_item, filtered_items)}; + ret {view_items: vec::map_imm(fld.fold_view_item, m.view_items), + items: vec::map_imm(fld.fold_item, filtered_items)}; } -fn filter_native_item(cfg: ast::crate_cfg, item: @ast::native_item) -> +fn filter_native_item(cfg: ast::crate_cfg, &&item: @ast::native_item) -> option::t<@ast::native_item> { if native_item_in_cfg(cfg, item) { option::some(item) @@ -46,11 +46,11 @@ fn fold_native_mod(cfg: ast::crate_cfg, nm: ast::native_mod, let filtered_items = vec::filter_map(filter, nm.items); ret {native_name: nm.native_name, abi: nm.abi, - view_items: vec::map(fld.fold_view_item, nm.view_items), + view_items: vec::map_imm(fld.fold_view_item, nm.view_items), items: filtered_items}; } -fn filter_stmt(cfg: ast::crate_cfg, stmt: @ast::stmt) -> +fn filter_stmt(cfg: ast::crate_cfg, &&stmt: @ast::stmt) -> option::t<@ast::stmt> { alt stmt.node { ast::stmt_decl(decl, _) { @@ -71,8 +71,8 @@ fn fold_block(cfg: ast::crate_cfg, b: ast::blk_, fld: fold::ast_fold) -> ast::blk_ { let filter = bind filter_stmt(cfg, _); let filtered_stmts = vec::filter_map(filter, b.stmts); - ret {stmts: vec::map(fld.fold_stmt, filtered_stmts), - expr: option::map(fld.fold_expr, b.expr), + ret {stmts: vec::map_imm(fld.fold_stmt, filtered_stmts), + expr: option::map_imm(fld.fold_expr, b.expr), id: b.id, rules: b.rules}; } @@ -97,21 +97,20 @@ fn in_cfg(cfg: ast::crate_cfg, attrs: [ast::attribute]) -> bool { // Pull the inner meta_items from the #[cfg(meta_item, ...)] attributes, // so we can match against them. This is the list of configurations for // which the item is valid - let item_cfg_metas = - { - fn extract_metas(inner_items: [@ast::meta_item], - cfg_item: @ast::meta_item) -> [@ast::meta_item] { - alt cfg_item.node { - ast::meta_list(name, items) { - assert (name == "cfg"); - inner_items + items - } - _ { inner_items } - } + let item_cfg_metas = { + fn extract_metas(inner_items: [@ast::meta_item], + &&cfg_item: @ast::meta_item) -> [@ast::meta_item] { + alt cfg_item.node { + ast::meta_list(name, items) { + assert (name == "cfg"); + inner_items + items + } + _ { inner_items } } - let cfg_metas = attr::attr_metas(item_cfg_attrs); - vec::foldl(extract_metas, [], cfg_metas) - }; + } + let cfg_metas = attr::attr_metas(item_cfg_attrs); + vec::foldl(extract_metas, [], cfg_metas) + }; for cfg_mi: @ast::meta_item in item_cfg_metas { if attr::contains(cfg, cfg_mi) { ret true; } diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs index 9aed642a2d5d..030a4faf5f98 100644 --- a/src/comp/front/test.rs +++ b/src/comp/front/test.rs @@ -56,7 +56,7 @@ fn fold_mod(_cx: test_ctxt, m: ast::_mod, fld: fold::ast_fold) -> ast::_mod { // the one we're going to add. FIXME: This is sloppy. Instead we should // have some mechanism to indicate to the translation pass which function // we want to be main. - fn nomain(item: @ast::item) -> option::t<@ast::item> { + fn nomain(&&item: @ast::item) -> option::t<@ast::item> { alt item.node { ast::item_fn(f, _) { if item.ident == "main" { diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index 83f5f4d8ef68..c47f75135d7c 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -909,9 +909,9 @@ obj type_names(type_names: std::map::hashmap, fn mk_type_names() -> type_names { let nt = std::map::new_str_hash::(); - fn hash(t: TypeRef) -> uint { ret t as uint; } + fn hash(&&t: TypeRef) -> uint { ret t as uint; } - fn eq(a: TypeRef, b: TypeRef) -> bool { ret a as uint == b as uint; } + fn eq(&&a: TypeRef, &&b: TypeRef) -> bool { ret a as uint == b as uint; } let hasher: std::map::hashfn = hash; let eqer: std::map::eqfn = eq; diff --git a/src/comp/metadata/common.rs b/src/comp/metadata/common.rs index a22dfa62d2bb..134e43d62809 100644 --- a/src/comp/metadata/common.rs +++ b/src/comp/metadata/common.rs @@ -65,7 +65,7 @@ const tag_crate_dep: uint = 0x26u; const tag_items_data_item_inlineness: uint = 0x27u; // djb's cdb hashes. -fn hash_node_id(node_id: int) -> uint { ret 177573u ^ (node_id as uint); } +fn hash_node_id(&&node_id: int) -> uint { ret 177573u ^ (node_id as uint); } fn hash_path(s: str) -> uint { let h = 5381u; diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs index bf43b158be72..f8145c306c86 100644 --- a/src/comp/metadata/encoder.rs +++ b/src/comp/metadata/encoder.rs @@ -427,7 +427,7 @@ fn encode_index(ebml_w: ebml::writer, buckets: [@[entry]], fn write_str(writer: io::writer, s: str) { writer.write_str(s); } -fn write_int(writer: io::writer, n: int) { +fn write_int(writer: io::writer, &&n: int) { writer.write_be_uint(n as uint, 4u); } diff --git a/src/comp/metadata/tydecode.rs b/src/comp/metadata/tydecode.rs index 3158b623439e..e1123c3b6232 100644 --- a/src/comp/metadata/tydecode.rs +++ b/src/comp/metadata/tydecode.rs @@ -380,14 +380,13 @@ fn parse_ty_fn(st: @pstate, sd: str_def) -> assert (next(st) as char == '['); let inputs: [ty::arg] = []; while peek(st) as char != ']' { - let mode = ast::by_ref; - if peek(st) as char == '&' { - mode = ast::by_mut_ref; - st.pos += 1u; - } else if peek(st) as char == '-' { - mode = ast::by_move; - st.pos += 1u; - } + let mode = alt peek(st) as char { + '&' { ast::by_mut_ref } + '-' { ast::by_move } + '=' { ast::by_ref } + '+' { ast::by_val } + }; + st.pos += 1u; inputs += [{mode: mode, ty: parse_ty(st, sd)}]; } st.pos += 1u; // eat the ']' diff --git a/src/comp/metadata/tyencode.rs b/src/comp/metadata/tyencode.rs index 55c3b2bc5b71..4867b80e125a 100644 --- a/src/comp/metadata/tyencode.rs +++ b/src/comp/metadata/tyencode.rs @@ -207,7 +207,8 @@ fn enc_ty_fn(w: io::writer, cx: @ctxt, args: [ty::arg], out: ty::t, alt arg.mode { by_mut_ref. { w.write_char('&'); } by_move. { w.write_char('-'); } - by_ref. { } + by_ref. { w.write_char('='); } + by_val. { w.write_char('+'); } } enc_ty(w, cx, arg.ty); } diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 03a060a57fd5..5d9d736f2097 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -251,10 +251,8 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] { mutable ok: valid, mutable copied: alt arg_t.mode { ast::by_move. { copied } - ast::by_ref. { - i + 1u == by_ref ? not_allowed : not_copied - } ast::by_mut_ref. { not_allowed } + _ { i + 1u == by_ref ? not_allowed : not_copied } }}]; i += 1u; } diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs index ce8c983c0f9b..9b89ec633314 100644 --- a/src/comp/middle/ast_map.rs +++ b/src/comp/middle/ast_map.rs @@ -76,7 +76,7 @@ fn map_expr(cx: ctx, ex: @expr) { } fn new_smallintmap_int_adapter<@V>() -> std::map::hashmap { - let key_idx = fn (key: int) -> uint { key as uint }; + let key_idx = fn (&&key: int) -> uint { key as uint }; let idx_key = fn (idx: uint) -> int { idx as int }; ret new_smallintmap_adapter(key_idx, idx_key); } diff --git a/src/comp/middle/check_alt.rs b/src/comp/middle/check_alt.rs index 236b04033588..a3b58cf16001 100644 --- a/src/comp/middle/check_alt.rs +++ b/src/comp/middle/check_alt.rs @@ -11,7 +11,7 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) { tcx.sess.abort_if_errors(); } -fn check_expr(tcx: ty::ctxt, ex: @expr, s: (), v: visit::vt<()>) { +fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) { visit::visit_expr(ex, s, v); alt ex.node { expr_alt(_, arms) { check_arms(tcx, arms); } _ { } } } @@ -123,7 +123,7 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool { } } -fn check_local(tcx: ty::ctxt, loc: @local, s: (), v: visit::vt<()>) { +fn check_local(tcx: ty::ctxt, loc: @local, &&s: (), v: visit::vt<()>) { visit::visit_local(loc, s, v); if is_refutable(tcx, loc.node.pat) { tcx.sess.span_err(loc.node.pat.span, diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs index e0a05a9f63ea..5a6ed3283e76 100644 --- a/src/comp/middle/freevars.rs +++ b/src/comp/middle/freevars.rs @@ -29,10 +29,10 @@ fn collect_freevars(def_map: resolve::def_map, walker: fn(visit::vt)) -> let seen = new_int_hash(); let refs = @mutable []; - fn ignore_item(_i: @ast::item, _depth: int, _v: visit::vt) { } + fn ignore_item(_i: @ast::item, &&_depth: int, _v: visit::vt) { } let walk_expr = - lambda (expr: @ast::expr, depth: int, v: visit::vt) { + lambda (expr: @ast::expr, &&depth: int, v: visit::vt) { alt expr.node { ast::expr_fn(f) { if f.proto == ast::proto_block || diff --git a/src/comp/middle/mut.rs b/src/comp/middle/mut.rs index 7952353ca2f9..836f6de87e31 100644 --- a/src/comp/middle/mut.rs +++ b/src/comp/middle/mut.rs @@ -131,7 +131,7 @@ fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) { }); } -fn visit_decl(cx: @ctx, d: @decl, e: (), v: visit::vt<()>) { +fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) { visit::visit_decl(d, e, v); alt d.node { decl_local(locs) { @@ -148,7 +148,7 @@ fn visit_decl(cx: @ctx, d: @decl, e: (), v: visit::vt<()>) { } } -fn visit_expr(cx: @ctx, ex: @expr, e: (), v: visit::vt<()>) { +fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) { alt ex.node { expr_call(f, args) { check_call(cx, f, args); } expr_swap(lhs, rhs) { @@ -225,7 +225,7 @@ fn check_call(cx: @ctx, f: @expr, args: [@expr]) { alt arg_t.mode { by_mut_ref. { check_lval(cx, args[i], msg_mut_ref); } by_move. { check_lval(cx, args[i], msg_move_out); } - by_ref. {} + _ {} } i += 1u; } diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 7018f8d1a858..fe95ecc0b852 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -1239,7 +1239,7 @@ fn mie_span(mie: mod_index_entry) -> span { }; } -fn check_item(e: @env, i: @ast::item, x: (), v: vt<()>) { +fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) { fn typaram_names(tps: [ast::ty_param]) -> [ident] { let x: [ast::ident] = []; for tp: ast::ty_param in tps { x += [tp.ident]; } @@ -1276,7 +1276,7 @@ fn check_pat(ch: checker, p: @ast::pat) { } } -fn check_arm(e: @env, a: ast::arm, x: (), v: vt<()>) { +fn check_arm(e: @env, a: ast::arm, &&x: (), v: vt<()>) { visit::visit_arm(a, x, v); let ch0 = checker(*e, "binding"); check_pat(ch0, a.pats[0]); @@ -1306,7 +1306,7 @@ fn check_arm(e: @env, a: ast::arm, x: (), v: vt<()>) { } } -fn check_block(e: @env, b: ast::blk, x: (), v: vt<()>) { +fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) { visit::visit_block(b, x, v); let values = checker(*e, "value"); let types = checker(*e, "type"); @@ -1359,7 +1359,7 @@ fn check_fn(e: env, sp: span, f: ast::_fn) { ensure_unique(e, sp, f.decl.inputs, arg_name, "argument"); } -fn check_expr(e: @env, ex: @ast::expr, x: (), v: vt<()>) { +fn check_expr(e: @env, ex: @ast::expr, &&x: (), v: vt<()>) { alt ex.node { ast::expr_rec(fields, _) { fn field_name(f: ast::field) -> ident { ret f.node.ident; } @@ -1370,7 +1370,7 @@ fn check_expr(e: @env, ex: @ast::expr, x: (), v: vt<()>) { visit::visit_expr(ex, x, v); } -fn check_ty(e: @env, ty: @ast::ty, x: (), v: vt<()>) { +fn check_ty(e: @env, ty: @ast::ty, &&x: (), v: vt<()>) { alt ty.node { ast::ty_rec(fields) { fn field_name(f: ast::ty_field) -> ident { ret f.node.ident; } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 10418cdfc542..294c9dfd15e0 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3699,7 +3699,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef, // be inspected. It's important for the value // to have type lldestty0 (the callee's expected type). val = llvm::LLVMGetUndef(lldestty0); - } else if arg.mode == ast::by_ref { + } else if arg.mode == ast::by_ref || arg.mode == ast::by_val { let copied = false; if !lv.is_mem && type_is_immediate(ccx, e_ty) { val = do_spill_noroot(bcx, val); @@ -4439,9 +4439,9 @@ fn lval_to_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt { // latter group "immediates" and, in some circumstances when we know we have a // pointer (or need one), perform load/store operations based on the // immediate-ness of the type. +// FIXME simply call the version in ty.rs immediately fn type_is_immediate(ccx: @crate_ctxt, t: ty::t) -> bool { - ret ty::type_is_scalar(ccx.tcx, t) || ty::type_is_boxed(ccx.tcx, t) || - ty::type_is_unique_box(ccx.tcx, t) || ty::type_is_native(ccx.tcx, t); + ty::type_is_immediate(ccx.tcx, t) } fn do_spill(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result { @@ -5144,7 +5144,11 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg], for aarg: ast::arg in args { let arg_ty = arg_tys[arg_n].ty; alt aarg.mode { - ast::by_ref. { + ast::by_move. { + add_clean(bcx, fcx.llargs.get(aarg.id), arg_ty); + } + ast::by_mut_ref. { } + _ { let mutated = !ignore_mut && fcx.lcx.ccx.mut_map.contains_key(aarg.id); @@ -5160,10 +5164,6 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg], add_clean(bcx, alloc, arg_ty); } } - ast::by_move. { - add_clean(bcx, fcx.llargs.get(aarg.id), arg_ty); - } - _ { } } arg_n += 1u; } @@ -5790,7 +5790,7 @@ fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str, } fn convert_arg_to_i32(cx: @block_ctxt, v: ValueRef, t: ty::t, mode: ty::mode) -> ValueRef { - if mode == ast::by_ref { + if mode == ast::by_ref || mode == ast::by_val { if ty::type_is_integral(bcx_tcx(cx), t) { // FIXME: would be nice to have a postcondition that says // if a type is integral, then it has static size (#586) @@ -5845,7 +5845,7 @@ fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str, let i = arg_n; for arg: ty::arg in args { let llarg = llvm::LLVMGetParam(fcx.llfn, i); - if arg.mode == ast::by_ref { + if arg.mode == ast::by_ref || arg.mode == ast::by_val { llarg = load_if_immediate(bcx, llarg, arg.ty); } assert (llarg as int != 0); diff --git a/src/comp/middle/trans_objects.rs b/src/comp/middle/trans_objects.rs index 3c42ce473ddd..b9152d30ad2e 100644 --- a/src/comp/middle/trans_objects.rs +++ b/src/comp/middle/trans_objects.rs @@ -41,7 +41,8 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id, // we're creating. let fn_args: [ast::arg] = []; for f: ast::obj_field in ob.fields { - fn_args += [{mode: ast::by_ref, ty: f.ty, ident: f.ident, id: f.id}]; + fn_args += [{mode: ast::by_ref, ty: f.ty, ident: f.ident, + id: f.id}]; } let fcx = new_fn_ctxt(cx, sp, llctor_decl); @@ -397,7 +398,7 @@ tag vtbl_mthd { } // Alphabetize ast::methods by ident. A helper for create_vtbl. -fn ast_mthd_lteq(a: @ast::method, b: @ast::method) -> bool { +fn ast_mthd_lteq(&&a: @ast::method, &&b: @ast::method) -> bool { ret str::lteq(a.node.ident, b.node.ident); } diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 9f2f13074783..036cf8ab0cec 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -99,10 +99,10 @@ fn find_pre_post_exprs(fcx: fn_ctxt, args: [@expr], id: node_id) { fn get_pp(ccx: crate_ctxt, e: @expr) -> pre_and_post { ret expr_pp(ccx, e); } - let pps = vec::map::<@expr, pre_and_post>(bind get_pp(fcx.ccx, _), args); + let pps = vec::map_imm(bind get_pp(fcx.ccx, _), args); set_pre_and_post(fcx.ccx, id, seq_preconds(fcx, pps), - seq_postconds(fcx, vec::map(get_post, pps))); + seq_postconds(fcx, vec::map_imm(get_post, pps))); } fn find_pre_post_loop(fcx: fn_ctxt, l: @local, index: @expr, body: blk, @@ -476,8 +476,8 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { } let alt_pps = []; for a: arm in alts { alt_pps += [do_an_alt(fcx, a)]; } - fn combine_pp(antec: pre_and_post, fcx: fn_ctxt, pp: pre_and_post, - next: pre_and_post) -> pre_and_post { + fn combine_pp(antec: pre_and_post, fcx: fn_ctxt, &&pp: pre_and_post, + &&next: pre_and_post) -> pre_and_post { union(pp.precondition, seq_preconds(fcx, [antec, next])); intersect(pp.postcondition, next.postcondition); ret pp; @@ -694,7 +694,7 @@ fn find_pre_post_block(fcx: fn_ctxt, b: blk) { */ } for s: @stmt in b.node.stmts { do_one_(fcx, s); } - fn do_inner_(fcx: fn_ctxt, e: @expr) { find_pre_post_expr(fcx, e); } + fn do_inner_(fcx: fn_ctxt, &&e: @expr) { find_pre_post_expr(fcx, e); } let do_inner = bind do_inner_(fcx, _); option::map::<@expr, ()>(do_inner, b.node.expr); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index ec9821d6d26a..faf11cb691a4 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -160,6 +160,7 @@ export type_is_native; export type_is_nil; export type_is_pod; export type_is_scalar; +export type_is_immediate; export type_is_sequence; export type_is_signed; export type_is_structural; @@ -916,6 +917,12 @@ pure fn type_is_scalar(cx: ctxt, ty: t) -> bool { } } +// FIXME maybe inline this for speed? +fn type_is_immediate(cx: ctxt, ty: t) -> bool { + ret type_is_scalar(cx, ty) || type_is_boxed(cx, ty) || + type_is_unique_box(cx, ty) || type_is_native(cx, ty); +} + fn type_has_pointers(cx: ctxt, ty: t) -> bool { alt cx.has_pointer_cache.find(ty) { some(result) { ret result; } @@ -924,14 +931,8 @@ fn type_has_pointers(cx: ctxt, ty: t) -> bool { let result = false; alt struct(cx, ty) { - - - // scalar types - ty_nil. { - /* no-op */ - - } + ty_nil. {/* no-op */ } ty_bot. {/* no-op */ } ty_bool. {/* no-op */ } ty_int. {/* no-op */ } @@ -1446,14 +1447,14 @@ fn hash_type_info(st: sty, cname_opt: option::t) -> uint { ret h; } -fn hash_raw_ty(rt: @raw_t) -> uint { ret rt.hash; } +fn hash_raw_ty(&&rt: @raw_t) -> uint { ret rt.hash; } -fn hash_ty(typ: t) -> uint { ret typ; } +fn hash_ty(&&typ: t) -> uint { ret typ; } // Type equality. This function is private to this module (and slow); external // users should use `eq_ty()` instead. -fn eq_int(x: uint, y: uint) -> bool { ret x == y; } +fn eq_int(&&x: uint, &&y: uint) -> bool { ret x == y; } fn arg_eq(eq: fn(T, T) -> bool, a: @sp_constr_arg, b: @sp_constr_arg) -> bool { @@ -1495,7 +1496,7 @@ fn constrs_eq(cs: [@constr], ds: [@constr]) -> bool { // An expensive type equality function. This function is private to this // module. -fn eq_raw_ty(a: @raw_t, b: @raw_t) -> bool { +fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool { // Check hashes (fast path). if a.hash != b.hash { ret false; } @@ -1518,7 +1519,7 @@ fn eq_raw_ty(a: @raw_t, b: @raw_t) -> bool { // This is the equality function the public should use. It works as long as // the types are interned. -fn eq_ty(a: t, b: t) -> bool { ret a == b; } +fn eq_ty(&&a: t, &&b: t) -> bool { ret a == b; } // Type lookups @@ -1954,12 +1955,15 @@ mod unify { let actual_input = actual_inputs[i]; // Unify the result modes. - let result_mode; - if expected_input.mode != actual_input.mode { + let result_mode = if expected_input.mode == ast::mode_infer { + actual_input.mode + } else if actual_input.mode == ast::mode_infer { + expected_input.mode + } else if expected_input.mode != actual_input.mode { ret fn_common_res_err (ures_err(terr_mode_mismatch(expected_input.mode, actual_input.mode))); - } else { result_mode = expected_input.mode; } + } else { expected_input.mode }; let result = unify_step(cx, expected_input.ty, actual_input.ty); alt result { ures_ok(rty) { result_ins += [{mode: result_mode, ty: rty}]; } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index bdf8b91c8ff7..088e6eec6f56 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -224,7 +224,27 @@ fn type_is_scalar(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool { // Parses the programmer's textual representation of a type into our internal // notion of a type. `getter` is a function that returns the type // corresponding to a definition ID: +fn default_arg_mode_for_ty(tcx: ty::ctxt, m: ast::mode, + ty: ty::t) -> ast::mode { + alt m { + ast::mode_infer. { + alt ty::struct(tcx, ty) { + ty::ty_var(_) { ast::mode_infer } + _ { + if ty::type_is_immediate(tcx, ty) { ast::by_val } + else { ast::by_ref } + } + } + } + _ { m } + } +} fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, ast_ty: @ast::ty) -> ty::t { + fn ast_arg_to_arg(tcx: ty::ctxt, getter: ty_getter, arg: ast::ty_arg) + -> {mode: ty::mode, ty: ty::t} { + let ty = ast_ty_to_ty(tcx, getter, arg.node.ty); + ret {mode: default_arg_mode_for_ty(tcx, arg.node.mode, ty), ty: ty}; + } alt tcx.ast_ty_to_ty_cache.find(ast_ty) { some(some(ty)) { ret ty; } some(none.) { @@ -237,10 +257,6 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, ast_ty: @ast::ty) -> ty::t { } /* go on */ tcx.ast_ty_to_ty_cache.insert(ast_ty, none::); - fn ast_arg_to_arg(tcx: ty::ctxt, getter: ty_getter, arg: ast::ty_arg) -> - {mode: ty::mode, ty: ty::t} { - ret {mode: arg.node.mode, ty: ast_ty_to_ty(tcx, getter, arg.node.ty)}; - } fn ast_mt_to_mt(tcx: ty::ctxt, getter: ty_getter, mt: ast::mt) -> ty::mt { ret {ty: ast_ty_to_ty(tcx, getter, mt.ty), mut: mt.mut}; } @@ -295,7 +311,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, ast_ty: @ast::ty) -> ty::t { typ = ty::mk_ptr(tcx, ast_mt_to_mt(tcx, getter, mt)); } ast::ty_tup(fields) { - let flds = vec::map(bind ast_ty_to_ty(tcx, getter, _), fields); + let flds = vec::map_imm(bind ast_ty_to_ty(tcx, getter, _), fields); typ = ty::mk_tup(tcx, flds); } ast::ty_rec(fields) { @@ -550,9 +566,8 @@ mod collect { ret tpt; } fn ty_of_arg(cx: @ctxt, a: ast::arg) -> ty::arg { - let f = bind getter(cx, _); - let tt = ast_ty_to_ty(cx.tcx, f, a.ty); - ret {mode: a.mode, ty: tt}; + let ty = ast_ty_to_ty(cx.tcx, bind getter(cx, _), a.ty); + {mode: default_arg_mode_for_ty(cx.tcx, a.mode, ty), ty: ty} } fn ty_of_method(cx: @ctxt, m: @ast::method) -> ty::method { let get = bind getter(cx, _); @@ -1216,7 +1231,7 @@ fn gather_locals(ccx: @crate_ctxt, f: ast::_fn, id: ast::node_id, // Add explicitly-declared locals. let visit_local = - lambda (local: @ast::local, e: (), v: visit::vt<()>) { + lambda (local: @ast::local, &&e: (), v: visit::vt<()>) { let local_ty = ast_ty_to_ty_crate_infer(ccx, local.node.ty); assign(local.node.id, ident_for_local(local), local_ty); visit::visit_local(local, e, v); @@ -1224,7 +1239,7 @@ fn gather_locals(ccx: @crate_ctxt, f: ast::_fn, id: ast::node_id, // Add pattern bindings. let visit_pat = - lambda (p: @ast::pat, e: (), v: visit::vt<()>) { + lambda (p: @ast::pat, &&e: (), v: visit::vt<()>) { alt p.node { ast::pat_bind(ident) { assign(p.id, ident, none); } _ {/* no-op */ } @@ -2022,16 +2037,16 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, write::ty_only_fixup(fcx, id, result_ty); } ast::expr_fn(f) { - let cx = @{tcx: tcx}; let convert = bind ast_ty_to_ty_crate_tyvar(fcx, _); - let ty_of_arg = - lambda (a: ast::arg) -> ty::arg { - let tt = ast_ty_to_ty_crate_tyvar(fcx, a.ty); - ret {mode: a.mode, ty: tt}; - }; - let fty = - collect::ty_of_fn_decl(cx, convert, ty_of_arg, f.decl, f.proto, - [], none).ty; + let ty_of_arg = lambda (a: ast::arg) -> ty::arg { + let tt = ast_ty_to_ty_crate_tyvar(fcx, a.ty); + ret {mode: default_arg_mode_for_ty(fcx.ccx.tcx, a.mode, tt), + ty: tt}; + }; + let cx = @{tcx: tcx}; + let fty = collect::ty_of_fn_decl(cx, convert, ty_of_arg, f.decl, + f.proto, [], none).ty; + write::ty_only_fixup(fcx, id, fty); // Unify the type of the function with the expected type before we @@ -2041,6 +2056,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, unify(fcx, expr.span, expected, fty); check_fn(fcx.ccx, f, id, some(fcx)); + if f.proto == ast::proto_block { + write::ty_only_fixup(fcx, id, expected); + } } ast::expr_block(b) { // If this is an unchecked block, turn off purity-checking @@ -2301,7 +2319,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, // FIXME: These next three functions are largely ripped off from // similar ones in collect::. Is there a better way to do this? fn ty_of_arg(ccx: @crate_ctxt, a: ast::arg) -> ty::arg { - ret {mode: a.mode, ty: ast_ty_to_ty_crate(ccx, a.ty)}; + let ty = ast_ty_to_ty_crate(ccx, a.ty); + ret {mode: default_arg_mode_for_ty(ccx.tcx, a.mode, ty), ty: ty}; } fn ty_of_method(ccx: @crate_ctxt, m: @ast::method) -> ty::method { diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 52aa6cb31d92..1864af6de9e1 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -132,7 +132,7 @@ tag unop { deref; not; neg; } -tag mode { by_ref; by_mut_ref; by_move; } +tag mode { by_ref; by_val; by_mut_ref; by_move; mode_infer; } type stmt = spanned; diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index c4d0272b95fa..d70b63dac675 100644 --- a/src/comp/syntax/ast_util.rs +++ b/src/comp/syntax/ast_util.rs @@ -180,9 +180,9 @@ fn is_constraint_arg(e: @expr) -> bool { } } -fn eq_ty(a: @ty, b: @ty) -> bool { ret std::box::ptr_eq(a, b); } +fn eq_ty(&&a: @ty, &&b: @ty) -> bool { ret std::box::ptr_eq(a, b); } -fn hash_ty(t: @ty) -> uint { ret t.span.lo << 16u + t.span.hi; } +fn hash_ty(&&t: @ty) -> uint { ret t.span.lo << 16u + t.span.hi; } fn block_from_expr(e: @expr) -> blk { let blk_ = checked_blk([], option::some::<@expr>(e), e.id); diff --git a/src/comp/syntax/ext/simplext.rs b/src/comp/syntax/ext/simplext.rs index 528b2cdc7565..5fafcdbb437c 100644 --- a/src/comp/syntax/ext/simplext.rs +++ b/src/comp/syntax/ext/simplext.rs @@ -266,7 +266,7 @@ fn transcribe_exprs(cx: ext_ctxt, b: bindings, idx_path: @mutable [uint], recur: fn(@expr) -> @expr, exprs: [@expr]) -> [@expr] { alt elts_to_ell(cx, exprs) { {pre: pre, rep: repeat_me_maybe, post: post} { - let res = vec::map(recur, pre); + let res = vec::map_imm(recur, pre); alt repeat_me_maybe { none. { } some(repeat_me) { @@ -315,7 +315,7 @@ fn transcribe_exprs(cx: ext_ctxt, b: bindings, idx_path: @mutable [uint], } } } - res += vec::map(recur, post); + res += vec::map_imm(recur, post); ret res; } } diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index bf8504f3c1aa..edee54fb808c 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -110,7 +110,7 @@ fn fold_meta_item_(mi: @meta_item, fld: ast_fold) -> @meta_item { meta_word(id) { meta_word(fld.fold_ident(id)) } meta_list(id, mis) { let fold_meta_item = bind fold_meta_item_(_, fld); - meta_list(id, vec::map(fold_meta_item, mis)) + meta_list(id, vec::map_imm(fold_meta_item, mis)) } meta_name_value(id, s) { meta_name_value(fld.fold_ident(id), s) @@ -153,10 +153,10 @@ fn noop_fold_crate(c: crate_, fld: ast_fold) -> crate_ { let fold_meta_item = bind fold_meta_item_(_, fld); let fold_attribute = bind fold_attribute_(_, fold_meta_item); - ret {directives: vec::map(fld.fold_crate_directive, c.directives), + ret {directives: vec::map_imm(fld.fold_crate_directive, c.directives), module: fld.fold_mod(c.module), attrs: vec::map(fold_attribute, c.attrs), - config: vec::map(fold_meta_item, c.config)}; + config: vec::map_imm(fold_meta_item, c.config)}; } fn noop_fold_crate_directive(cd: crate_directive_, fld: ast_fold) -> @@ -167,7 +167,7 @@ fn noop_fold_crate_directive(cd: crate_directive_, fld: ast_fold) -> } cdir_dir_mod(id, fname, cds, attrs) { cdir_dir_mod(fld.fold_ident(id), fname, - vec::map(fld.fold_crate_directive, cds), attrs) + vec::map_imm(fld.fold_crate_directive, cds), attrs) } cdir_view_item(vi) { cdir_view_item(fld.fold_view_item(vi)) } cdir_syntax(_) { cd } @@ -198,8 +198,8 @@ fn noop_fold_native_item(ni: @native_item, fld: ast_fold) -> @native_item { il: fdec.il, cf: fdec.cf, constraints: - vec::map(fld.fold_constr, - fdec.constraints)}, typms) + vec::map_imm(fld.fold_constr, + fdec.constraints)}, typms) } }, id: ni.id, @@ -237,8 +237,8 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { } item_obj(o, typms, d) { item_obj({fields: vec::map(fold_obj_field, o.fields), - methods: vec::map(fld.fold_method, o.methods)}, typms, - d) + methods: vec::map_imm(fld.fold_method, o.methods)}, + typms, d) } item_res(dtor, did, typms, cid) { item_res(fld.fold_fn(dtor), did, typms, cid) @@ -252,8 +252,8 @@ fn noop_fold_method(m: method_, fld: ast_fold) -> method_ { fn noop_fold_block(b: blk_, fld: ast_fold) -> blk_ { - ret {stmts: vec::map(fld.fold_stmt, b.stmts), - expr: option::map(fld.fold_expr, b.expr), + ret {stmts: vec::map_imm(fld.fold_stmt, b.stmts), + expr: option::map_imm(fld.fold_expr, b.expr), id: b.id, rules: b.rules}; } @@ -269,8 +269,8 @@ fn noop_fold_stmt(s: stmt_, fld: ast_fold) -> stmt_ { } fn noop_fold_arm(a: arm, fld: ast_fold) -> arm { - ret {pats: vec::map(fld.fold_pat, a.pats), - guard: option::map(fld.fold_expr, a.guard), + ret {pats: vec::map_imm(fld.fold_pat, a.pats), + guard: option::map_imm(fld.fold_expr, a.guard), body: fld.fold_block(a.body)}; } @@ -280,7 +280,7 @@ fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ { pat_bind(ident) { pat_bind(fld.fold_ident(ident)) } pat_lit(_) { p } pat_tag(pth, pats) { - pat_tag(fld.fold_path(pth), vec::map(fld.fold_pat, pats)) + pat_tag(fld.fold_path(pth), vec::map_imm(fld.fold_pat, pats)) } pat_rec(fields, etc) { let fs = []; @@ -289,7 +289,7 @@ fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ { } pat_rec(fs, etc) } - pat_tup(elts) { pat_tup(vec::map(fld.fold_pat, elts)) } + pat_tup(elts) { pat_tup(vec::map_imm(fld.fold_pat, elts)) } pat_box(inner) { pat_box(fld.fold_pat(inner)) } pat_uniq(inner) { pat_uniq(fld.fold_pat(inner)) } pat_range(_, _) { p } @@ -334,8 +334,8 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { option::some(vec::map(fold_anon_obj_field, v)) } }, - methods: vec::map(fld.fold_method, ao.methods), - inner_obj: option::map(fld.fold_expr, ao.inner_obj)} + methods: vec::map_imm(fld.fold_method, ao.methods), + inner_obj: option::map_imm(fld.fold_expr, ao.inner_obj)} } let fold_anon_obj = bind fold_anon_obj_(_, fld); @@ -347,15 +347,15 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { } expr_rec(fields, maybe_expr) { expr_rec(vec::map(fold_field, fields), - option::map(fld.fold_expr, maybe_expr)) + option::map_imm(fld.fold_expr, maybe_expr)) } - expr_tup(elts) { expr_tup(vec::map(fld.fold_expr, elts)) } + expr_tup(elts) { expr_tup(vec::map_imm(fld.fold_expr, elts)) } expr_call(f, args) { expr_call(fld.fold_expr(f), fld.map_exprs(fld.fold_expr, args)) } expr_self_method(id) { expr_self_method(fld.fold_ident(id)) } expr_bind(f, args) { - let opt_map_se = bind option::map(fld.fold_expr, _); + let opt_map_se = bind option::map_imm(fld.fold_expr, _); expr_bind(fld.fold_expr(f), vec::map(opt_map_se, args)) } expr_binary(binop, lhs, rhs) { @@ -366,7 +366,7 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { expr_cast(expr, ty) { expr_cast(fld.fold_expr(expr), ty) } expr_if(cond, tr, fl) { expr_if(fld.fold_expr(cond), fld.fold_block(tr), - option::map(fld.fold_expr, fl)) + option::map_imm(fld.fold_expr, fl)) } expr_ternary(cond, tr, fl) { expr_ternary(fld.fold_expr(cond), fld.fold_expr(tr), @@ -411,18 +411,18 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { expr_index(fld.fold_expr(el), fld.fold_expr(er)) } expr_path(pth) { expr_path(fld.fold_path(pth)) } - expr_fail(e) { expr_fail(option::map(fld.fold_expr, e)) } + expr_fail(e) { expr_fail(option::map_imm(fld.fold_expr, e)) } expr_break. { e } expr_cont. { e } - expr_ret(e) { expr_ret(option::map(fld.fold_expr, e)) } - expr_put(e) { expr_put(option::map(fld.fold_expr, e)) } + expr_ret(e) { expr_ret(option::map_imm(fld.fold_expr, e)) } + expr_put(e) { expr_put(option::map_imm(fld.fold_expr, e)) } expr_be(e) { expr_be(fld.fold_expr(e)) } expr_log(lv, e) { expr_log(lv, fld.fold_expr(e)) } expr_assert(e) { expr_assert(fld.fold_expr(e)) } expr_check(m, e) { expr_check(m, fld.fold_expr(e)) } expr_if_check(cond, tr, fl) { expr_if_check(fld.fold_expr(cond), fld.fold_block(tr), - option::map(fld.fold_expr, fl)) + option::map_imm(fld.fold_expr, fl)) } expr_anon_obj(ao) { expr_anon_obj(fold_anon_obj(ao)) } expr_mac(mac) { expr_mac(fold_mac(mac)) } @@ -448,22 +448,22 @@ fn noop_fold_fn(f: _fn, fld: ast_fold) -> _fn { purity: f.decl.purity, il: f.decl.il, cf: f.decl.cf, - constraints: vec::map(fld.fold_constr, f.decl.constraints)}, + constraints: vec::map_imm(fld.fold_constr, f.decl.constraints)}, proto: f.proto, body: fld.fold_block(f.body)}; } // ...nor do modules fn noop_fold_mod(m: _mod, fld: ast_fold) -> _mod { - ret {view_items: vec::map(fld.fold_view_item, m.view_items), - items: vec::map(fld.fold_item, m.items)}; + ret {view_items: vec::map_imm(fld.fold_view_item, m.view_items), + items: vec::map_imm(fld.fold_item, m.items)}; } fn noop_fold_native_mod(nm: native_mod, fld: ast_fold) -> native_mod { ret {native_name: nm.native_name, abi: nm.abi, - view_items: vec::map(fld.fold_view_item, nm.view_items), - items: vec::map(fld.fold_native_item, nm.items)} + view_items: vec::map_imm(fld.fold_view_item, nm.view_items), + items: vec::map_imm(fld.fold_native_item, nm.items)} } fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { @@ -479,7 +479,7 @@ fn noop_fold_ident(i: ident, _fld: ast_fold) -> ident { ret i; } fn noop_fold_path(p: path_, fld: ast_fold) -> path_ { ret {global: p.global, idents: vec::map(fld.fold_ident, p.idents), - types: vec::map(fld.fold_ty, p.types)}; + types: vec::map_imm(fld.fold_ty, p.types)}; } fn noop_fold_local(l: local_, fld: ast_fold) -> local_ { @@ -499,7 +499,7 @@ fn noop_fold_local(l: local_, fld: ast_fold) -> local_ { /* temporarily eta-expand because of a compiler bug with using `fn` as a value */ fn noop_map_exprs(f: fn(@expr) -> @expr, es: [@expr]) -> [@expr] { - ret vec::map(f, es); + ret vec::map_imm(f, es); } fn noop_id(i: node_id) -> node_id { ret i; } diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 53c3aa01bf06..e220149f6f81 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -587,17 +587,11 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty { } fn parse_arg_mode(p: parser) -> ast::mode { - if eat(p, token::BINOP(token::AND)) { - ret ast::by_mut_ref; - } else if eat(p, token::BINOP(token::MINUS)) { - ret ast::by_move; - } else { - // FIXME Temporarily ignore these, to make it possible to implement - // them without breaking the stage0 build. - eat(p, token::ANDAND); - eat(p, token::BINOP(token::PLUS)); - ret ast::by_ref; - } + if eat(p, token::BINOP(token::AND)) { ast::by_mut_ref } + else if eat(p, token::BINOP(token::MINUS)) { ast::by_move } + else if eat(p, token::ANDAND) { ast::by_ref } + else if eat(p, token::BINOP(token::PLUS)) { ast::by_val } + else { ast::mode_infer } } fn parse_arg(p: parser) -> ast::arg { @@ -1890,7 +1884,8 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item { let dtor = parse_block_no_value(p); let decl = {inputs: - [{mode: ast::by_ref, ty: t, ident: arg_ident, id: p.get_id()}], + [{mode: ast::by_ref, ty: t, ident: arg_ident, + id: p.get_id()}], output: @spanned(lo, lo, ast::ty_nil), purity: ast::impure_fn, il: ast::il_normal, diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 555cd7fddeea..a24b4c9b9849 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -226,7 +226,7 @@ fn commasep_cmnt(s: ps, b: breaks, elts: [IN], op: fn(ps, IN), } fn commasep_exprs(s: ps, b: breaks, exprs: [@ast::expr]) { - fn expr_span(expr: @ast::expr) -> codemap::span { ret expr.span; } + fn expr_span(&&expr: @ast::expr) -> codemap::span { ret expr.span; } commasep_cmnt(s, b, exprs, print_expr, expr_span); } @@ -246,7 +246,7 @@ fn print_native_mod(s: ps, nmod: ast::native_mod, attrs: [ast::attribute]) { for item: @ast::native_item in nmod.items { print_native_item(s, item); } } -fn print_type(s: ps, ty: @ast::ty) { +fn print_type(s: ps, &&ty: @ast::ty) { maybe_print_comment(s, ty.span.lo); ibox(s, 0u); alt ty.node { @@ -365,7 +365,7 @@ fn print_native_item(s: ps, item: @ast::native_item) { } } -fn print_item(s: ps, item: @ast::item) { +fn print_item(s: ps, &&item: @ast::item) { hardbreak_if_not_bol(s); maybe_print_comment(s, item.span.lo); print_outer_attributes(s, item.attrs); @@ -678,7 +678,7 @@ fn print_mac(s: ps, m: ast::mac) { } } -fn print_expr(s: ps, expr: @ast::expr) { +fn print_expr(s: ps, &&expr: @ast::expr) { maybe_print_comment(s, expr.span.lo); ibox(s, indent_unit); let ann_node = node_expr(s, expr); @@ -1080,7 +1080,7 @@ fn print_path(s: ps, path: ast::path, colons_before_params: bool) { } } -fn print_pat(s: ps, pat: @ast::pat) { +fn print_pat(s: ps, &&pat: @ast::pat) { maybe_print_comment(s, pat.span.lo); let ann_node = node_pat(s, pat); s.ann.pre(ann_node); @@ -1145,7 +1145,7 @@ fn print_fn_args_and_ret(s: ps, decl: ast::fn_decl, constrs: [@ast::constr]) { popen(s); fn print_arg(s: ps, x: ast::arg) { ibox(s, indent_unit); - print_alias(s, x.mode); + print_arg_mode(s, x.mode); word_space(s, x.ident + ":"); print_type(s, x.ty); end(s); @@ -1174,7 +1174,7 @@ fn print_fn_block_args(s: ps, decl: ast::fn_decl) { word(s.s, "|"); fn print_arg(s: ps, x: ast::arg) { ibox(s, indent_unit); - print_alias(s, x.mode); + print_arg_mode(s, x.mode); word(s.s, x.ident); end(s); } @@ -1183,11 +1183,13 @@ fn print_fn_block_args(s: ps, decl: ast::fn_decl) { maybe_print_comment(s, decl.output.span.lo); } -fn print_alias(s: ps, m: ast::mode) { +fn print_arg_mode(s: ps, m: ast::mode) { alt m { ast::by_mut_ref. { word(s.s, "&"); } ast::by_move. { word(s.s, "-"); } - ast::by_ref. { } + ast::by_ref. { word(s.s, "&&"); } + ast::by_val. { word(s.s, "+"); } + ast::mode_infer. {} } } @@ -1211,7 +1213,7 @@ fn print_type_params(s: ps, params: [ast::ty_param]) { } } -fn print_meta_item(s: ps, item: @ast::meta_item) { +fn print_meta_item(s: ps, &&item: @ast::meta_item) { ibox(s, indent_unit); alt item.node { ast::meta_word(name) { word(s.s, name); } @@ -1351,7 +1353,7 @@ fn print_ty_fn(s: ps, proto: ast::proto, id: option::t, zerobreak(s.s); popen(s); fn print_arg(s: ps, input: ast::ty_arg) { - print_alias(s, input.node.mode); + print_arg_mode(s, input.node.mode); print_type(s, input.node.ty); } commasep(s, inconsistent, inputs, print_arg); @@ -1418,7 +1420,7 @@ fn in_cbox(s: ps) -> bool { ret s.boxes[len - 1u] == pp::consistent; } -fn print_literal(s: ps, lit: @ast::lit) { +fn print_literal(s: ps, &&lit: @ast::lit) { maybe_print_comment(s, lit.span.lo); alt next_lit(s) { some(lt) { @@ -1596,7 +1598,7 @@ fn constr_arg_to_str(f: fn(T) -> str, c: ast::constr_arg_general_) -> // needed b/c constr_args_to_str needs // something that takes an alias // (argh) -fn uint_to_str(i: uint) -> str { ret uint::str(i); } +fn uint_to_str(&&i: uint) -> str { ret uint::str(i); } fn ast_ty_fn_constr_to_str(c: @ast::constr) -> str { ret path_to_str(c.node.path) + @@ -1614,7 +1616,7 @@ fn ast_ty_fn_constrs_str(constrs: [@ast::constr]) -> str { ret s; } -fn fn_arg_idx_to_str(decl: ast::fn_decl, idx: uint) -> str { +fn fn_arg_idx_to_str(decl: ast::fn_decl, &&idx: uint) -> str { decl.inputs[idx].ident } diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index 2a002c3ada36..f234c2fb221f 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -377,62 +377,62 @@ fn default_simple_visitor() -> simple_visitor { } fn mk_simple_visitor(v: simple_visitor) -> vt<()> { - fn v_mod(f: fn(_mod, span), m: _mod, sp: span, e: (), v: vt<()>) { + fn v_mod(f: fn(_mod, span), m: _mod, sp: span, &&e: (), v: vt<()>) { f(m, sp); visit_mod(m, sp, e, v); } - fn v_view_item(f: fn(@view_item), vi: @view_item, e: (), v: vt<()>) { + fn v_view_item(f: fn(@view_item), vi: @view_item, &&e: (), v: vt<()>) { f(vi); visit_view_item(vi, e, v); } - fn v_native_item(f: fn(@native_item), ni: @native_item, e: (), + fn v_native_item(f: fn(@native_item), ni: @native_item, &&e: (), v: vt<()>) { f(ni); visit_native_item(ni, e, v); } - fn v_item(f: fn(@item), i: @item, e: (), v: vt<()>) { + fn v_item(f: fn(@item), i: @item, &&e: (), v: vt<()>) { f(i); visit_item(i, e, v); } - fn v_local(f: fn(@local), l: @local, e: (), v: vt<()>) { + fn v_local(f: fn(@local), l: @local, &&e: (), v: vt<()>) { f(l); visit_local(l, e, v); } - fn v_block(f: fn(ast::blk), bl: ast::blk, e: (), v: vt<()>) { + fn v_block(f: fn(ast::blk), bl: ast::blk, &&e: (), v: vt<()>) { f(bl); visit_block(bl, e, v); } - fn v_stmt(f: fn(@stmt), st: @stmt, e: (), v: vt<()>) { + fn v_stmt(f: fn(@stmt), st: @stmt, &&e: (), v: vt<()>) { f(st); visit_stmt(st, e, v); } - fn v_arm(f: fn(arm), a: arm, e: (), v: vt<()>) { + fn v_arm(f: fn(arm), a: arm, &&e: (), v: vt<()>) { f(a); visit_arm(a, e, v); } - fn v_pat(f: fn(@pat), p: @pat, e: (), v: vt<()>) { + fn v_pat(f: fn(@pat), p: @pat, &&e: (), v: vt<()>) { f(p); visit_pat(p, e, v); } - fn v_decl(f: fn(@decl), d: @decl, e: (), v: vt<()>) { + fn v_decl(f: fn(@decl), d: @decl, &&e: (), v: vt<()>) { f(d); visit_decl(d, e, v); } - fn v_expr(f: fn(@expr), ex: @expr, e: (), v: vt<()>) { + fn v_expr(f: fn(@expr), ex: @expr, &&e: (), v: vt<()>) { f(ex); visit_expr(ex, e, v); } - fn v_ty(f: fn(@ty), ty: @ty, e: (), v: vt<()>) { + fn v_ty(f: fn(@ty), ty: @ty, &&e: (), v: vt<()>) { f(ty); visit_ty(ty, e, v); } fn v_constr(f: fn(path, span, node_id), pt: path, sp: span, id: node_id, - e: (), v: vt<()>) { + &&e: (), v: vt<()>) { f(pt, sp, id); visit_constr(pt, sp, id, e, v); } fn v_fn(f: fn(_fn, [ty_param], span, fn_ident, node_id), ff: _fn, - tps: [ty_param], sp: span, ident: fn_ident, id: node_id, e: (), + tps: [ty_param], sp: span, ident: fn_ident, id: node_id, &&e: (), v: vt<()>) { f(ff, tps, sp, ident, id); visit_fn(ff, tps, sp, ident, id, e, v); diff --git a/src/comp/util/ppaux.rs b/src/comp/util/ppaux.rs index 11c50affd28d..3502eb80a06e 100644 --- a/src/comp/util/ppaux.rs +++ b/src/comp/util/ppaux.rs @@ -13,9 +13,11 @@ import metadata::csearch; fn mode_str(m: ty::mode) -> str { alt m { - ast::by_ref. { "" } + ast::by_ref. { "&&" } + ast::by_val. { "+" } ast::by_mut_ref. { "&" } ast::by_move. { "-" } + _ { "" } } } diff --git a/src/lib/io.rs b/src/lib/io.rs index 73460e50588e..d8f7f36b24f6 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -175,14 +175,11 @@ fn stdin() -> reader { } fn file_reader(path: str) -> reader { - let f = - str::as_buf(path, - {|pathbuf| - str::as_buf("r", - {|modebuf| - os::libc::fopen(pathbuf, modebuf) - }) - }); + let f = str::as_buf(path, {|pathbuf| + str::as_buf("r", {|modebuf| + os::libc::fopen(pathbuf, modebuf) + }) + }); if f as uint == 0u { log_err "error opening " + path; fail; } ret new_reader(FILE_buf_reader(f, option::some(@FILE_res(f)))); } diff --git a/src/lib/list.rs b/src/lib/list.rs index 7037cff365aa..58f976110d9f 100644 --- a/src/lib/list.rs +++ b/src/lib/list.rs @@ -49,7 +49,7 @@ fn has<@T>(ls_: list, elt: T) -> bool { } fn length<@T>(ls: list) -> uint { - fn count(_t: T, u: uint) -> uint { ret u + 1u; } + fn count(_t: T, &&u: uint) -> uint { ret u + 1u; } ret foldl(ls, 0u, count); } diff --git a/src/lib/map.rs b/src/lib/map.rs index 81be20a66207..c63183b18930 100644 --- a/src/lib/map.rs +++ b/src/lib/map.rs @@ -199,14 +199,14 @@ fn new_str_hash<@V>() -> hashmap { } fn new_int_hash<@V>() -> hashmap { - fn hash_int(x: int) -> uint { ret x as uint; } - fn eq_int(a: int, b: int) -> bool { ret a == b; } + fn hash_int(&&x: int) -> uint { ret x as uint; } + fn eq_int(&&a: int, &&b: int) -> bool { ret a == b; } ret mk_hashmap(hash_int, eq_int); } fn new_uint_hash<@V>() -> hashmap { - fn hash_uint(x: uint) -> uint { ret x; } - fn eq_uint(a: uint, b: uint) -> bool { ret a == b; } + fn hash_uint(&&x: uint) -> uint { ret x; } + fn eq_uint(&&a: uint, &&b: uint) -> bool { ret a == b; } ret mk_hashmap(hash_uint, eq_uint); } diff --git a/src/lib/option.rs b/src/lib/option.rs index 53c19ba8c0ab..56b56b5f69f1 100644 --- a/src/lib/option.rs +++ b/src/lib/option.rs @@ -9,6 +9,11 @@ fn get<@T>(opt: t) -> &T { fn map<@T, @U>(f: block(T) -> U, opt: t) -> t { alt opt { some(x) { some(f(x)) } none. { none } } } +// FIXME This is needed to make working with by-value functions a bit less +// painful. We should come up with a better solution. +fn map_imm<@T, @U>(f: block(+T) -> U, opt: t) -> t { + alt opt { some(x) { some(f(x)) } none. { none } } +} fn is_none<@T>(opt: t) -> bool { alt opt { none. { true } some(_) { false } } diff --git a/src/lib/vec.rs b/src/lib/vec.rs index 59f29d40d7c1..bc4334a06bcc 100644 --- a/src/lib/vec.rs +++ b/src/lib/vec.rs @@ -191,6 +191,17 @@ fn map<@T, @U>(f: block(T) -> U, v: [mutable? T]) -> [U] { } ret result; } +// FIXME This is needed to make working with by-value functions a bit less +// painful. We should come up with a better solution. +fn map_imm<@T, @U>(f: block(+T) -> U, v: [mutable? T]) -> [U] { + let result = []; + reserve(result, len(v)); + for elem: T in v { + let elem2 = elem; // satisfies alias checker + result += [f(elem2)]; + } + ret result; +} fn map2<@T, @U, @V>(f: block(T, U) -> V, v0: [T], v1: [U]) -> [V] { let v0_len = len::(v0);