From aa5382bb13690ff183f6e94065dadf0524ce1c6e Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Thu, 29 Dec 2011 20:07:55 -0800 Subject: [PATCH] split proto from fn_decl, as not all fn_decls know the proto. this will address the (crashing) new test added. --- src/comp/front/test.rs | 10 +-- src/comp/middle/alias.rs | 6 +- src/comp/middle/ast_map.rs | 6 +- src/comp/middle/debuginfo.rs | 2 +- src/comp/middle/freevars.rs | 9 +-- src/comp/middle/kind.rs | 8 +- src/comp/middle/last_use.rs | 10 +-- src/comp/middle/resolve.rs | 32 ++++---- src/comp/middle/trans.rs | 8 +- src/comp/middle/trans_closure.rs | 5 +- src/comp/middle/tstate/annotate.rs | 6 +- src/comp/middle/tstate/auxiliary.rs | 4 +- src/comp/middle/tstate/bitvectors.rs | 2 +- src/comp/middle/tstate/ck.rs | 21 +++-- src/comp/middle/tstate/collect_locals.rs | 20 ++--- src/comp/middle/tstate/pre_post_conditions.rs | 11 ++- src/comp/middle/tstate/states.rs | 2 +- src/comp/middle/typeck.rs | 67 ++++++++-------- src/comp/syntax/ast.rs | 7 +- src/comp/syntax/fold.rs | 11 ++- src/comp/syntax/parse/parser.rs | 59 +++++--------- src/comp/syntax/print/pprust.rs | 20 ++--- src/comp/syntax/visit.rs | 77 ++++++++++++------- src/comp/util/ppaux.rs | 4 - src/test/run-pass/block-arg-call-as.rs | 22 ++++++ 25 files changed, 229 insertions(+), 200 deletions(-) create mode 100644 src/test/run-pass/block-arg-call-as.rs diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs index ee32a31aabb..f8aa8bdac53 100644 --- a/src/comp/front/test.rs +++ b/src/comp/front/test.rs @@ -190,8 +190,7 @@ fn mk_tests(cx: test_ctxt) -> @ast::item { let ret_ty = mk_test_desc_vec_ty(cx); let decl: ast::fn_decl = - {proto: ast::proto_bare, - inputs: [], + {inputs: [], output: ret_ty, purity: ast::impure_fn, cf: ast::return_val, @@ -322,7 +321,6 @@ fn mk_test_wrapper(cx: test_ctxt, ast::stmt_expr(@call_expr, cx.sess.next_node_id())); let wrapper_decl: ast::fn_decl = { - proto: ast::proto_bare, inputs: [], output: @nospan(ast::ty_nil), purity: ast::impure_fn, @@ -345,7 +343,8 @@ fn mk_test_wrapper(cx: test_ctxt, let wrapper_expr: ast::expr = { id: cx.sess.next_node_id(), - node: ast::expr_fn(wrapper_decl, wrapper_body, wrapper_capture), + node: ast::expr_fn(ast::proto_bare, wrapper_decl, + wrapper_body, wrapper_capture), span: span }; @@ -366,8 +365,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item { let ret_ty = nospan(ast::ty_nil); let decl: ast::fn_decl = - {proto: ast::proto_bare, - inputs: [args_arg], + {inputs: [args_arg], output: @ret_ty, purity: ast::impure_fn, cf: ast::return_val, diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 959f5e02e17..e3c91b3d52a 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -61,7 +61,7 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (copy_map, ref_map) { copy_map: std::map::new_int_hash(), ref_map: std::map::new_int_hash(), mutable silent: false}; - let v = @{visit_fn: bind visit_fn(cx, _, _, _, _, _, _, _, _), + let v = @{visit_fn: bind visit_fn(cx, _, _, _, _, _, _, _), visit_expr: bind visit_expr(cx, _, _, _), visit_block: bind visit_block(cx, _, _, _) with *visit::default_visitor::<scope>()}; @@ -71,8 +71,8 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (copy_map, ref_map) { ret (cx.copy_map, cx.ref_map); } -fn visit_fn(cx: @ctx, decl: ast::fn_decl, _ts: [ast::ty_param], - body: ast::blk, sp: span, _name: ast::fn_ident, +fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl, + body: ast::blk, sp: span, id: ast::node_id, sc: scope, v: vt<scope>) { visit::visit_fn_decl(decl, sc, v); let fty = ty::node_id_to_type(cx.tcx, id); diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs index 995c16ddb2c..2d2ef2e4c17 100644 --- a/src/comp/middle/ast_map.rs +++ b/src/comp/middle/ast_map.rs @@ -32,7 +32,7 @@ fn map_crate(c: crate) -> map { (@{visit_item: bind map_item(cx, _), visit_native_item: bind map_native_item(cx, _), visit_expr: bind map_expr(cx, _), - visit_fn: bind map_fn(cx, _, _, _, _, _, _), + visit_fn: bind map_fn(cx, _, _, _, _, _), visit_local: bind map_local(cx, _), visit_arm: bind map_arm(cx, _) with *visit::default_simple_visitor()}); @@ -40,8 +40,8 @@ fn map_crate(c: crate) -> map { ret cx.map; } -fn map_fn(cx: ctx, decl: fn_decl, _tps: [ty_param], _body: blk, - _sp: codemap::span, _n: fn_ident, _id: node_id) { +fn map_fn(cx: ctx, _fk: visit::fn_kind, decl: fn_decl, _body: blk, + _sp: codemap::span, _id: node_id) { for a in decl.inputs { cx.map.insert(a.id, node_arg(a, cx.local_id)); cx.local_id += 1u; diff --git a/src/comp/middle/debuginfo.rs b/src/comp/middle/debuginfo.rs index b97b9a65510..0cc6cc7b79d 100644 --- a/src/comp/middle/debuginfo.rs +++ b/src/comp/middle/debuginfo.rs @@ -736,7 +736,7 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> { } ast_map::node_expr(expr) { alt expr.node { - ast::expr_fn(decl, _, _) { + ast::expr_fn(_, decl, _, _) { (dbg_cx.names.next("fn"), decl.output, expr.id) } ast::expr_fn_block(decl, _) { diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs index 9e18bae4a2e..7b348a9c8a1 100644 --- a/src/comp/middle/freevars.rs +++ b/src/comp/middle/freevars.rs @@ -38,8 +38,8 @@ fn collect_freevars(def_map: resolve::def_map, blk: ast::blk) let walk_expr = lambda (expr: @ast::expr, &&depth: int, v: visit::vt<int>) { alt expr.node { - ast::expr_fn(decl, _, captures) { - if decl.proto != ast::proto_bare { + ast::expr_fn(proto, decl, _, captures) { + if proto != ast::proto_bare { visit::visit_expr(expr, depth + 1, v); } } @@ -82,9 +82,8 @@ fn annotate_freevars(def_map: resolve::def_map, crate: @ast::crate) -> freevar_map { let freevars = new_int_hash(); - let walk_fn = lambda (_decl: ast::fn_decl, _tps: [ast::ty_param], - blk: ast::blk, _sp: span, _nm: ast::fn_ident, - nid: ast::node_id) { + let walk_fn = lambda (_fk: visit::fn_kind, _decl: ast::fn_decl, + blk: ast::blk, _sp: span, nid: ast::node_id) { let vars = collect_freevars(def_map, blk); freevars.insert(nid, vars); }; diff --git a/src/comp/middle/kind.rs b/src/comp/middle/kind.rs index e9b15729450..f71112002c4 100644 --- a/src/comp/middle/kind.rs +++ b/src/comp/middle/kind.rs @@ -67,8 +67,8 @@ fn with_closure_check_fn(cx: ctx, id: node_id, // Check that the free variables used in a shared/sendable closure conform // to the copy/move kind bounds. Then recursively check the function body. -fn check_fn(decl: fn_decl, tps: [ty_param], body: blk, sp: span, - i: fn_ident, id: node_id, cx: ctx, v: visit::vt<ctx>) { +fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, + id: node_id, cx: ctx, v: visit::vt<ctx>) { // n.b.: This could be the body of either a fn decl or a fn expr. In the // former case, the prototype will be proto_bare and no check occurs. In @@ -88,7 +88,7 @@ fn check_fn(decl: fn_decl, tps: [ty_param], body: blk, sp: span, } } - visit::visit_fn(decl, tps, body, sp, i, id, cx, v); + visit::visit_fn(fk, decl, body, sp, id, cx, v); } fn check_fn_cap_clause(cx: ctx, @@ -181,7 +181,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) { } } expr_ternary(_, a, b) { maybe_copy(cx, a); maybe_copy(cx, b); } - expr_fn(_, _, cap_clause) { + expr_fn(_, _, _, cap_clause) { check_fn_cap_clause(cx, e.id, *cap_clause); } _ { } diff --git a/src/comp/middle/last_use.rs b/src/comp/middle/last_use.rs index 7b1a0b6c0a3..113e9a9c299 100644 --- a/src/comp/middle/last_use.rs +++ b/src/comp/middle/last_use.rs @@ -136,7 +136,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) { for arg in args { alt arg.node { //NDM--register captured as uses - expr_fn(_, _, captured) { fns += [arg]; } + expr_fn(_, _, _, captured) { fns += [arg]; } expr_fn_block(_, _) { fns += [arg]; } _ { alt arg_ts[i].mode { @@ -153,19 +153,19 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) { } } -fn visit_fn(decl: fn_decl, tps: [ty_param], body: blk, - sp: span, nm: fn_ident, id: node_id, +fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, + sp: span, id: node_id, cx: ctx, v: visit::vt<ctx>) { let fty = ty::node_id_to_type(cx.tcx, id); let proto = ty::ty_fn_proto(cx.tcx, fty); if proto == proto_block { visit_block(func, cx, {|| - visit::visit_fn(decl, tps, body, sp, nm, id, cx, v); + visit::visit_fn(fk, decl, body, sp, id, cx, v); }); } else { let old = nil; cx.blocks <-> old; - visit::visit_fn(decl, tps, body, sp, nm, id, cx, v); + visit::visit_fn(fk, decl, body, sp, id, cx, v); cx.blocks <-> old; leave_fn(cx); } diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 9eaaee2cb36..ca9887534cb 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -336,7 +336,7 @@ fn resolve_names(e: @env, c: @ast::crate) { visit_expr: bind walk_expr(e, _, _, _), visit_ty: bind walk_ty(e, _, _, _), visit_constr: bind walk_constr(e, _, _, _, _, _), - visit_fn: bind visit_fn_with_scope(e, _, _, _, _, _, _, _, _) + visit_fn: bind visit_fn_with_scope(e, _, _, _, _, _, _, _) with *visit::default_visitor()}; visit::visit_crate(*c, cons(scope_crate, @nil), visit::mk_vt(v)); e.used_imports.track = false; @@ -350,7 +350,7 @@ fn resolve_names(e: @env, c: @ast::crate) { lookup_path_strict(*e, sc, exp.span, p.node, ns_value)); } - ast::expr_fn(_, _, cap_clause) { + ast::expr_fn(_, _, _, cap_clause) { let rci = bind resolve_capture_item(e, sc, _); vec::iter(cap_clause.copies, rci); vec::iter(cap_clause.moves, rci); @@ -403,8 +403,9 @@ fn visit_item_with_scope(i: @ast::item, sc: scopes, v: vt<scopes>) { alt ifce { some(ty) { v.visit_ty(ty, sc, v); } _ {} } v.visit_ty(sty, sc, v); for m in methods { - v.visit_fn(m.decl, tps + m.tps, m.body, m.span, - some(m.ident), m.id, sc, v); + v.visit_fn(visit::fk_method(m.ident, tps + m.tps), + m.decl, m.body, m.span, + m.id, sc, v); } } _ { visit::visit_item(i, sc, v); } @@ -416,30 +417,35 @@ fn visit_native_item_with_scope(ni: @ast::native_item, sc: scopes, visit::visit_native_item(ni, cons(scope_native_item(ni), @sc), v); } -fn visit_fn_with_scope(e: @env, decl: ast::fn_decl, tp: [ast::ty_param], - body: ast::blk, sp: span, name: fn_ident, +fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl, + body: ast::blk, sp: span, id: node_id, sc: scopes, v: vt<scopes>) { // is this a main fn declaration? - alt name { - some(nm) { + alt fk { + visit::fk_item_fn(nm, _) { if is_main_name([nm]) && !e.sess.building_library() { // This is a main function -- set it in the session // as the main ID e.sess.set_main_id(id); } } - _ { } + _ { /* fallthrough */ } } // here's where we need to set up the mapping // for f's constrs in the table. for c: @ast::constr in decl.constraints { resolve_constr(e, c, sc, v); } - let scope = alt decl.proto { - ast::proto_bare. { scope_bare_fn(decl, id, tp) } - _ { scope_fn_expr(decl, id, tp) } + let scope = alt fk { + visit::fk_item_fn(_, tps) | visit::fk_method(_, tps) | + visit::fk_res(_, tps) { + scope_bare_fn(decl, id, tps) + } + visit::fk_anon(_) | visit::fk_fn_block. { + scope_fn_expr(decl, id, []) + } }; - visit::visit_fn(decl, tp, body, sp, name, id, cons(scope, @sc), v); + visit::visit_fn(fk, decl, body, sp, id, cons(scope, @sc), v); } fn visit_block_with_scope(b: ast::blk, sc: scopes, v: vt<scopes>) { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a318f2ec354..26a9a29b685 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3551,16 +3551,18 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt { assert op != ast::deref; // lvals are handled above ret trans_unary(bcx, op, x, e.id, dest); } - ast::expr_fn(decl, body, cap_clause) { + ast::expr_fn(proto, decl, body, cap_clause) { ret trans_closure::trans_expr_fn( - bcx, decl, body, e.span, e.id, *cap_clause, dest); + bcx, proto, decl, body, e.span, e.id, *cap_clause, dest); } ast::expr_fn_block(decl, body) { alt ty::struct(tcx, ty::expr_ty(tcx, e)) { ty::ty_fn({proto, _}) { + #debug("translating fn_block %s with type %s", + expr_to_str(e), ty_to_str(tcx, ty::expr_ty(tcx, e))); let cap_clause = { copies: [], moves: [] }; ret trans_closure::trans_expr_fn( - bcx, decl, body, e.span, e.id, cap_clause, dest); + bcx, proto, decl, body, e.span, e.id, cap_clause, dest); } _ { fail "Type of fn block is not a function!"; diff --git a/src/comp/middle/trans_closure.rs b/src/comp/middle/trans_closure.rs index b60649a2280..7205dd27c1c 100644 --- a/src/comp/middle/trans_closure.rs +++ b/src/comp/middle/trans_closure.rs @@ -372,6 +372,7 @@ fn load_environment(enclosing_cx: @block_ctxt, } fn trans_expr_fn(bcx: @block_ctxt, + proto: ast::proto, decl: ast::fn_decl, body: ast::blk, sp: span, @@ -390,7 +391,7 @@ fn trans_expr_fn(bcx: @block_ctxt, let trans_closure_env = lambda(ck: ty::closure_kind) -> ValueRef { let cap_vars = capture::compute_capture_vars( - ccx.tcx, id, decl.proto, cap_clause); + ccx.tcx, id, proto, cap_clause); let {llbox, box_ty, bcx} = build_closure(bcx, cap_vars, ck); trans_closure(sub_cx, sp, decl, body, llfn, no_self, [], id, {|fcx| load_environment(bcx, fcx, box_ty, cap_vars, ck); @@ -398,7 +399,7 @@ fn trans_expr_fn(bcx: @block_ctxt, llbox }; - let closure = alt decl.proto { + let closure = alt proto { ast::proto_block. { trans_closure_env(ty::closure_block) } ast::proto_shared(_) { trans_closure_env(ty::closure_shared) } ast::proto_send. { trans_closure_env(ty::closure_send) } diff --git a/src/comp/middle/tstate/annotate.rs b/src/comp/middle/tstate/annotate.rs index cc1360114cd..e5c4cd7192c 100644 --- a/src/comp/middle/tstate/annotate.rs +++ b/src/comp/middle/tstate/annotate.rs @@ -56,8 +56,8 @@ fn visit_fn(ccx: crate_ctxt, num_constraints: uint, body: blk) { init_vecs(ccx, node_id_vec, num_constraints); } -fn annotate_in_fn(ccx: crate_ctxt, _decl: fn_decl, _ts: [ty_param], body: blk, - _sp: span, _n: fn_ident, id: node_id) { +fn annotate_in_fn(ccx: crate_ctxt, _fk: visit::fn_kind, _decl: fn_decl, + body: blk, _sp: span, id: node_id) { let f_info = get_fn_info(ccx, id); visit_fn(ccx, num_constraints(f_info), body); } @@ -65,7 +65,7 @@ fn annotate_in_fn(ccx: crate_ctxt, _decl: fn_decl, _ts: [ty_param], body: blk, fn annotate_crate(ccx: crate_ctxt, crate: crate) { let do_ann = visit::mk_simple_visitor( - @{visit_fn: bind annotate_in_fn(ccx, _, _, _, _, _, _) + @{visit_fn: bind annotate_in_fn(ccx, _, _, _, _, _) with *visit::default_simple_visitor()}); visit::visit_crate(crate, (), do_ann); } diff --git a/src/comp/middle/tstate/auxiliary.rs b/src/comp/middle/tstate/auxiliary.rs index 340b2264354..5b12477d873 100644 --- a/src/comp/middle/tstate/auxiliary.rs +++ b/src/comp/middle/tstate/auxiliary.rs @@ -1008,8 +1008,8 @@ fn op_to_oper_ty(io: init_op) -> oper_type { } // default function visitor -fn do_nothing<T>(_decl: fn_decl, _ts: [ty_param], _body: blk, - _sp: span, _i: fn_ident, _id: node_id, +fn do_nothing<T>(_fk: visit::fn_kind, _decl: fn_decl, _body: blk, + _sp: span, _id: node_id, _t: T, _v: visit::vt<T>) { } diff --git a/src/comp/middle/tstate/bitvectors.rs b/src/comp/middle/tstate/bitvectors.rs index 120e33d9254..9f4d5949e01 100644 --- a/src/comp/middle/tstate/bitvectors.rs +++ b/src/comp/middle/tstate/bitvectors.rs @@ -151,7 +151,7 @@ fn relax_precond_block(fcx: fn_ctxt, i: node_id, b: blk) { visit_stmt: relax_precond_stmt, visit_item: fn (_i: @item, _cx: relax_ctxt, _vt: visit::vt<relax_ctxt>) { }, - visit_fn: bind do_nothing(_, _, _, _, _, _, _, _) + visit_fn: bind do_nothing(_, _, _, _, _, _, _) with *visitor}; let v1 = visit::mk_vt(visitor); v1.visit_block(b, cx, v1); diff --git a/src/comp/middle/tstate/ck.rs b/src/comp/middle/tstate/ck.rs index f790334fbc4..0ebf4bd0ccc 100644 --- a/src/comp/middle/tstate/ck.rs +++ b/src/comp/middle/tstate/ck.rs @@ -94,21 +94,20 @@ fn check_states_stmt(s: @stmt, fcx: fn_ctxt, v: visit::vt<fn_ctxt>) { } fn check_states_against_conditions(fcx: fn_ctxt, + fk: visit::fn_kind, f_decl: ast::fn_decl, f_body: ast::blk, sp: span, - nm: fn_ident, id: node_id) { /* Postorder traversal instead of pre is important because we want the smallest possible erroneous statement or expression. */ - let visitor = visit::mk_vt( @{visit_stmt: check_states_stmt, visit_expr: check_states_expr, - visit_fn: bind do_nothing::<fn_ctxt>(_, _, _, _, _, _, _, _) + visit_fn: bind do_nothing::<fn_ctxt>(_, _, _, _, _, _, _) with *visit::default_visitor::<fn_ctxt>()}); - visit::visit_fn(f_decl, [], f_body, sp, nm, id, fcx, visitor); + visit::visit_fn(fk, f_decl, f_body, sp, id, fcx, visitor); /* Check that the return value is initialized */ let post = aux::block_poststate(fcx.ccx, f_body); @@ -142,10 +141,10 @@ fn check_states_against_conditions(fcx: fn_ctxt, } fn check_fn_states(fcx: fn_ctxt, + fk: visit::fn_kind, f_decl: ast::fn_decl, f_body: ast::blk, sp: span, - nm: fn_ident, id: node_id) { /* Compute the pre- and post-states for this function */ @@ -155,20 +154,20 @@ fn check_fn_states(fcx: fn_ctxt, /* Now compare each expr's pre-state to its precondition and post-state to its postcondition */ - check_states_against_conditions(fcx, f_decl, f_body, sp, nm, id); + check_states_against_conditions(fcx, fk, f_decl, f_body, sp, id); } -fn fn_states(f_decl: ast::fn_decl, tps: [ast::ty_param], f_body: ast::blk, - sp: span, i: ast::fn_ident, id: node_id, +fn fn_states(fk: visit::fn_kind, f_decl: ast::fn_decl, f_body: ast::blk, + sp: span, id: node_id, ccx: crate_ctxt, v: visit::vt<crate_ctxt>) { - visit::visit_fn(f_decl, tps, f_body, sp, i, id, ccx, v); + visit::visit_fn(fk, f_decl, f_body, sp, id, ccx, v); /* Look up the var-to-bit-num map for this function */ assert (ccx.fm.contains_key(id)); let f_info = ccx.fm.get(id); - let name = option::from_maybe("anon", i); // XXXX + let name = visit::name_of_fn(fk); let fcx = {enclosing: f_info, id: id, name: name, ccx: ccx}; - check_fn_states(fcx, f_decl, f_body, sp, i, id) + check_fn_states(fcx, fk, f_decl, f_body, sp, id) } fn check_crate(cx: ty::ctxt, crate: @crate) { diff --git a/src/comp/middle/tstate/collect_locals.rs b/src/comp/middle/tstate/collect_locals.rs index 457a6ca0173..60c79468589 100644 --- a/src/comp/middle/tstate/collect_locals.rs +++ b/src/comp/middle/tstate/collect_locals.rs @@ -1,6 +1,5 @@ import syntax::ast::*; import syntax::ast_util::*; -import util::ppaux::fn_ident_to_string; import option::*; import syntax::visit; import aux::*; @@ -45,11 +44,10 @@ fn collect_pred(e: @expr, cx: ctxt, v: visit::vt<ctxt>) { } fn find_locals(tcx: ty::ctxt, + fk: visit::fn_kind, f_decl: fn_decl, - tps: [ty_param], f_body: blk, sp: span, - n: fn_ident, id: node_id) -> ctxt { let cx: ctxt = {cs: @mutable [], tcx: tcx}; let visitor = visit::default_visitor::<ctxt>(); @@ -57,10 +55,10 @@ fn find_locals(tcx: ty::ctxt, visitor = @{visit_local: collect_local, visit_expr: collect_pred, - visit_fn: bind do_nothing(_, _, _, _, _, _, _, _) + visit_fn: bind do_nothing(_, _, _, _, _, _, _) with *visitor}; - visit::visit_fn(f_decl, tps, f_body, sp, - n, id, cx, visit::mk_vt(visitor)); + visit::visit_fn(fk, f_decl, f_body, sp, + id, cx, visit::mk_vt(visitor)); ret cx; } @@ -98,18 +96,16 @@ fn add_constraint(tcx: ty::ctxt, c: sp_constr, next: uint, tbl: constr_map) -> /* builds a table mapping each local var defined in f to a bit number in the precondition/postcondition vectors */ fn mk_fn_info(ccx: crate_ctxt, + fk: visit::fn_kind, f_decl: fn_decl, - tps: [ty_param], f_body: blk, f_sp: span, - f_name: fn_ident, id: node_id) { - let name = fn_ident_to_string(id, f_name); + let name = visit::name_of_fn(fk); let res_map = @new_def_hash::<constraint>(); let next: uint = 0u; - let cx: ctxt = find_locals(ccx.tcx, f_decl, tps, f_body, f_sp, - f_name, id); + let cx: ctxt = find_locals(ccx.tcx, fk, f_decl, f_body, f_sp, id); /* now we have to add bit nums for both the constraints and the variables... */ @@ -167,7 +163,7 @@ fn mk_fn_info(ccx: crate_ctxt, fn mk_f_to_fn_info(ccx: crate_ctxt, c: @crate) { let visitor = visit::mk_simple_visitor(@{visit_fn: - bind mk_fn_info(ccx, _, _, _, _, _, _) + bind mk_fn_info(ccx, _, _, _, _, _) with *visit::default_simple_visitor()}); visit::visit_crate(*c, (), visitor); } diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 9a3100e7bb2..fb1dd7564a8 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -14,7 +14,6 @@ import syntax::visit; import util::common::{new_def_hash, log_expr, field_exprs, has_nonlocal_exits, log_stmt}; import syntax::codemap::span; -import util::ppaux::fn_ident_to_string; fn find_pre_post_mod(_m: _mod) -> _mod { #debug("implement find_pre_post_mod!"); @@ -346,7 +345,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { expr_log(_, lvl, arg) { find_pre_post_exprs(fcx, [lvl, arg], e.id); } - expr_fn(_, _, cap_clause) { + expr_fn(_, _, _, cap_clause) { find_pre_post_expr_fn_upvars(fcx, e); let use_cap_item = lambda(&&cap_item: @capture_item) { @@ -727,15 +726,15 @@ fn find_pre_post_fn(fcx: fn_ctxt, body: blk) { } } -fn fn_pre_post(decl: fn_decl, tps: [ty_param], body: blk, sp: span, - i: fn_ident, id: node_id, +fn fn_pre_post(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, + id: node_id, ccx: crate_ctxt, v: visit::vt<crate_ctxt>) { - visit::visit_fn(decl, tps, body, sp, i, id, ccx, v); + visit::visit_fn(fk, decl, body, sp, id, ccx, v); assert (ccx.fm.contains_key(id)); let fcx = {enclosing: ccx.fm.get(id), id: id, - name: fn_ident_to_string(id, i), + name: visit::name_of_fn(fk), ccx: ccx}; find_pre_post_fn(fcx, body); } diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index 492570e9123..2652585f09b 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -371,7 +371,7 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { } expr_mac(_) { fcx.ccx.tcx.sess.bug("unexpanded macro"); } expr_lit(l) { ret pure_exp(fcx.ccx, e.id, pres); } - expr_fn(_, _, cap_clause) { + expr_fn(_, _, _, cap_clause) { ret find_pre_post_state_cap_clause(fcx, e.id, pres, *cap_clause); } expr_fn_block(_, _) { ret pure_exp(fcx.ccx, e.id, pres); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 137804b59d4..5d65ce78049 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -333,8 +333,8 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t { } typ = ty::mk_rec(tcx, flds); } - ast::ty_fn(decl) { - typ = ty::mk_fn(tcx, ty_of_fn_decl(tcx, mode, decl)); + ast::ty_fn(proto, decl) { + typ = ty::mk_fn(tcx, ty_of_fn_decl(tcx, mode, proto, decl)); } ast::ty_path(path, id) { alt tcx.def_map.find(id) { @@ -465,7 +465,8 @@ fn ty_of_arg(tcx: ty::ctxt, mode: mode, a: ast::arg) -> ty::arg { let ty = ast_ty_to_ty(tcx, mode, a.ty); {mode: default_arg_mode_for_ty(tcx, a.mode, ty), ty: ty} } -fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl) -> ty::fn_ty { +fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode, + proto: ast::proto, decl: ast::fn_decl) -> ty::fn_ty { let input_tys = []; for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; } let output_ty = ast_ty_to_ty(tcx, mode, decl.output); @@ -474,19 +475,20 @@ fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl) -> ty::fn_ty { for constr: @ast::constr in decl.constraints { out_constrs += [ty::ast_constr_to_constr(tcx, constr)]; } - {proto: decl.proto, inputs: input_tys, + {proto: proto, inputs: input_tys, output: output_ty, ret_style: decl.cf, constraints: out_constrs} } fn ty_of_fn(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl, ty_params: [ast::ty_param], def_id: ast::def_id) -> ty::ty_param_bounds_and_ty { - let tpt = @{bounds: ty_param_bounds(tcx, mode, ty_params), - ty: ty::mk_fn(tcx, ty_of_fn_decl(tcx, mode, decl))}; + let bounds = ty_param_bounds(tcx, mode, ty_params); + let tofd = ty_of_fn_decl(tcx, mode, ast::proto_bare, decl); + let tpt = @{bounds: bounds, ty: ty::mk_fn(tcx, tofd)}; tcx.tcache.insert(def_id, tpt); ret tpt; } fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl, - ty_params: [ast::ty_param], def_id: ast::def_id) + ty_params: [ast::ty_param], def_id: ast::def_id) -> ty::ty_param_bounds_and_ty { let input_tys = [], bounds = ty_param_bounds(tcx, mode, ty_params); for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; } @@ -524,12 +526,12 @@ fn ty_param_bounds(tcx: ty::ctxt, mode: mode, params: [ast::ty_param]) } fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method { {ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps), - fty: ty_of_fn_decl(tcx, mode, m.decl)} + fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl)} } fn ty_of_ty_method(tcx: ty::ctxt, mode: mode, m: ast::ty_method) -> ty::method { {ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps), - fty: ty_of_fn_decl(tcx, mode, m.decl)} + fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl)} } fn ty_of_obj(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj, ty_params: [ast::ty_param]) -> ty::ty_param_bounds_and_ty { @@ -691,8 +693,9 @@ mod collect { ty_param_bounds(cx.tcx, m_collect, tps); for m in ms { let bounds = ty_param_bounds(cx.tcx, m_collect, m.tps); - let ty = ty::mk_fn(cx.tcx, ty_of_fn_decl(cx.tcx, m_collect, - m.decl)); + let ty = ty::mk_fn(cx.tcx, + ty_of_fn_decl(cx.tcx, m_collect, + ast::proto_bare, m.decl)); cx.tcx.tcache.insert(local_def(m.id), @{bounds: bounds, ty: ty}); write::ty_only(cx.tcx, m.id, ty); @@ -1005,7 +1008,7 @@ mod writeback { if !wbcx.success { ret; } resolve_type_vars_for_node(wbcx, e.span, e.id); alt e.node { - ast::expr_fn(decl, _, _) | + ast::expr_fn(_, decl, _, _) | ast::expr_fn_block(decl, _) { for input in decl.inputs { resolve_type_vars_for_node(wbcx, e.span, input.id); @@ -1154,16 +1157,15 @@ fn gather_locals(ccx: @crate_ctxt, }; // Don't descend into fns and items - fn visit_fn<T>(_decl: ast::fn_decl, _ts: [ast::ty_param], _body: ast::blk, - _sp: span, _nm: ast::fn_ident, _id: ast::node_id, - _t: T, _v: visit::vt<T>) { + fn visit_fn<T>(_fk: visit::fn_kind, _decl: ast::fn_decl, _body: ast::blk, + _sp: span, _id: ast::node_id, _t: T, _v: visit::vt<T>) { } fn visit_item<E>(_i: @ast::item, _e: E, _v: visit::vt<E>) { } let visit = @{visit_local: visit_local, visit_pat: visit_pat, - visit_fn: bind visit_fn(_, _, _, _, _, _, _, _), + visit_fn: bind visit_fn(_, _, _, _, _, _, _), visit_item: bind visit_item(_, _, _) with *visit::default_visitor()}; @@ -1510,13 +1512,15 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes, fn check_expr_fn_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, + proto: ast::proto, decl: ast::fn_decl, body: ast::blk, unify: unifier, expected: ty::t) { let tcx = fcx.ccx.tcx; - let fty = ty::mk_fn(tcx, ty_of_fn_decl(tcx, m_check_tyvar(fcx), decl)); + let fty = ty::mk_fn(tcx, ty_of_fn_decl(tcx, m_check_tyvar(fcx), + proto, decl)); #debug("check_expr_fn_with_unifier %s fty=%s", expr_to_str(expr), @@ -1530,7 +1534,7 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt, // record projection work on type inferred arguments. unify(fcx, expr.span, expected, fty); - check_fn(fcx.ccx, decl, body, expr.id, some(fcx)); + check_fn(fcx.ccx, proto, decl, body, expr.id, some(fcx)); } fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, @@ -1964,10 +1968,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, if !arm_non_bot { result_ty = ty::mk_bot(tcx); } write::ty_only_fixup(fcx, id, result_ty); } - ast::expr_fn(decl, body, captures) { - check_expr_fn_with_unifier(fcx, expr, decl, body, + ast::expr_fn(proto, decl, body, captures) { + check_expr_fn_with_unifier(fcx, expr, proto, decl, body, unify, expected); - capture::check_capture_clause(tcx, expr.id, decl.proto, *captures); + capture::check_capture_clause(tcx, expr.id, proto, *captures); } ast::expr_fn_block(decl, body) { // Take the prototype from the expected type, but default to block: @@ -1983,7 +1987,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, #debug("checking expr_fn_block %s expected=%s", expr_to_str(expr), ty_to_str(tcx, expected)); - check_expr_fn_with_unifier(fcx, expr, {proto: proto with decl}, body, + check_expr_fn_with_unifier(fcx, expr, proto, decl, body, unify, expected); write::ty_only_fixup(fcx, id, expected); } @@ -2602,10 +2606,11 @@ fn check_constraints(fcx: @fn_ctxt, cs: [@ast::constr], args: [ast::arg]) { } fn check_fn(ccx: @crate_ctxt, - decl: ast::fn_decl, - body: ast::blk, - id: ast::node_id, - old_fcx: option::t<@fn_ctxt>) { + proto: ast::proto, + decl: ast::fn_decl, + body: ast::blk, + id: ast::node_id, + old_fcx: option::t<@fn_ctxt>) { // If old_fcx is some(...), this is a block fn { |x| ... }. // In that case, the purity is inherited from the context. let purity = alt old_fcx { @@ -2618,7 +2623,7 @@ fn check_fn(ccx: @crate_ctxt, let fcx: @fn_ctxt = @{ret_ty: ty::ty_fn_ret(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)), purity: purity, - proto: decl.proto, + proto: proto, var_bindings: gather_result.var_bindings, locals: gather_result.locals, next_var_id: gather_result.next_var_id, @@ -2655,15 +2660,17 @@ fn check_fn(ccx: @crate_ctxt, } fn check_method(ccx: @crate_ctxt, method: @ast::method) { - check_fn(ccx, method.decl, method.body, method.id, none); + check_fn(ccx, ast::proto_bare, method.decl, method.body, method.id, none); } fn check_item(ccx: @crate_ctxt, it: @ast::item) { alt it.node { ast::item_const(_, e) { check_const(ccx, it.span, e, it.id); } - ast::item_fn(decl, _, body) { check_fn(ccx, decl, body, it.id, none); } + ast::item_fn(decl, _, body) { + check_fn(ccx, ast::proto_bare, decl, body, it.id, none); + } ast::item_res(decl, _, body, dtor_id, _) { - check_fn(ccx, decl, body, dtor_id, none); + check_fn(ccx, ast::proto_bare, decl, body, dtor_id, none); } ast::item_obj(ob, _, _) { // We're entering an object, so gather up the info we need. diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 04516826ba7..b0d51b58040 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -202,7 +202,7 @@ tag expr_ { expr_for(@local, @expr, blk); expr_do_while(blk, @expr); expr_alt(@expr, [arm]); - expr_fn(fn_decl, blk, @capture_clause); + expr_fn(proto, fn_decl, blk, @capture_clause); expr_fn_block(fn_decl, blk); expr_block(blk); @@ -317,7 +317,7 @@ tag ty_ { ty_port(@ty); ty_chan(@ty); ty_rec([ty_field]); - ty_fn(fn_decl); + ty_fn(proto, fn_decl); ty_obj([ty_method]); ty_tup([@ty]); ty_path(@path, node_id); @@ -368,8 +368,7 @@ type ty_constr = spanned<ty_constr_>; type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; type fn_decl = - {proto: proto, - inputs: [arg], + {inputs: [arg], output: @ty, purity: purity, cf: ret_style, diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index d06c98b0a31..9313bbcdc58 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -143,8 +143,7 @@ fn fold_mac_(m: mac, fld: ast_fold) -> mac { } fn fold_fn_decl(decl: ast::fn_decl, fld: ast_fold) -> ast::fn_decl { - ret {proto: decl.proto, - inputs: vec::map(decl.inputs, bind fold_arg_(_, fld)), + ret {inputs: vec::map(decl.inputs, bind fold_arg_(_, fld)), output: fld.fold_ty(decl.output), purity: decl.purity, cf: decl.cf, @@ -192,8 +191,7 @@ fn noop_fold_native_item(&&ni: @native_item, fld: ast_fold) -> @native_item { alt ni.node { native_item_ty. { native_item_ty } native_item_fn(fdec, typms) { - native_item_fn({proto: fdec.proto, - inputs: vec::map(fdec.inputs, fold_arg), + native_item_fn({inputs: vec::map(fdec.inputs, fold_arg), output: fld.fold_ty(fdec.output), purity: fdec.purity, cf: fdec.cf, @@ -398,8 +396,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { expr_alt(expr, arms) { expr_alt(fld.fold_expr(expr), vec::map(arms, fld.fold_arm)) } - expr_fn(decl, body, captures) { - expr_fn(fold_fn_decl(decl, fld), fld.fold_block(body), captures) + expr_fn(proto, decl, body, captures) { + expr_fn(proto, fold_fn_decl(decl, fld), + fld.fold_block(body), captures) } expr_fn_block(decl, body) { expr_fn_block(fold_fn_decl(decl, fld), fld.fold_block(body)) diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index b681f713422..dd649779235 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -280,21 +280,21 @@ fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ { // auto constrs = parse_constrs(~[], p); let constrs: [@ast::constr] = []; let (ret_style, ret_ty) = parse_ret_ty(p); - ret ast::ty_fn({proto: proto, inputs: inputs.node, output: ret_ty, - purity: ast::impure_fn, cf: ret_style, - constraints: constrs}); + ret ast::ty_fn(proto, {inputs: inputs.node, output: ret_ty, + purity: ast::impure_fn, cf: ret_style, + constraints: constrs}); } fn parse_ty_methods(p: parser, allow_tps: bool) -> [ast::ty_method] { parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p| let flo = p.get_lo_pos(); - let proto: ast::proto = parse_method_proto(p); + expect_word(p, "fn"); let ident = parse_value_ident(p); let tps = allow_tps ? parse_ty_params(p) : []; - let f = parse_ty_fn(proto, p), fhi = p.get_last_hi_pos(); + let f = parse_ty_fn(ast::proto_bare, p), fhi = p.get_last_hi_pos(); expect(p, token::SEMI); alt f { - ast::ty_fn(d) { + ast::ty_fn(_, d) { {ident: ident, decl: d, tps: tps, span: ast_util::mk_sp(flo, fhi)} } @@ -1284,10 +1284,10 @@ fn parse_capture_clause(p: parser) -> @ast::capture_clause { fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr { let lo = p.get_last_lo_pos(); let capture_clause = parse_capture_clause(p); - let decl = parse_fn_decl(p, proto, ast::impure_fn); + let decl = parse_fn_decl(p, ast::impure_fn); let body = parse_block(p); ret mk_expr(p, lo, body.span.hi, - ast::expr_fn(decl, body, capture_clause)); + ast::expr_fn(proto, decl, body, capture_clause)); } fn parse_fn_block_expr(p: parser) -> @ast::expr { @@ -1738,7 +1738,7 @@ fn parse_ty_params(p: parser) -> [ast::ty_param] { } else { [] } } -fn parse_fn_decl(p: parser, proto: ast::proto, purity: ast::purity) +fn parse_fn_decl(p: parser, purity: ast::purity) -> ast::fn_decl { let inputs: ast::spanned<[ast::arg]> = parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA), @@ -1752,8 +1752,7 @@ fn parse_fn_decl(p: parser, proto: ast::proto, purity: ast::purity) constrs = parse_constrs({|x| parse_ty_constr(inputs.node, x) }, p); } let (ret_style, ret_ty) = parse_ret_ty(p); - ret {proto: proto, - inputs: inputs.node, + ret {inputs: inputs.node, output: ret_ty, purity: purity, cf: ret_style, @@ -1766,8 +1765,7 @@ fn parse_fn_block_decl(p: parser) -> ast::fn_decl { seq_sep(token::COMMA), parse_fn_block_arg, p).node; let output = eat(p, token::RARROW) ? parse_ty(p, false) : @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer); - ret {proto: ast::proto_block, - inputs: inputs, + ret {inputs: inputs, output: output, purity: ast::impure_fn, cf: ast::return_val, @@ -1789,11 +1787,11 @@ fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_, span: ast_util::mk_sp(lo, hi)}; } -fn parse_item_fn(p: parser, purity: ast::purity, proto: ast::proto, +fn parse_item_fn(p: parser, purity: ast::purity, attrs: [ast::attribute]) -> @ast::item { let lo = p.get_last_lo_pos(); let t = parse_fn_header(p); - let decl = parse_fn_decl(p, proto, purity); + let decl = parse_fn_decl(p, purity); let body = parse_block(p); ret mk_item(p, lo, body.span.hi, t.ident, ast::item_fn(decl, t.tps, body), attrs); @@ -1819,10 +1817,10 @@ fn parse_anon_obj_field(p: parser) -> ast::anon_obj_field { fn parse_method(p: parser, allow_tps: bool) -> @ast::method { let lo = p.get_lo_pos(); - let proto = parse_method_proto(p); + expect_word(p, "fn"); let ident = parse_value_ident(p); let tps = allow_tps ? parse_ty_params(p) : []; - let decl = parse_fn_decl(p, proto, ast::impure_fn); + let decl = parse_fn_decl(p, ast::impure_fn); let body = parse_block(p); @{ident: ident, tps: tps, decl: decl, body: body, id: p.get_id(), span: ast_util::mk_sp(lo, body.span.hi)} @@ -1900,8 +1898,7 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item { expect(p, token::RPAREN); let dtor = parse_block_no_value(p); let decl = - {proto: ast::proto_bare, - inputs: + {inputs: [{mode: ast::by_ref, ty: t, ident: arg_ident, id: p.get_id()}], output: @spanned(lo, lo, ast::ty_nil), @@ -1974,7 +1971,7 @@ fn parse_item_native_fn(p: parser, attrs: [ast::attribute], purity: ast::purity) -> @ast::native_item { let lo = p.get_last_lo_pos(); let t = parse_fn_header(p); - let decl = parse_fn_decl(p, ast::proto_bare, purity); + let decl = parse_fn_decl(p, purity); let hi = p.get_hi_pos(); expect(p, token::SEMI); ret @{ident: t.ident, @@ -2107,10 +2104,6 @@ fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item { ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs); } -fn parse_fn_item_proto(_p: parser) -> ast::proto { - ast::proto_bare -} - fn parse_fn_ty_proto(p: parser) -> ast::proto { if p.peek() == token::AT { p.bump(); @@ -2120,32 +2113,22 @@ fn parse_fn_ty_proto(p: parser) -> ast::proto { } } -fn parse_method_proto(p: parser) -> ast::proto { - if eat_word(p, "fn") { - ret ast::proto_bare; - } else { unexpected(p, p.peek()); } -} - fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> { if eat_word(p, "const") { ret some(parse_item_const(p, attrs)); } else if eat_word(p, "inline") { expect_word(p, "fn"); - let proto = parse_fn_item_proto(p); - ret some(parse_item_fn(p, ast::impure_fn, proto, attrs)); + ret some(parse_item_fn(p, ast::impure_fn, attrs)); } else if is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN { p.bump(); - let proto = parse_fn_item_proto(p); - ret some(parse_item_fn(p, ast::impure_fn, proto, attrs)); + ret some(parse_item_fn(p, ast::impure_fn, attrs)); } else if eat_word(p, "pure") { expect_word(p, "fn"); - let proto = parse_fn_item_proto(p); - ret some(parse_item_fn(p, ast::pure_fn, proto, attrs)); + ret some(parse_item_fn(p, ast::pure_fn, attrs)); } else if is_word(p, "unsafe") && p.look_ahead(1u) != token::LBRACE { p.bump(); expect_word(p, "fn"); - let proto = parse_fn_item_proto(p); - ret some(parse_item_fn(p, ast::unsafe_fn, proto, attrs)); + ret some(parse_item_fn(p, ast::unsafe_fn, attrs)); } else if eat_word(p, "mod") { ret some(parse_item_mod(p, attrs)); } else if eat_word(p, "native") { diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 48893f67227..c8f6b1b0a87 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -305,8 +305,8 @@ fn print_type(s: ps, &&ty: @ast::ty) { commasep(s, inconsistent, elts, print_type); pclose(s); } - ast::ty_fn(d) { - print_ty_fn(s, d, none::<str>); + ast::ty_fn(proto, d) { + print_ty_fn(s, proto, d, none::<str>); } ast::ty_obj(methods) { head(s, "obj"); @@ -519,7 +519,7 @@ fn print_ty_method(s: ps, m: ast::ty_method) { hardbreak_if_not_bol(s); cbox(s, indent_unit); maybe_print_comment(s, m.span.lo); - print_ty_fn(s, m.decl, some(m.ident)); + print_ty_fn(s, ast::proto_bare, m.decl, some(m.ident)); word(s.s, ";"); end(s); } @@ -840,8 +840,8 @@ fn print_expr(s: ps, &&expr: @ast::expr) { } bclose_(s, expr.span, alt_indent_unit); } - ast::expr_fn(decl, body, captures) { // NDM captures - head(s, proto_to_str(decl.proto)); + ast::expr_fn(proto, decl, body, captures) { // NDM captures + head(s, proto_to_str(proto)); print_fn_args_and_ret(s, decl); space(s.s); print_block(s, body); @@ -1147,8 +1147,9 @@ fn print_pat(s: ps, &&pat: @ast::pat) { fn print_fn(s: ps, decl: ast::fn_decl, name: ast::ident, typarams: [ast::ty_param]) { alt decl.purity { - ast::impure_fn. { head(s, proto_to_str(decl.proto)); } - _ { head(s, "pure fn"); } + ast::impure_fn. { head(s, "fn"); } + ast::unsafe_fn. { head(s, "unsafe fn"); } + ast::pure_fn. { head(s, "pure fn"); } } word(s.s, name); print_type_params(s, typarams); @@ -1360,9 +1361,10 @@ fn print_mt(s: ps, mt: ast::mt) { print_type(s, mt.ty); } -fn print_ty_fn(s: ps, decl: ast::fn_decl, id: option::t<ast::ident>) { +fn print_ty_fn(s: ps, proto: ast::proto, + decl: ast::fn_decl, id: option::t<ast::ident>) { ibox(s, indent_unit); - word(s.s, proto_to_str(decl.proto)); + word(s.s, proto_to_str(proto)); alt id { some(id) { word(s.s, " "); word(s.s, id); } _ { } } zerobreak(s.s); popen(s); diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index 64dfafb9c4b..e2767160302 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -15,6 +15,28 @@ import codemap::span; // hold functions that take visitors. A vt tag is used to break the cycle. tag vt<E> { mk_vt(visitor<E>); } +tag fn_kind { + fk_item_fn(ident, [ty_param]); //< an item declared with fn() + fk_method(ident, [ty_param]); + fk_res(ident, [ty_param]); + fk_anon(proto); //< an anonymous function like lambda(...) + fk_fn_block; //< a block {||...} +} + +fn name_of_fn(fk: fn_kind) -> ident { + alt fk { + fk_item_fn(name, _) | fk_method(name, _) | fk_res(name, _) { name } + fk_anon(_) | fk_fn_block. { "anon" } + } +} + +fn tps_of_fn(fk: fn_kind) -> [ty_param] { + alt fk { + fk_item_fn(_, tps) | fk_method(_, tps) | fk_res(_, tps) { tps } + fk_anon(_) | fk_fn_block. { [] } + } +} + type visitor<E> = // takes the components so that one function can be // generic over constr and ty_constr @@ -31,8 +53,7 @@ type visitor<E> = visit_expr: fn@(@expr, E, vt<E>), visit_ty: fn@(@ty, E, vt<E>), visit_constr: fn@(@path, span, node_id, E, vt<E>), - visit_fn: fn@(fn_decl, [ty_param], blk, span, fn_ident, node_id, - E, vt<E>)}; + visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>)}; fn default_visitor<E>() -> visitor<E> { ret @{visit_mod: bind visit_mod::<E>(_, _, _, _), @@ -48,7 +69,7 @@ fn default_visitor<E>() -> visitor<E> { visit_expr: bind visit_expr::<E>(_, _, _), visit_ty: bind skip_ty::<E>(_, _, _), visit_constr: bind visit_constr::<E>(_, _, _, _, _), - visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _, _)}; + visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _)}; } fn visit_crate<E>(c: crate, e: E, v: vt<E>) { @@ -85,7 +106,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) { alt i.node { item_const(t, ex) { v.visit_ty(t, e, v); v.visit_expr(ex, e, v); } item_fn(decl, tp, body) { - v.visit_fn(decl, tp, body, i.span, some(i.ident), i.id, e, v); + v.visit_fn(fk_item_fn(i.ident, tp), decl, body, i.span, i.id, e, v); } item_mod(m) { v.visit_mod(m, i.span, e, v); } item_native_mod(nm) { @@ -94,8 +115,8 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) { } item_ty(t, tps) { v.visit_ty(t, e, v); visit_ty_params(tps, e, v); } item_res(decl, tps, body, dtor_id, _) { - v.visit_fn(decl, tps, body, i.span, some(i.ident), dtor_id, - e, v); + v.visit_fn(fk_res(i.ident, tps), decl, body, i.span, + dtor_id, e, v); } item_tag(variants, tps) { visit_ty_params(tps, e, v); @@ -107,8 +128,8 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) { visit_ty_params(tps, e, v); for f: obj_field in ob.fields { v.visit_ty(f.ty, e, v); } for m: @method in ob.methods { - v.visit_fn(m.decl, m.tps, m.body, m.span, - some(m.ident), m.id, e, v); + v.visit_fn(fk_method(m.ident, m.tps), m.decl, m.body, m.span, + m.id, e, v); } } item_impl(tps, ifce, ty, methods) { @@ -116,8 +137,8 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) { alt ifce { some(ty) { v.visit_ty(ty, e, v); } _ {} } v.visit_ty(ty, e, v); for m in methods { - v.visit_fn(m.decl, m.tps, m.body, m.span, - some(m.ident), m.id, e, v); + v.visit_fn(fk_method(m.ident, m.tps), m.decl, m.body, m.span, + m.id, e, v); } } item_iface(tps, methods) { @@ -142,7 +163,7 @@ fn visit_ty<E>(t: @ty, e: E, v: vt<E>) { for f: ty_field in flds { v.visit_ty(f.node.mt.ty, e, v); } } ty_tup(ts) { for tt in ts { v.visit_ty(tt, e, v); } } - ty_fn(decl) { + ty_fn(_, decl) { for a in decl.inputs { v.visit_ty(a.ty, e, v); } for c: @constr in decl.constraints { v.visit_constr(c.node.path, c.span, c.node.id, e, v); @@ -222,10 +243,10 @@ fn visit_fn_decl<E>(fd: fn_decl, e: E, v: vt<E>) { v.visit_ty(fd.output, e, v); } -fn visit_fn<E>(decl: fn_decl, tp: [ty_param], body: blk, _sp: span, - _i: fn_ident, _id: node_id, e: E, v: vt<E>) { +fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span, + _id: node_id, e: E, v: vt<E>) { visit_fn_decl(decl, e, v); - visit_ty_params(tp, e, v); + visit_ty_params(tps_of_fn(fk), e, v); v.visit_block(body, e, v); } @@ -314,11 +335,11 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) { v.visit_expr(x, e, v); for a: arm in arms { v.visit_arm(a, e, v); } } - expr_fn(decl, body, _) { - v.visit_fn(decl, [], body, ex.span, none, ex.id, e, v); + expr_fn(proto, decl, body, _) { + v.visit_fn(fk_anon(proto), decl, body, ex.span, ex.id, e, v); } expr_fn_block(decl, body) { - v.visit_fn(decl, [], body, ex.span, none, ex.id, e, v); + v.visit_fn(fk_fn_block, decl, body, ex.span, ex.id, e, v); } expr_block(b) { v.visit_block(b, e, v); } expr_assign(a, b) { v.visit_expr(b, e, v); v.visit_expr(a, e, v); } @@ -361,8 +382,8 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) { some(ex) { v.visit_expr(ex, e, v); } } for m: @method in anon_obj.methods { - v.visit_fn(m.decl, m.tps, m.body, m.span, - some(m.ident), m.id, e, v); + v.visit_fn(fk_method(m.ident, m.tps), m.decl, m.body, m.span, + m.id, e, v); } } expr_mac(mac) { visit_mac(mac, e, v); } @@ -394,7 +415,7 @@ type simple_visitor = visit_expr: fn@(@expr), visit_ty: fn@(@ty), visit_constr: fn@(@path, span, node_id), - visit_fn: fn@(fn_decl, [ty_param], blk, span, fn_ident, node_id)}; + visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id)}; fn simple_ignore_ty(_t: @ty) {} @@ -412,8 +433,8 @@ fn default_simple_visitor() -> simple_visitor { visit_expr: fn(_e: @expr) { }, visit_ty: simple_ignore_ty, visit_constr: fn(_p: @path, _sp: span, _id: node_id) { }, - visit_fn: fn(_d: fn_decl, _tps: [ty_param], _b: blk, _sp: span, - _ident: fn_ident, _id: node_id) { } + visit_fn: fn(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span, + _id: node_id) { } }; } @@ -472,11 +493,11 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> { f(pt, sp, id); visit_constr(pt, sp, id, e, v); } - fn v_fn(f: fn@(fn_decl, [ty_param], blk, span, fn_ident, node_id), - decl: fn_decl, tps: [ty_param], body: blk, sp: span, - ident: fn_ident, id: node_id, &&e: (), v: vt<()>) { - f(decl, tps, body, sp, ident, id); - visit_fn(decl, tps, body, sp, ident, id, e, v); + fn v_fn(f: fn@(fn_kind, fn_decl, blk, span, node_id), + fk: fn_kind, decl: fn_decl, body: blk, sp: span, + id: node_id, &&e: (), v: vt<()>) { + f(fk, decl, body, sp, id); + visit_fn(fk, decl, body, sp, id, e, v); } let visit_ty = if v.visit_ty == simple_ignore_ty { bind skip_ty(_, _, _) @@ -497,7 +518,7 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> { visit_expr: bind v_expr(v.visit_expr, _, _, _), visit_ty: visit_ty, visit_constr: bind v_constr(v.visit_constr, _, _, _, _, _), - visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _, _) + visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _) }); } diff --git a/src/comp/util/ppaux.rs b/src/comp/util/ppaux.rs index 39cb65dcf30..ec1b90572c0 100644 --- a/src/comp/util/ppaux.rs +++ b/src/comp/util/ppaux.rs @@ -23,10 +23,6 @@ fn mode_str_1(m: ty::mode) -> str { alt m { ast::by_ref. { "ref" } _ { mode_str(m) } } } -fn fn_ident_to_string(id: ast::node_id, i: ast::fn_ident) -> str { - ret alt i { none. { "anon" + int::str(id) } some(s) { s } }; -} - fn ty_to_str(cx: ctxt, typ: t) -> str { fn fn_input_to_str(cx: ctxt, input: {mode: middle::ty::mode, ty: t}) -> str { diff --git a/src/test/run-pass/block-arg-call-as.rs b/src/test/run-pass/block-arg-call-as.rs new file mode 100644 index 00000000000..caef692060e --- /dev/null +++ b/src/test/run-pass/block-arg-call-as.rs @@ -0,0 +1,22 @@ +use std; + +fn asSendfn( f : sendfn()->uint ) -> uint { + ret f(); +} + +fn asLambda( f : lambda()->uint ) -> uint { + ret f(); +} + +fn asBlock( f : block()->uint ) -> uint { + ret f(); +} + +fn main() { + let x = asSendfn({|| 22u}); + assert(x == 22u); + let x = asLambda({|| 22u}); + assert(x == 22u); + let x = asBlock({|| 22u}); + assert(x == 22u); +}