about summary refs log tree commit diff
path: root/src/comp/syntax
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2011-12-29 20:07:55 -0800
committerNiko Matsakis <niko@alum.mit.edu>2011-12-29 20:29:28 -0800
commitaa5382bb13690ff183f6e94065dadf0524ce1c6e (patch)
tree627037c40c72983b75572e1bc3d04c0b3ab3fde4 /src/comp/syntax
parentd6db9506f421ebc6a48cc101307c1f5dca92c53e (diff)
downloadrust-aa5382bb13690ff183f6e94065dadf0524ce1c6e.tar.gz
rust-aa5382bb13690ff183f6e94065dadf0524ce1c6e.zip
split proto from fn_decl, as not all fn_decls know the proto.
this will address the (crashing) new test added.
Diffstat (limited to 'src/comp/syntax')
-rw-r--r--src/comp/syntax/ast.rs7
-rw-r--r--src/comp/syntax/fold.rs11
-rw-r--r--src/comp/syntax/parse/parser.rs59
-rw-r--r--src/comp/syntax/print/pprust.rs20
-rw-r--r--src/comp/syntax/visit.rs77
5 files changed, 89 insertions, 85 deletions
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, _, _, _, _, _, _, _)
                });
 }