about summary refs log tree commit diff
path: root/src/comp/middle
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/middle
parentd6db9506f421ebc6a48cc101307c1f5dca92c53e (diff)
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/middle')
-rw-r--r--src/comp/middle/alias.rs6
-rw-r--r--src/comp/middle/ast_map.rs6
-rw-r--r--src/comp/middle/debuginfo.rs2
-rw-r--r--src/comp/middle/freevars.rs9
-rw-r--r--src/comp/middle/kind.rs8
-rw-r--r--src/comp/middle/last_use.rs10
-rw-r--r--src/comp/middle/resolve.rs32
-rw-r--r--src/comp/middle/trans.rs8
-rw-r--r--src/comp/middle/trans_closure.rs5
-rw-r--r--src/comp/middle/tstate/annotate.rs6
-rw-r--r--src/comp/middle/tstate/auxiliary.rs4
-rw-r--r--src/comp/middle/tstate/bitvectors.rs2
-rw-r--r--src/comp/middle/tstate/ck.rs21
-rw-r--r--src/comp/middle/tstate/collect_locals.rs20
-rw-r--r--src/comp/middle/tstate/pre_post_conditions.rs11
-rw-r--r--src/comp/middle/tstate/states.rs2
-rw-r--r--src/comp/middle/typeck.rs67
17 files changed, 114 insertions, 105 deletions
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.