about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2012-08-23 18:17:16 -0700
committerMichael Sullivan <sully@msully.net>2012-08-23 19:40:01 -0700
commit0f996f70a632d1427801f20935a69a57fbb3679e (patch)
tree10bb420206b95838c5bd1b2ac6451cf93ef0b8f4 /src/rustc
parent34886ed488f6cc18c3fdc20cdeccab6178e00c0f (diff)
Remove purity from fn_decl and move it out to containing AST elements.
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/front/test.rs13
-rw-r--r--src/rustc/metadata/decoder.rs9
-rw-r--r--src/rustc/metadata/encoder.rs51
-rw-r--r--src/rustc/middle/borrowck/check_loans.rs6
-rw-r--r--src/rustc/middle/lint.rs2
-rw-r--r--src/rustc/middle/region.rs10
-rw-r--r--src/rustc/middle/resolve3.rs16
-rw-r--r--src/rustc/middle/trans/base.rs12
-rw-r--r--src/rustc/middle/trans/debuginfo.rs2
-rw-r--r--src/rustc/middle/trans/foreign.rs2
-rw-r--r--src/rustc/middle/trans/reachable.rs2
-rw-r--r--src/rustc/middle/trans/type_use.rs4
-rw-r--r--src/rustc/middle/ty.rs10
-rw-r--r--src/rustc/middle/typeck.rs2
-rw-r--r--src/rustc/middle/typeck/astconv.rs13
-rw-r--r--src/rustc/middle/typeck/check.rs31
-rw-r--r--src/rustc/middle/typeck/collect.rs37
17 files changed, 118 insertions, 104 deletions
diff --git a/src/rustc/front/test.rs b/src/rustc/front/test.rs
index cba7e89dcbb..d2abe360f67 100644
--- a/src/rustc/front/test.rs
+++ b/src/rustc/front/test.rs
@@ -71,7 +71,7 @@ fn fold_mod(cx: test_ctxt, m: ast::_mod, fld: fold::ast_fold) -> ast::_mod {
     // indicate to the translation pass which function we want to be main.
     fn nomain(cx: test_ctxt, item: @ast::item) -> option<@ast::item> {
         match item.node {
-          ast::item_fn(_, _, _) => {
+          ast::item_fn(*) => {
             if item.ident == cx.sess.ident_of(~"main") {
                 option::none
             } else { option::some(item) }
@@ -105,7 +105,7 @@ fn fold_item(cx: test_ctxt, &&i: @ast::item, fld: fold::ast_fold) ->
 
     if is_test_fn(i) {
         match i.node {
-          ast::item_fn(decl, _, _) if decl.purity == ast::unsafe_fn => {
+          ast::item_fn(decl, purity, _, _) if purity == ast::unsafe_fn => {
             cx.sess.span_fatal(
                 i.span,
                 ~"unsafe functions cannot be used for tests");
@@ -132,7 +132,7 @@ fn is_test_fn(i: @ast::item) -> bool {
 
     fn has_test_signature(i: @ast::item) -> bool {
         match i.node {
-          ast::item_fn(decl, tps, _) => {
+          ast::item_fn(decl, _, tps, _) => {
             let input_cnt = vec::len(decl.inputs);
             let no_output = decl.output.node == ast::ty_nil;
             let tparm_cnt = vec::len(tps);
@@ -223,7 +223,6 @@ fn mk_tests(cx: test_ctxt) -> @ast::item {
     let decl: ast::fn_decl =
         {inputs: ~[],
          output: ret_ty,
-         purity: ast::impure_fn,
          cf: ast::return_val};
 
     // The vector of test_descs for this crate
@@ -233,7 +232,7 @@ fn mk_tests(cx: test_ctxt) -> @ast::item {
         default_block(~[], option::some(test_descs), cx.sess.next_node_id());
     let body = nospan(body_);
 
-    let item_ = ast::item_fn(decl, ~[], body);
+    let item_ = ast::item_fn(decl, ast::impure_fn, ~[], body);
     let item: ast::item =
         {ident: cx.sess.ident_of(~"tests"),
          attrs: ~[],
@@ -389,7 +388,6 @@ fn mk_test_wrapper(cx: test_ctxt,
     let wrapper_decl: ast::fn_decl = {
         inputs: ~[],
         output: @{id: cx.sess.next_node_id(), node: ast::ty_nil, span: span},
-        purity: ast::impure_fn,
         cf: ast::return_val
     };
 
@@ -442,7 +440,6 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
     let decl: ast::fn_decl =
         {inputs: ~[args_arg],
          output: @ret_ty,
-         purity: ast::impure_fn,
          cf: ast::return_val};
 
     let test_main_call_expr = mk_test_main_call(cx);
@@ -452,7 +449,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
                       cx.sess.next_node_id());
     let body = {node: body_, span: dummy_sp()};
 
-    let item_ = ast::item_fn(decl, ~[], body);
+    let item_ = ast::item_fn(decl, ast::impure_fn, ~[], body);
     let item: ast::item =
         {ident: cx.sess.ident_of(~"main"),
          attrs: ~[],
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index 37f00be40ff..05457a710ea 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -695,13 +695,8 @@ fn get_trait_methods(intr: ident_interner, cdata: cmd, id: ast::node_id,
         } };
         let self_ty = get_self_ty(mth);
         vec::push(result, {ident: name, tps: bounds, fty: fty,
-                    self_ty: self_ty,
-                    purity: match item_family(mth) {
-                      UnsafeFn => ast::unsafe_fn,
-                      Fn => ast::impure_fn,
-                      PureFn => ast::pure_fn,
-                      _ => fail ~"bad purity"
-                    }, vis: ast::public});
+                           self_ty: self_ty,
+                           vis: ast::public});
     }
     #debug("get_trait_methods: }");
     @result
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 4e584fb167f..66d74c377ca 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -414,14 +414,14 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
     *index
 }
 
-fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
-                      id: node_id, ident: ident, path: ast_map::path,
-                      item: option<inlined_item>, tps: ~[ty_param],
-                      decl: fn_decl) {
+// This is for encoding info for ctors and dtors
+fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml::writer,
+                        id: node_id, ident: ident, path: ast_map::path,
+                        item: option<inlined_item>, tps: ~[ty_param]) {
         ebml_w.start_tag(tag_items_data_item);
         encode_name(ecx, ebml_w, ident);
         encode_def_id(ebml_w, local_def(id));
-        encode_family(ebml_w, purity_fn_family(decl.purity));
+        encode_family(ebml_w, purity_fn_family(ast::impure_fn));
         encode_type_param_bounds(ebml_w, ecx, tps);
         let its_ty = node_id_to_type(ecx.tcx, id);
         debug!("fn name = %s ty = %s its node id = %d",
@@ -448,7 +448,7 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::writer,
            ecx.tcx.sess.str_of(m.ident), all_tps.len());
     ebml_w.start_tag(tag_items_data_item);
     encode_def_id(ebml_w, local_def(m.id));
-    encode_family(ebml_w, purity_fn_family(m.decl.purity));
+    encode_family(ebml_w, purity_fn_family(m.purity));
     encode_type_param_bounds(ebml_w, ecx, all_tps);
     encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
     encode_name(ecx, ebml_w, m.ident);
@@ -519,11 +519,11 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         ebml_w.end_tag();
       }
-      item_fn(decl, tps, _) => {
+      item_fn(decl, purity, tps, _) => {
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
-        encode_family(ebml_w, purity_fn_family(decl.purity));
+        encode_family(ebml_w, purity_fn_family(purity));
         encode_type_param_bounds(ebml_w, ecx, tps);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
@@ -588,13 +588,14 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         /* Encode the dtor */
         do option::iter(struct_def.dtor) |dtor| {
             vec::push(*index, {val: dtor.node.id, pos: ebml_w.writer.tell()});
-          encode_info_for_fn(ecx, ebml_w, dtor.node.id,
-                             ecx.tcx.sess.ident_of(
-                                 ecx.tcx.sess.str_of(item.ident) + ~"_dtor"),
-                             path, if tps.len() > 0u {
-                                 some(ii_dtor(dtor, item.ident, tps,
-                                              local_def(item.id))) }
-                             else { none }, tps, ast_util::dtor_dec());
+          encode_info_for_ctor(ecx, ebml_w, dtor.node.id,
+                               ecx.tcx.sess.ident_of(
+                                   ecx.tcx.sess.str_of(item.ident) +
+                                   ~"_dtor"),
+                               path, if tps.len() > 0u {
+                                   some(ii_dtor(dtor, item.ident, tps,
+                                                local_def(item.id))) }
+                               else { none }, tps);
         }
 
         /* Index the class*/
@@ -647,7 +648,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
                 /* Write the info that's needed when viewing this class
                    as a trait */
                 ebml_w.start_tag(tag_item_trait_method);
-                encode_family(ebml_w, purity_fn_family(m.decl.purity));
+                encode_family(ebml_w, purity_fn_family(m.purity));
                 encode_name(ecx, ebml_w, m.ident);
                 encode_type_param_bounds(ebml_w, ecx, m.tps);
                 encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id));
@@ -675,11 +676,11 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
                 val: ctor.node.id,
                 pos: ebml_w.writer.tell()
             });
-            encode_info_for_fn(ecx, ebml_w, ctor.node.id, item.ident,
-                               path, if tps.len() > 0u {
-                                   some(ii_ctor(ctor, item.ident, tps,
-                                                local_def(item.id))) }
-                               else { none }, tps, ctor.node.dec);
+            encode_info_for_ctor(ecx, ebml_w, ctor.node.id, item.ident,
+                                 path, if tps.len() > 0u {
+                                     some(ii_ctor(ctor, item.ident, tps,
+                                                  local_def(item.id))) }
+                                 else { none }, tps);
         }
       }
       item_impl(tps, traits, _, methods) => {
@@ -734,7 +735,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
                 encode_name(ecx, ebml_w, mty.ident);
                 encode_type_param_bounds(ebml_w, ecx, ty_m.tps);
                 encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
-                encode_family(ebml_w, purity_fn_family(mty.purity));
+                encode_family(ebml_w, purity_fn_family(mty.fty.purity));
                 encode_self_type(ebml_w, mty.self_ty);
                 ebml_w.end_tag();
               }
@@ -766,7 +767,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
             encode_def_id(ebml_w, local_def(ty_m.id));
             encode_name(ecx, ebml_w, ty_m.ident);
             encode_family(ebml_w,
-                          purity_static_method_family(ty_m.decl.purity));
+                          purity_static_method_family(ty_m.purity));
             let polyty = ecx.tcx.tcache.get(local_def(ty_m.id));
             encode_ty_type_param_bounds(ebml_w, ecx, polyty.bounds);
             encode_type(ecx, ebml_w, polyty.ty);
@@ -789,9 +790,9 @@ fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
 
     ebml_w.start_tag(tag_items_data_item);
     match nitem.node {
-      foreign_item_fn(fn_decl, tps) => {
+      foreign_item_fn(fn_decl, purity, tps) => {
         encode_def_id(ebml_w, local_def(nitem.id));
-        encode_family(ebml_w, purity_fn_family(fn_decl.purity));
+        encode_family(ebml_w, purity_fn_family(purity));
         encode_type_param_bounds(ebml_w, ecx, tps);
         encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
         if abi == foreign_abi_rust_intrinsic {
diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs
index 6db7297618b..7c18133ae02 100644
--- a/src/rustc/middle/borrowck/check_loans.rs
+++ b/src/rustc/middle/borrowck/check_loans.rs
@@ -521,6 +521,8 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
         do save_and_restore(self.declared_purity) {
             do save_and_restore(self.fn_args) {
                 let is_stack_closure = self.is_stack_closure(id);
+                let purity =
+                    ty::ty_fn_purity(ty::node_id_to_type(self.tcx(), id));
 
                 // In principle, we could consider fk_anon(*) or
                 // fk_fn_block(*) to be in a ctor, I suppose, but the
@@ -531,7 +533,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
                 match fk {
                   visit::fk_ctor(*) => {
                     self.in_ctor = true;
-                    self.declared_purity = decl.purity;
+                    self.declared_purity = purity;
                     self.fn_args = @decl.inputs.map(|i| i.id );
                   }
                   visit::fk_anon(*) |
@@ -543,7 +545,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
                   visit::fk_method(*) | visit::fk_item_fn(*) |
                   visit::fk_dtor(*) => {
                     self.in_ctor = false;
-                    self.declared_purity = decl.purity;
+                    self.declared_purity = purity;
                     self.fn_args = @decl.inputs.map(|i| i.id );
                   }
                 }
diff --git a/src/rustc/middle/lint.rs b/src/rustc/middle/lint.rs
index 1137ec47cdd..7b7e163d38c 100644
--- a/src/rustc/middle/lint.rs
+++ b/src/rustc/middle/lint.rs
@@ -401,7 +401,7 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) {
       either::Right(ast::foreign_abi_rust_intrinsic) => {
         for nmod.items.each |ni| {
             match ni.node {
-              ast::foreign_item_fn(decl, tps) => {
+              ast::foreign_item_fn(decl, _, tps) => {
                 check_foreign_fn(cx, it.id, decl);
               }
             }
diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs
index 17d4eaa5984..5b6a64ccd73 100644
--- a/src/rustc/middle/region.rs
+++ b/src/rustc/middle/region.rs
@@ -613,8 +613,8 @@ fn determine_rp_in_ty(ty: @ast::ty,
         }
       }
 
-      ast::ty_fn(ast::proto_bare, _, _) |
-      ast::ty_fn(ast::proto_block, _, _) if cx.anon_implies_rp => {
+      ast::ty_fn(ast::proto_bare, _, _, _) |
+      ast::ty_fn(ast::proto_block, _, _, _) if cx.anon_implies_rp => {
         debug!("referenced bare fn type with regions %s",
                pprust::ty_to_str(ty, cx.sess.intr()));
         cx.add_rp(cx.item_id, cx.add_variance(rv_contravariant));
@@ -661,8 +661,8 @@ fn determine_rp_in_ty(ty: @ast::ty,
     match ty.node {
       ast::ty_box(mt) | ast::ty_uniq(mt) => {
         match mt.ty.node {
-          ast::ty_fn(ast::proto_bare, _, _) |
-          ast::ty_fn(ast::proto_block, _, _) => {
+          ast::ty_fn(ast::proto_bare, _, _, _) |
+          ast::ty_fn(ast::proto_block, _, _, _) => {
             do cx.with(cx.item_id, false) {
                 visit_mt(mt, cx, visitor);
             }
@@ -695,7 +695,7 @@ fn determine_rp_in_ty(ty: @ast::ty,
         }
       }
 
-      ast::ty_fn(_, bounds, decl) => {
+      ast::ty_fn(_, _, bounds, decl) => {
         // fn() binds the & region, so do not consider &T types that
         // appear *inside* a fn() type to affect the enclosing item:
         do cx.with(cx.item_id, false) {
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index da6b0b5087b..66b7818d880 100644
--- a/src/rustc/middle/resolve3.rs
+++ b/src/rustc/middle/resolve3.rs
@@ -891,11 +891,11 @@ struct Resolver {
                      def_const(local_def(item.id)),
                      sp);
             }
-            item_fn(decl, _, _) => {
+            item_fn(decl, purity, _, _) => {
               let (name_bindings, new_parent) = self.add_child(atom, parent,
                                                         ~[ValueNS], sp);
 
-                let def = def_fn(local_def(item.id), decl.purity);
+                let def = def_fn(local_def(item.id), purity);
                 (*name_bindings).define_value
                     (self.visibility_to_privacy(item.vis), def, sp);
                 visit_item(item, new_parent, visitor);
@@ -954,7 +954,7 @@ struct Resolver {
                         (*name_bindings).define_type
                             (privacy, def_ty(local_def(item.id)), sp);
 
-                        let purity = ctor.node.dec.purity;
+                        let purity = impure_fn;
                         let ctor_def = def_fn(local_def(ctor.node.id),
                                               purity);
                         (*name_bindings).define_value(privacy, ctor_def, sp);
@@ -992,7 +992,7 @@ struct Resolver {
                             self.add_child(atom, new_parent, ~[ValueNS],
                                            ty_m.span);
                         let def = def_static_method(local_def(ty_m.id),
-                                                    ty_m.decl.purity);
+                                                    ty_m.purity);
                         (*method_name_bindings).define_value
                             (Public, def, ty_m.span);
                       }
@@ -1215,11 +1215,11 @@ struct Resolver {
         let name = foreign_item.ident;
 
         match foreign_item.node {
-            foreign_item_fn(fn_decl, type_parameters) => {
+            foreign_item_fn(fn_decl, purity, type_parameters) => {
               let (name_bindings, new_parent) = self.add_child(name, parent,
                                               ~[ValueNS], foreign_item.span);
 
-                let def = def_fn(local_def(foreign_item.id), fn_decl.purity);
+                let def = def_fn(local_def(foreign_item.id), purity);
                 (*name_bindings).define_value(Public, def, foreign_item.span);
 
                 do self.with_type_parameter_rib
@@ -2944,7 +2944,7 @@ struct Resolver {
                 do self.with_scope(some(item.ident)) {
                     for foreign_module.items.each |foreign_item| {
                         match foreign_item.node {
-                            foreign_item_fn(_, type_parameters) => {
+                            foreign_item_fn(_, _, type_parameters) => {
                                 do self.with_type_parameter_rib
                                     (HasTypeParameters(&type_parameters,
                                                        foreign_item.id,
@@ -2961,7 +2961,7 @@ struct Resolver {
                 }
             }
 
-            item_fn(fn_decl, ty_params, block) => {
+            item_fn(fn_decl, _, ty_params, block) => {
                 // If this is the main function, we must record it in the
                 // session.
                 //
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 60a57540fa9..13988ad8861 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -2214,7 +2214,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id,
 
     let psubsts = some({tys: substs, vtables: vtables, bounds: tpt.bounds});
     let lldecl = match map_node {
-      ast_map::node_item(i@@{node: ast::item_fn(decl, _, body), _}, _) => {
+      ast_map::node_item(i@@{node: ast::item_fn(decl, _, _, body), _}, _) => {
         let d = mk_lldecl();
         set_inline_hint_if_appr(i.attrs, d);
         trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node);
@@ -5010,8 +5010,8 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
       ast_map::node_item(_, p) => p
     };
     match item.node {
-      ast::item_fn(decl, tps, body) => {
-        if decl.purity == ast::extern_fn  {
+      ast::item_fn(decl, purity, tps, body) => {
+        if purity == ast::extern_fn  {
             let llfndecl = get_item_val(ccx, item.id);
             foreign::trans_foreign_fn(ccx,
                                      vec::append(
@@ -5304,8 +5304,8 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
                 ccx.item_symbols.insert(i.id, s);
                 g
               }
-              ast::item_fn(decl, _, _) => {
-                let llfn = if decl.purity != ast::extern_fn {
+              ast::item_fn(decl, purity, _, _) => {
+                let llfn = if purity != ast::extern_fn {
                     register_fn(ccx, i.span, my_path, i.id)
                 } else {
                     foreign::register_foreign_fn(ccx, i.span, my_path, i.id)
@@ -5535,7 +5535,7 @@ fn push_rtcall(ccx: @crate_ctxt, name: ~str, did: ast::def_id) {
 fn gather_local_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) {
     visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
         visit_item: |item| match item.node {
-          ast::item_fn(decl, _, _) => {
+          ast::item_fn(decl, _, _, _) => {
             let attr_metas = attr::attr_metas(
                 attr::find_attrs_by_name(item.attrs, ~"rt"));
             do vec::iter(attr_metas) |attr_meta| {
diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs
index 18603f0edeb..04e0f7be75f 100644
--- a/src/rustc/middle/trans/debuginfo.rs
+++ b/src/rustc/middle/trans/debuginfo.rs
@@ -721,7 +721,7 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
     let (ident, ret_ty, id) = match cx.tcx.items.get(fcx.id) {
       ast_map::node_item(item, _) => {
         match item.node {
-          ast::item_fn(decl, _, _) => {
+          ast::item_fn(decl, _, _, _) => {
             (item.ident, decl.output, item.id)
           }
           _ => fcx.ccx.sess.span_bug(item.span, ~"create_function: item \
diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs
index 10e657af0f4..efcdc644104 100644
--- a/src/rustc/middle/trans/foreign.rs
+++ b/src/rustc/middle/trans/foreign.rs
@@ -755,7 +755,7 @@ fn trans_foreign_mod(ccx: @crate_ctxt,
 
     for vec::each(foreign_mod.items) |foreign_item| {
       match foreign_item.node {
-        ast::foreign_item_fn(fn_decl, typarams) => {
+        ast::foreign_item_fn(fn_decl, purity, typarams) => {
           let id = foreign_item.id;
           if abi != ast::foreign_abi_rust_intrinsic {
               let llwrapfn = get_item_val(ccx, id);
diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs
index 5ea2d8625e6..48ab856342a 100644
--- a/src/rustc/middle/trans/reachable.rs
+++ b/src/rustc/middle/trans/reachable.rs
@@ -96,7 +96,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
               for vec::each(nm.items) |item| { cx.rmap.insert(item.id, ()); }
           }
       }
-      item_fn(_, tps, blk) => {
+      item_fn(_, _, tps, blk) => {
         if tps.len() > 0u ||
            attr::find_inline_attr(item.attrs) != attr::ia_none {
             traverse_inline_body(cx, blk);
diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs
index ce84269bb67..2b527bb9682 100644
--- a/src/rustc/middle/trans/type_use.rs
+++ b/src/rustc/middle/trans/type_use.rs
@@ -65,7 +65,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
                                      fn_id_loc))
     };
     match map_node {
-      ast_map::node_item(@{node: item_fn(_, _, body), _}, _) |
+      ast_map::node_item(@{node: item_fn(_, _, _, body), _}, _) |
       ast_map::node_method(@{body, _}, _, _) => {
         handle_body(cx, body);
       }
@@ -78,7 +78,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
       ast_map::node_variant(_, _, _) => {
         for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr;}
       }
-      ast_map::node_foreign_item(i@@{node: foreign_item_fn(_, _), _},
+      ast_map::node_foreign_item(i@@{node: foreign_item_fn(*), _},
                                  abi, _) => {
         if abi == foreign_abi_rust_intrinsic {
             let flags = match cx.ccx.sess.str_of(i.ident) {
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 15eaa683bae..b5411dd597c 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -79,7 +79,7 @@ export ty_opaque_closure_ptr, mk_opaque_closure_ptr;
 export ty_opaque_box, mk_opaque_box;
 export ty_float, mk_float, mk_mach_float, type_is_fp;
 export ty_fn, fn_ty, mk_fn;
-export ty_fn_proto, ty_fn_ret, ty_fn_ret_style, tys_in_fn_ty;
+export ty_fn_proto, ty_fn_purity, ty_fn_ret, ty_fn_ret_style, tys_in_fn_ty;
 export ty_int, mk_int, mk_mach_int, mk_char;
 export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64;
 export ty_estr, mk_estr, type_is_str;
@@ -202,7 +202,6 @@ type method = {ident: ast::ident,
                tps: @~[param_bounds],
                fty: fn_ty,
                self_ty: ast::self_ty_,
-               purity: ast::purity,
                vis: ast::visibility};
 
 type mt = {ty: t, mutbl: ast::mutability};
@@ -2358,6 +2357,13 @@ fn ty_fn_proto(fty: t) -> fn_proto {
     }
 }
 
+fn ty_fn_purity(fty: t) -> ast::purity {
+    match get(fty).struct {
+      ty_fn(ref f) => f.purity,
+      _ => fail ~"ty_fn_purity() called on non-fn type"
+    }
+}
+
 pure fn ty_fn_ret(fty: t) -> t {
     match get(fty).struct {
       ty_fn(ref f) => f.output,
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 302bc604c2a..d4ed45f99b3 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -259,7 +259,7 @@ fn check_main_fn_ty(ccx: @crate_ctxt,
         match tcx.items.find(main_id) {
          some(ast_map::node_item(it,_)) => {
              match it.node {
-               ast::item_fn(_,ps,_) if vec::is_not_empty(ps) => {
+               ast::item_fn(_,_,ps,_) if vec::is_not_empty(ps) => {
                   tcx.sess.span_err(main_span,
                     ~"main function is not allowed to have type parameters");
                   return;
diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs
index 1b6f4e86a61..374e14749f2 100644
--- a/src/rustc/middle/typeck/astconv.rs
+++ b/src/rustc/middle/typeck/astconv.rs
@@ -201,7 +201,7 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy owned>(
               _ => ()
             }
           }
-          ast::ty_fn(ast::proto_block, ast_bounds, ast_fn_decl) => {
+          ast::ty_fn(ast::proto_block, purity, ast_bounds, ast_fn_decl) => {
             let new_proto;
             match vst {
                 ty::vstore_fixed(_) => {
@@ -216,7 +216,8 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy owned>(
 
             // Run through the normal function type conversion process.
             let bounds = collect::compute_bounds(self.ccx(), ast_bounds);
-            let fn_decl = ty_of_fn_decl(self, rscope, new_proto, bounds,
+            let fn_decl = ty_of_fn_decl(self, rscope, new_proto, purity,
+                                        bounds,
                                         ast_fn_decl, none, span);
             return ty::mk_fn(tcx, fn_decl);
           }
@@ -301,9 +302,10 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy owned>(
         };
         ty::mk_rec(tcx, flds)
       }
-      ast::ty_fn(proto, ast_bounds, decl) => {
+      ast::ty_fn(proto, purity, ast_bounds, decl) => {
         let bounds = collect::compute_bounds(self.ccx(), ast_bounds);
-        let fn_decl = ty_of_fn_decl(self, rscope, proto, bounds, decl, none,
+        let fn_decl = ty_of_fn_decl(self, rscope, proto, purity,
+                                    bounds, decl, none,
                                     ast_ty.span);
         ty::mk_fn(tcx, fn_decl)
       }
@@ -465,6 +467,7 @@ type expected_tys = option<{inputs: ~[ty::arg],
 fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy owned>(
     self: AC, rscope: RS,
     ast_proto: ast::proto,
+    purity: ast::purity,
     bounds: @~[ty::param_bound],
     decl: ast::fn_decl,
     expected_tys: expected_tys,
@@ -494,7 +497,7 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy owned>(
 
         let proto = ast_proto_to_proto(self, rscope, span, ast_proto);
 
-        {purity: decl.purity, proto: proto, bounds: bounds, inputs: input_tys,
+        {purity: purity, proto: proto, bounds: bounds, inputs: input_tys,
          output: output_ty, ret_style: decl.cf}
     }
 }
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index 7b71c59bf26..aa51f2dd4a2 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -223,12 +223,12 @@ fn check_fn(ccx: @crate_ctxt,
           none => {
             {infcx: infer::new_infer_ctxt(tcx),
              locals: int_hash(),
-             purity: decl.purity,
+             purity: fn_ty.purity,
              node_types: map::int_hash(),
              node_type_substs: map::int_hash()}
           }
           some(fcx) => {
-            assert decl.purity == ast::impure_fn;
+            assert fn_ty.purity == ast::impure_fn;
             {infcx: fcx.infcx,
              locals: fcx.locals,
              purity: fcx.purity,
@@ -476,7 +476,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
       ast::item_enum(enum_definition, _) => {
         check_enum_variants(ccx, it.span, enum_definition.variants, it.id);
       }
-      ast::item_fn(decl, tps, body) => {
+      ast::item_fn(decl, _, tps, body) => {
         check_bare_fn(ccx, decl, body, it.id, none);
       }
       ast::item_impl(tps, _, ty, ms) => {
@@ -1232,8 +1232,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
             }
         }
 
+        let purity = ast::impure_fn;
+
         // construct the function type
-        let mut fn_ty = astconv::ty_of_fn_decl(fcx, fcx, ast_proto, @~[],
+        let mut fn_ty = astconv::ty_of_fn_decl(fcx, fcx, ast_proto, purity,
+                                               @~[],
                                                decl, expected_tys, expr.span);
 
         // Patch up the function declaration, if necessary.
@@ -1599,16 +1602,18 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
         bot = alt::check_alt(fcx, expr, discrim, arms);
       }
       ast::expr_fn(proto, decl, body, cap_clause) => {
-        check_expr_fn(fcx, expr, foap_ast_proto(proto), decl, body, false,
+        check_expr_fn(fcx, expr, foap_ast_proto(proto),
+                      decl, body, false,
                       expected);
         capture::check_capture_clause(tcx, expr.id, cap_clause);
       }
       ast::expr_fn_block(decl, body, cap_clause) => {
-         // Take the prototype from the expected type, but default to block:
-          let proto = unpack_expected(fcx, expected, |sty|
-              match sty { ty::ty_fn({proto, _}) => some(proto), _ => none }
-          ).get_default(ty::proto_vstore(ty::vstore_box));
-        check_expr_fn(fcx, expr, foap_fn_proto(proto), decl, body, false,
+        // Take the prototype from the expected type, but default to block:
+        let proto = do unpack_expected(fcx, expected) |sty| {
+            match sty { ty::ty_fn({proto, _}) => some(proto), _ => none }
+        }.get_default(ty::proto_vstore(ty::vstore_box));
+        check_expr_fn(fcx, expr, foap_fn_proto(proto),
+                      decl, body, false,
                       expected);
         capture::check_capture_clause(tcx, expr.id, cap_clause);
       }
@@ -1642,7 +1647,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
         };
         match check b.node {
           ast::expr_fn_block(decl, body, cap_clause) => {
-            check_expr_fn(fcx, b, foap_fn_proto(proto), decl, body, true,
+            check_expr_fn(fcx, b, foap_fn_proto(proto),
+                          decl, body, true,
                           some(inner_ty));
             demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
             capture::check_capture_clause(tcx, b.id, cap_clause);
@@ -1671,7 +1677,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
         };
         match check b.node {
           ast::expr_fn_block(decl, body, cap_clause) => {
-            check_expr_fn(fcx, b, foap_fn_proto(proto), decl, body, true,
+            check_expr_fn(fcx, b, foap_fn_proto(proto),
+                          decl, body, true,
                           some(inner_ty));
             demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
             capture::check_capture_clause(tcx, b.id, cap_clause);
diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs
index 132ec2a4e90..b87380720ce 100644
--- a/src/rustc/middle/typeck/collect.rs
+++ b/src/rustc/middle/typeck/collect.rs
@@ -247,7 +247,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
                        trait_m: ty::method, trait_substs: ty::substs,
                        self_ty: ty::t) {
 
-    if impl_m.purity != trait_m.purity {
+    if impl_m.fty.purity != trait_m.fty.purity {
         tcx.sess.span_err(
             sp, fmt!("method `%s`'s purity does \
                           not match the trait method's \
@@ -506,7 +506,8 @@ fn convert_struct(ccx: @crate_ctxt,
         // Write the dtor type
         let t_dtor = ty::mk_fn(
             tcx,
-            ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare, @~[],
+            ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare,
+                          ast::impure_fn, @~[],
                           ast_util::dtor_dec(), none, dtor.span));
         write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
         tcx.tcache.insert(local_def(dtor.node.id),
@@ -537,7 +538,7 @@ fn convert_foreign(ccx: @crate_ctxt, i: @ast::foreign_item) {
     // table.
     let tpt = ty_of_foreign_item(ccx, i);
     match i.node {
-      ast::foreign_item_fn(_, _) => {
+      ast::foreign_item_fn(*) => {
         write_ty_to_tcx(ccx.tcx, i.id, tpt.ty);
         ccx.tcx.tcache.insert(local_def(i.id), tpt);
       }
@@ -549,10 +550,10 @@ fn ty_of_method(ccx: @crate_ctxt,
                 rp: option<ty::region_variance>) -> ty::method {
     {ident: m.ident,
      tps: ty_param_bounds(ccx, m.tps),
-     fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare, @~[],
+     fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare,
+                        m.purity, @~[],
                         m.decl, none, m.span),
      self_ty: m.self_ty.node,
-     purity: m.decl.purity,
      vis: m.vis}
 }
 
@@ -561,11 +562,11 @@ fn ty_of_ty_method(self: @crate_ctxt,
                    rp: option<ty::region_variance>) -> ty::method {
     {ident: m.ident,
      tps: ty_param_bounds(self, m.tps),
-     fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare, @~[], m.decl,
-                        none, m.span),
+     fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare, m.purity,
+                        @~[], m.decl, none, m.span),
      // assume public, because this is only invoked on trait methods
      self_ty: m.self_ty.node,
-     purity: m.decl.purity, vis: ast::public}
+     vis: ast::public}
 }
 
 /*
@@ -614,9 +615,10 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
         tcx.tcache.insert(local_def(it.id), tpt);
         return tpt;
       }
-      ast::item_fn(decl, tps, _) => {
+      ast::item_fn(decl, purity, tps, _) => {
         let bounds = ty_param_bounds(ccx, tps);
-        let tofd = ty_of_fn_decl(ccx, empty_rscope, ast::proto_bare, @~[],
+        let tofd = ty_of_fn_decl(ccx, empty_rscope,
+                                 ast::proto_bare, purity, @~[],
                                  decl, none, it.span);
         let tpt = {bounds: bounds,
                    region_param: none,
@@ -689,9 +691,9 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
 fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item)
     -> ty::ty_param_bounds_and_ty {
     match it.node {
-      ast::foreign_item_fn(fn_decl, params) => {
-        return ty_of_foreign_fn_decl(ccx, fn_decl, params,
-                                  local_def(it.id));
+      ast::foreign_item_fn(fn_decl, purity, params) => {
+        return ty_of_foreign_fn_decl(ccx, fn_decl, purity, params,
+                                     local_def(it.id));
       }
     }
 }
@@ -739,16 +741,17 @@ fn ty_param_bounds(ccx: @crate_ctxt,
 }
 
 fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
-                        decl: ast::fn_decl,
-                        ty_params: ~[ast::ty_param],
-                        def_id: ast::def_id) -> ty::ty_param_bounds_and_ty {
+                         decl: ast::fn_decl,
+                         purity: ast::purity,
+                         ty_params: ~[ast::ty_param],
+                         def_id: ast::def_id) -> ty::ty_param_bounds_and_ty {
 
     let bounds = ty_param_bounds(ccx, ty_params);
     let rb = in_binding_rscope(empty_rscope);
     let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, rb, a, none) );
     let output_ty = ast_ty_to_ty(ccx, rb, decl.output);
 
-    let t_fn = ty::mk_fn(ccx.tcx, {purity: decl.purity,
+    let t_fn = ty::mk_fn(ccx.tcx, {purity: purity,
                                    proto: ty::proto_bare,
                                    bounds: @~[],
                                    inputs: input_tys,