about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2010-11-02 11:11:58 -0700
committerGraydon Hoare <graydon@mozilla.com>2010-11-02 11:11:58 -0700
commitda13c508d83032ca13679e1e122e96d25ac23283 (patch)
tree51c3d466dfedf3ad8e21b56c4769325561b3d650 /src
parentccd62969c1bb07f8931de0819979f060f5414bcc (diff)
First pass on splitting stratum and opacity off of effects. WIP.
Diffstat (limited to 'src')
-rw-r--r--src/boot/fe/ast.ml80
-rw-r--r--src/boot/fe/cexp.ml2
-rw-r--r--src/boot/fe/fuzz.ml2
-rw-r--r--src/boot/fe/item.ml35
-rw-r--r--src/boot/fe/lexer.mll6
-rw-r--r--src/boot/fe/pexp.ml22
-rw-r--r--src/boot/fe/token.ml20
-rw-r--r--src/boot/me/dwarf.ml15
-rw-r--r--src/boot/me/effect.ml14
-rw-r--r--src/boot/me/semant.ml49
-rw-r--r--src/boot/me/typestate.ml3
-rw-r--r--src/comp/driver/rustc.rs4
-rw-r--r--src/comp/front/lexer.rs14
-rw-r--r--src/comp/front/parser.rs94
-rw-r--r--src/comp/rustc.rc2
-rw-r--r--src/lib/map.rs2
-rw-r--r--src/lib/sys.rs4
-rw-r--r--src/rt/rust_builtin.cpp2
-rw-r--r--src/test/compile-fail/comm-makes-io.rs2
-rw-r--r--src/test/compile-fail/impure-pred.rs2
-rw-r--r--src/test/compile-fail/io-infects-caller.rs4
-rw-r--r--src/test/compile-fail/unnecessary-io.rs2
-rw-r--r--src/test/run-fail/linked-failure.rs2
-rw-r--r--src/test/run-pass/acyclic-unwind.rs4
-rw-r--r--src/test/run-pass/basic-1.rs6
-rw-r--r--src/test/run-pass/basic-2.rs6
-rw-r--r--src/test/run-pass/basic.rs6
-rw-r--r--src/test/run-pass/comm.rs4
-rw-r--r--src/test/run-pass/lazychan.rs4
-rw-r--r--src/test/run-pass/lib-map.rs2
-rw-r--r--src/test/run-pass/obj-dtor.rs4
-rw-r--r--src/test/run-pass/preempt.rs4
-rw-r--r--src/test/run-pass/task-comm-0.rs6
-rw-r--r--src/test/run-pass/task-comm-11.rs4
-rw-r--r--src/test/run-pass/task-comm-13-thread.rs2
-rw-r--r--src/test/run-pass/task-comm-13.rs2
-rw-r--r--src/test/run-pass/task-comm-4.rs4
-rw-r--r--src/test/run-pass/task-comm-5.rs4
-rw-r--r--src/test/run-pass/task-comm-6.rs4
-rw-r--r--src/test/run-pass/task-comm-7.rs6
40 files changed, 271 insertions, 183 deletions
diff --git a/src/boot/fe/ast.ml b/src/boot/fe/ast.ml
index f81f614fc82..b72c4935af5 100644
--- a/src/boot/fe/ast.ml
+++ b/src/boot/fe/ast.ml
@@ -29,10 +29,20 @@ type slot_key =
  *)
 
 type effect =
-    PURE
-  | IO
-  | STATE
-  | UNSAFE
+    EFF_pure
+  | EFF_impure
+  | EFF_unsafe
+;;
+
+type stratum =
+    STRAT_value
+  | STRAT_state
+  | STRAT_gc
+;;
+
+type opacity =
+    OPA_transparent
+  | OPA_abstract
 ;;
 
 type mutability =
@@ -702,10 +712,48 @@ and fmt_effect
     (effect:effect)
     : unit =
   match effect with
-      PURE -> ()
-    | IO -> fmt ff "io"
-    | STATE -> fmt ff "state"
-    | UNSAFE -> fmt ff "unsafe"
+      EFF_pure -> ()
+    | EFF_impure -> fmt ff "impure"
+    | EFF_unsafe -> fmt ff "unsafe"
+
+and fmt_effect_qual
+    (ff:Format.formatter)
+    (e:effect)
+    : unit =
+  fmt_effect ff e;
+  if e <> EFF_pure then fmt ff " ";
+
+and fmt_stratum
+    (ff:Format.formatter)
+    (strat:stratum)
+    : unit =
+  match strat with
+      STRAT_value -> ()
+    | STRAT_state -> fmt ff "state"
+    | STRAT_gc -> fmt ff "gc"
+
+and fmt_stratum_qual
+    (ff:Format.formatter)
+    (s:stratum)
+    : unit =
+  fmt_stratum ff s;
+  if s <> STRAT_value then fmt ff " ";
+
+and fmt_opacity
+    (ff:Format.formatter)
+    (opa:opacity)
+    : unit =
+  match opa with
+      OPA_transparent -> ()
+    | OPA_abstract -> fmt ff "abs"
+
+and fmt_opacity_qual
+    (ff:Format.formatter)
+    (op:opacity)
+    : unit =
+  fmt_opacity ff op;
+  if op <> OPA_transparent then fmt ff " ";
+
 
 and fmt_ty_fn
     (ff:Format.formatter)
@@ -713,8 +761,7 @@ and fmt_ty_fn
     (tf:ty_fn)
     : unit =
   let (tsig, ta) = tf in
-    fmt_effect ff ta.fn_effect;
-    if ta.fn_effect <> PURE then fmt ff " ";
+    fmt_effect_qual ff ta.fn_effect;
     fmt ff "%s" (if ta.fn_is_iter then "iter" else "fn");
     begin
       match ident_and_params with
@@ -763,8 +810,7 @@ and fmt_ty (ff:Format.formatter) (t:ty) : unit =
       fmt_ident_tys ff entries;
       fmt ff "@]"
 
-  | TY_param (i, e) -> (fmt_effect ff e;
-                        if e <> PURE then fmt ff " ";
+  | TY_param (i, e) -> (fmt_effect_qual ff e;
                         fmt ff "<p#%d>" i)
   | TY_native oid -> fmt ff "<native#%d>" (int_of_opaque oid)
   | TY_named n -> fmt_name ff n
@@ -789,8 +835,7 @@ and fmt_ty (ff:Format.formatter) (t:ty) : unit =
 
   | TY_obj (effect, fns) ->
       fmt_obox ff;
-      fmt_effect ff effect;
-      if effect <> PURE then fmt ff " ";
+      fmt_effect_qual ff effect;
       fmt ff "obj ";
       fmt_obr ff;
       Hashtbl.iter
@@ -1584,8 +1629,7 @@ and fmt_slice (ff:Format.formatter) (slice:slice) : unit =
 
 and fmt_decl_param (ff:Format.formatter) (param:ty_param) : unit =
   let (ident, (i, e)) = param in
-  fmt_effect ff e;
-  if e <> PURE then fmt ff " ";
+  fmt_effect_qual ff e;
   fmt_ident ff ident;
   fmt ff "=<p#%d>" i
 
@@ -1608,10 +1652,6 @@ and fmt_ident_and_params
   fmt_ident ff id;
   fmt_decl_params ff params
 
-and fmt_effect_qual (ff:Format.formatter) (e:effect) : unit =
-  fmt_effect ff e;
-  if e <> PURE then fmt ff " ";
-
 and fmt_fn
     (ff:Format.formatter)
     (id:ident)
diff --git a/src/boot/fe/cexp.ml b/src/boot/fe/cexp.ml
index 6828689f942..3ca4ded78a3 100644
--- a/src/boot/fe/cexp.ml
+++ b/src/boot/fe/cexp.ml
@@ -181,7 +181,7 @@ and parse_cexp (ps:pstate) : cexp =
                   fun (ident, item) ->
                     htab_put items ident item
                 end
-                (Item.parse_mod_item_from_signature ps)
+                (Item.parse_native_mod_item_from_signature ps)
             in
               ignore (bracketed_zero_or_more
                         LBRACE RBRACE None get_item ps);
diff --git a/src/boot/fe/fuzz.ml b/src/boot/fe/fuzz.ml
index 47a708dcebd..e8db9f39032 100644
--- a/src/boot/fe/fuzz.ml
+++ b/src/boot/fe/fuzz.ml
@@ -104,7 +104,7 @@ let rec generate_mod_item (mis:mod_items) (cx:ctxt) : unit =
     match Random.int 2 with
         0 ->
           let ty = generate_ty cx in
-          let eff = PURE in
+          let eff = Ast.EFF_pure in
             decl (MOD_ITEM_type (eff, ty))
       | _ ->
           let mis' = Hashtbl.create 0 in
diff --git a/src/boot/fe/item.ml b/src/boot/fe/item.ml
index c1746cc2f99..4c9bd556965 100644
--- a/src/boot/fe/item.ml
+++ b/src/boot/fe/item.ml
@@ -154,8 +154,6 @@ and parse_stmts (ps:pstate) : Ast.stmt array =
     if (Array.length arr) == 0 then
       raise (err "statement does nothing" ps);
     arr
-        
-    
 
 (*
  * We have no way to parse a single Ast.stmt; any incoming syntactic statement
@@ -605,7 +603,11 @@ and parse_stmts_including_none (ps:pstate) : Ast.stmt array =
             expect ps SEMI;
             spans ps stmts apos (Ast.STMT_join lval)
 
-      | IO | STATE | UNSAFE | MOD | OBJ | TAG | TYPE | FN | USE | NATIVE ->
+
+       | STATE | GC
+       | IMPURE | UNSAFE
+       | ABS | NATIVE
+       | MOD | OBJ | TAG | TYPE | FN | USE ->
           let items = ctxt "stmt: decl" parse_mod_item ps in
           let bpos = lexpos ps in
             Array.map
@@ -689,6 +691,8 @@ and parse_stmts_including_none (ps:pstate) : Ast.stmt array =
 
 and parse_ty_param (iref:int ref) (ps:pstate) : Ast.ty_param identified =
   let apos = lexpos ps in
+  let _ = Pexp.parse_opacity ps in
+  let _ = Pexp.parse_stratum ps in
   let e = Pexp.parse_effect ps in
   let ident = Pexp.parse_ident ps in
   let i = !iref in
@@ -851,7 +855,7 @@ and parse_obj_item
       do
         let apos = lexpos ps in
           match peek ps with
-              IO | STATE | UNSAFE | FN | ITER ->
+              IMPURE | UNSAFE | FN | ITER ->
                 let effect = Pexp.parse_effect ps in
                 let is_iter = (peek ps) = ITER in
                   bump ps;
@@ -986,7 +990,10 @@ and parse_mod_item (ps:pstate)
 
     match peek ps with
 
-        IO | STATE | UNSAFE | TYPE | OBJ | TAG | FN | ITER ->
+        STATE | GC | IMPURE | UNSAFE | ABS
+      | TYPE | OBJ | TAG | FN | ITER ->
+          let _ = Pexp.parse_opacity ps in
+          let _ = Pexp.parse_stratum ps in
           let effect = Pexp.parse_effect ps in
             begin
               match peek ps with
@@ -1044,7 +1051,7 @@ and parse_mod_item (ps:pstate)
               expect ps MOD;
               let ident = Pexp.parse_ident ps in
               let path = parse_lib_name ident in
-              let items = parse_mod_items_from_signature ps in
+              let items = parse_native_mod_items_from_signature ps in
               let bpos = lexpos ps in
               let rlib = REQUIRED_LIB_c { required_libname = path;
                                           required_prefix = ps.pstate_depth }
@@ -1056,7 +1063,7 @@ and parse_mod_item (ps:pstate)
           end
       | _ -> raise (unexpected ps)
 
-and parse_mod_items_header_from_signature (ps:pstate) : Ast.mod_view =
+and parse_native_mod_header_from_signature (ps:pstate) : Ast.mod_view =
   let exports = Hashtbl.create 0 in
     while (peek ps = EXPORT)
     do
@@ -1068,11 +1075,11 @@ and parse_mod_items_header_from_signature (ps:pstate) : Ast.mod_view =
     then htab_put exports Ast.EXPORT_all_decls ();
     {empty_view with Ast.view_exports = exports}
 
-and parse_mod_items_from_signature
+and parse_native_mod_items_from_signature
     (ps:pstate)
     : (Ast.mod_view * Ast.mod_items) =
   expect ps LBRACE;
-  let view  = parse_mod_items_header_from_signature ps in
+  let view  = parse_native_mod_header_from_signature ps in
   let items = Hashtbl.create 0 in
     while not (peek ps = RBRACE)
     do
@@ -1080,24 +1087,24 @@ and parse_mod_items_from_signature
         (fun (ident, item) ->
            htab_put items ident item)
         (ctxt "mod items from sig: mod item"
-           parse_mod_item_from_signature ps)
+           parse_native_mod_item_from_signature ps)
     done;
     expect ps RBRACE;
     (view,items)
 
-and parse_mod_item_from_signature (ps:pstate)
+and parse_native_mod_item_from_signature (ps:pstate)
     : (Ast.ident * Ast.mod_item) array =
   let apos = lexpos ps in
     match peek ps with
         MOD ->
           bump ps;
           let (ident, params) = parse_ident_and_params ps "mod signature" in
-          let items = parse_mod_items_from_signature ps in
+          let items = parse_native_mod_items_from_signature ps in
           let bpos = lexpos ps in
             [| (ident,
                 span ps apos bpos (decl params (Ast.MOD_ITEM_mod items))) |]
 
-      | IO | STATE | UNSAFE | FN | ITER ->
+      | IMPURE | UNSAFE | FN | ITER ->
           let effect = Pexp.parse_effect ps in
           let is_iter = (peek ps) = ITER in
             bump ps;
@@ -1142,7 +1149,7 @@ and parse_mod_item_from_signature (ps:pstate)
           expect ps SEMI;
           let bpos = lexpos ps in
             [| (ident, span ps apos bpos
-                  (decl params (Ast.MOD_ITEM_type (Ast.UNSAFE, t)))) |]
+                  (decl params (Ast.MOD_ITEM_type (Ast.EFF_unsafe, t)))) |]
 
     | _ -> raise (unexpected ps)
 
diff --git a/src/boot/fe/lexer.mll b/src/boot/fe/lexer.mll
index 151af827657..84aeb9ab114 100644
--- a/src/boot/fe/lexer.mll
+++ b/src/boot/fe/lexer.mll
@@ -95,8 +95,12 @@
                 ("claim", CLAIM);
                 ("prove", PROVE);
 
-                ("io", IO);
+                ("abs", ABS);
+
                 ("state", STATE);
+                ("gc", GC);
+
+                ("impure", IMPURE);
                 ("unsafe", UNSAFE);
 
                 ("native", NATIVE);
diff --git a/src/boot/fe/pexp.ml b/src/boot/fe/pexp.ml
index 85eb32c46df..59cfaf751bb 100644
--- a/src/boot/fe/pexp.ml
+++ b/src/boot/fe/pexp.ml
@@ -140,12 +140,22 @@ and parse_optional_trailing_constrs (ps:pstate) : Ast.constrs =
       COLON -> (bump ps; parse_constrs ps)
     | _ -> [| |]
 
+and parse_opacity (ps:pstate) : Ast.opacity =
+  match peek ps with
+      ABS -> bump ps; Ast.OPA_abstract
+    |  _ -> Ast.OPA_transparent
+
+and parse_stratum (ps:pstate) : Ast.stratum =
+  match peek ps with
+      STATE -> bump ps; Ast.STRAT_state
+    | GC -> bump ps; Ast.STRAT_gc
+    |  _ -> Ast.STRAT_value
+
 and parse_effect (ps:pstate) : Ast.effect =
   match peek ps with
-      IO -> bump ps; Ast.IO
-    | STATE -> bump ps; Ast.STATE
-    | UNSAFE -> bump ps; Ast.UNSAFE
-    | _ -> Ast.PURE
+      IMPURE -> bump ps; Ast.EFF_impure
+    | UNSAFE -> bump ps; Ast.EFF_unsafe
+    | _ -> Ast.EFF_pure
 
 and parse_mutability (ps:pstate) : Ast.mutability =
   match peek ps with
@@ -263,7 +273,9 @@ and parse_atomic_ty (ps:pstate) : Ast.ty =
         bump ps;
         Ast.TY_mach m
 
-    | IO | STATE | UNSAFE | OBJ | FN | ITER ->
+    | ABS | STATE | GC | IMPURE | UNSAFE | OBJ | FN | ITER ->
+        let _ = parse_opacity ps in
+        let _ = parse_stratum ps in
         let effect = parse_effect ps in
           begin
             match peek ps with
diff --git a/src/boot/fe/token.ml b/src/boot/fe/token.ml
index cd41ec2fec5..6c2282de210 100644
--- a/src/boot/fe/token.ml
+++ b/src/boot/fe/token.ml
@@ -80,9 +80,15 @@ type token =
   | CLAIM
   | PROVE
 
-  (* Effect keywords *)
-  | IO
+  (* Opacity keywords *)
+  | ABS
+
+  (* Stratum keywords *)
   | STATE
+  | GC
+
+  (* Effect keywords *)
+  | IMPURE
   | UNSAFE
 
   (* Type qualifiers *)
@@ -237,9 +243,15 @@ let rec string_of_tok t =
     | CLAIM      -> "claim"
     | PROVE      -> "prove"
 
-    (* Effect keywords *)
-    | IO         -> "io"
+    (* Opacity keywords *)
+    | ABS        -> "abs"
+
+    (* Stratum keywords *)
     | STATE      -> "state"
+    | GC         -> "gc"
+
+    (* Effect keywords *)
+    | IMPURE     -> "impure"
     | UNSAFE     -> "unsafe"
 
     (* Type qualifiers *)
diff --git a/src/boot/me/dwarf.ml b/src/boot/me/dwarf.ml
index 08f8c3478f8..86a0c8a63cb 100644
--- a/src/boot/me/dwarf.ml
+++ b/src/boot/me/dwarf.ml
@@ -1527,10 +1527,9 @@ let dwarf_visitor
     (* Note: weird encoding: mutable+pure = unsafe. *)
     let mut_byte, pure_byte =
       match eff with
-          Ast.UNSAFE -> (1,1)
-        | Ast.STATE -> (1,0)
-        | Ast.IO -> (0,0)
-        | Ast.PURE -> (0,1)
+          Ast.EFF_unsafe -> (1,1)
+        | Ast.EFF_impure -> (0,0)
+        | Ast.EFF_pure -> (0,1)
     in
       SEQ [|
         (* DW_AT_mutable: DW_FORM_flag *)
@@ -2888,10 +2887,10 @@ let rec extract_mod_items
   let get_effect die =
     match (get_flag die DW_AT_mutable, get_flag die DW_AT_pure) with
         (* Note: weird encoding: mutable+pure = unsafe. *)
-        (true, true) -> Ast.UNSAFE
-      | (true, false) -> Ast.STATE
-      | (false, false) -> Ast.IO
-      | (false, true) -> Ast.PURE
+        (true, true) -> Ast.EFF_unsafe
+      | (false, false) -> Ast.EFF_impure
+      | (false, true) -> Ast.EFF_pure
+      | _ -> failwith "bad effect encoding"
   in
 
   let get_name die = get_str die DW_AT_name in
diff --git a/src/boot/me/effect.ml b/src/boot/me/effect.ml
index 8a8292d9cb8..3bb761efed1 100644
--- a/src/boot/me/effect.ml
+++ b/src/boot/me/effect.ml
@@ -92,7 +92,7 @@ let function_effect_propagation_visitor
    * This visitor calculates the effect of each function according to
    * its statements:
    * 
-   *    - Communication lowers to 'io'
+   *    - Communication statements lower to 'impure'
    *    - Native calls lower to 'unsafe'
    *    - Calling a function with effect e lowers to e.
    *)
@@ -138,7 +138,7 @@ let function_effect_propagation_visitor
     let fn_id = Stack.top curr_fn in
     let e =
       match htab_search item_effect fn_id with
-          None -> Ast.PURE
+          None -> Ast.EFF_pure
         | Some e -> e
     in
     let ne = lower_effect_of ne e in
@@ -163,7 +163,7 @@ let function_effect_propagation_visitor
     begin
       match s.node with
           Ast.STMT_send _
-        | Ast.STMT_recv _ -> lower_to s Ast.IO
+        | Ast.STMT_recv _ -> lower_to s Ast.EFF_impure
 
         | Ast.STMT_call (_, fn, _) ->
             let lower_to_callee_ty t =
@@ -183,7 +183,7 @@ let function_effect_propagation_visitor
                     match htab_search cx.ctxt_required_items item.id with
                         None -> ()
                       | Some (REQUIRED_LIB_rust _, _) -> ()
-                      | Some _ -> lower_to s Ast.UNSAFE
+                      | Some _ -> lower_to s Ast.EFF_unsafe
                 end
         | _ -> ()
     end;
@@ -232,7 +232,7 @@ let effect_checking_visitor
         | Some e ->
             let curr =
               if Stack.is_empty auth_stack
-              then Ast.PURE
+              then Ast.EFF_pure
               else Stack.top auth_stack
             in
             let next = lower_effect_of e curr in
@@ -253,7 +253,7 @@ let effect_checking_visitor
           Ast.MOD_ITEM_fn f ->
             let e =
               match htab_search item_effect i.id with
-                None -> Ast.PURE
+                None -> Ast.EFF_pure
               | Some e -> e
             in
             let fe = f.Ast.fn_aux.Ast.fn_effect in
@@ -291,7 +291,7 @@ let effect_checking_visitor
           let curr = Stack.pop auth_stack in
           let next =
             if Stack.is_empty auth_stack
-            then Ast.PURE
+            then Ast.EFF_pure
             else Stack.top auth_stack
           in
           iflog cx
diff --git a/src/boot/me/semant.ml b/src/boot/me/semant.ml
index 1eb88ab1678..1b65c0dbdac 100644
--- a/src/boot/me/semant.ml
+++ b/src/boot/me/semant.ml
@@ -191,7 +191,7 @@ type ctxt =
 
       ctxt_rty_cache: (Ast.ty,Il.referent_ty) Hashtbl.t;
 
-      ctxt_type_effect_cache: (Ast.ty,Ast.effect) Hashtbl.t;
+      ctxt_type_stratum_cache: (Ast.ty,Ast.stratum) Hashtbl.t;
       ctxt_type_points_to_heap_cache: (Ast.ty,bool) Hashtbl.t;
       ctxt_type_is_structured_cache: (Ast.ty,bool) Hashtbl.t;
       ctxt_type_contains_chan_cache: (Ast.ty,bool) Hashtbl.t;
@@ -296,7 +296,7 @@ let new_ctxt sess abi crate =
     ctxt_curr_path = Stack.create ();
 
     ctxt_rty_cache = Hashtbl.create 0;
-    ctxt_type_effect_cache = Hashtbl.create 0;
+    ctxt_type_stratum_cache = Hashtbl.create 0;
     ctxt_type_points_to_heap_cache = Hashtbl.create 0;
     ctxt_type_is_structured_cache = Hashtbl.create 0;
     ctxt_type_contains_chan_cache = Hashtbl.create 0;
@@ -1227,16 +1227,15 @@ let type_points_to_heap (cx:ctxt) (t:Ast.ty) : bool =
       (fun _ -> fold_ty cx fold t)
 ;;
 
-(* Effect analysis. *)
+
+(* Type qualifier analysis. *)
+
 let effect_le x y =
   match (x,y) with
-      (Ast.UNSAFE, _) -> true
-    | (Ast.STATE, Ast.PURE) -> true
-    | (Ast.STATE, Ast.IO) -> true
-    | (Ast.STATE, Ast.STATE) -> true
-    | (Ast.IO, Ast.PURE) -> true
-    | (Ast.IO, Ast.IO) -> true
-    | (Ast.PURE, Ast.PURE) -> true
+      (Ast.EFF_unsafe, _) -> true
+    | (Ast.EFF_impure, Ast.EFF_pure) -> true
+    | (Ast.EFF_impure, Ast.EFF_impure) -> true
+    | (Ast.EFF_pure, Ast.EFF_pure) -> true
     | _ -> false
 ;;
 
@@ -1244,16 +1243,30 @@ let lower_effect_of x y =
   if effect_le x y then x else y
 ;;
 
-let type_effect (cx:ctxt) (t:Ast.ty) : Ast.effect =
-  let fold_mutable _ = Ast.STATE in
-  let fold = associative_binary_op_ty_fold Ast.PURE lower_effect_of in
+let stratum_le x y =
+  match (x,y) with
+      (Ast.STRAT_gc, _) -> true
+    | (Ast.STRAT_state, Ast.STRAT_value) -> true
+    | (Ast.STRAT_state, Ast.STRAT_state) -> true
+    | (Ast.STRAT_value, Ast.STRAT_value) -> true
+    | _ -> false
+;;
+
+let lower_stratum_of x y =
+  if stratum_le x y then x else y
+;;
+
+let type_stratum (cx:ctxt) (t:Ast.ty) : Ast.stratum =
+  let fold_mutable _ = Ast.STRAT_state in
+  let fold = associative_binary_op_ty_fold Ast.STRAT_value lower_stratum_of in
   let fold = { fold with ty_fold_mutable = fold_mutable } in
-    htab_search_or_add cx.ctxt_type_effect_cache t
+    htab_search_or_add cx.ctxt_type_stratum_cache t
       (fun _ -> fold_ty cx fold t)
 ;;
 
+
 let type_has_state (cx:ctxt) (t:Ast.ty) : bool =
-  effect_le (type_effect cx t) Ast.STATE
+  stratum_le (type_stratum cx t) Ast.STRAT_state
 ;;
 
 
@@ -1627,7 +1640,7 @@ let ty_of_mod_item (item:Ast.mod_item) : Ast.ty =
     | Ast.MOD_ITEM_mod _ -> bug () "Semant.ty_of_mod_item on mod"
     | Ast.MOD_ITEM_const (ty, _) -> ty
     | Ast.MOD_ITEM_obj ob ->
-        let taux = { Ast.fn_effect = Ast.PURE;
+        let taux = { Ast.fn_effect = Ast.EFF_pure;
                      Ast.fn_is_iter = false }
         in
         let tobj = Ast.TY_obj (ty_obj_of_obj ob) in
@@ -1650,7 +1663,7 @@ let ty_of_mod_item (item:Ast.mod_item) : Ast.ty =
           if Array.length hdr = 0
           then Ast.TY_tag ttag
           else
-            let taux = { Ast.fn_effect = Ast.PURE;
+            let taux = { Ast.fn_effect = Ast.EFF_pure;
                          Ast.fn_is_iter = false }
             in
             let inputs = Array.map (fun (s, _) -> s.node) hdr in
@@ -2561,7 +2574,7 @@ let mk_ty_fn_or_iter
     (is_iter:bool)
     : Ast.ty =
   (* In some cases we don't care what aux or constrs are. *)
-  let taux = { Ast.fn_effect = Ast.PURE;
+  let taux = { Ast.fn_effect = Ast.EFF_pure;
                Ast.fn_is_iter = is_iter; }
   in
   let tsig = { Ast.sig_input_slots = arg_slots;
diff --git a/src/boot/me/typestate.ml b/src/boot/me/typestate.ml
index 00629886ebc..0579775f7de 100644
--- a/src/boot/me/typestate.ml
+++ b/src/boot/me/typestate.ml
@@ -126,7 +126,7 @@ let determine_constr_key
               match Hashtbl.find cx.ctxt_all_item_types cid with
                   Ast.TY_fn (_, taux) ->
                     begin
-                      if taux.Ast.fn_effect = Ast.PURE
+                      if taux.Ast.fn_effect = Ast.EFF_pure
                       then cid
                       else err (Some cid) "impure function used in constraint"
                     end
@@ -989,6 +989,7 @@ let graph_special_block_structure_building_visitor
                         Hashtbl.replace graph cond_id [then_id; else_id];
                         Hashtbl.replace graph then_end_id succ;
                         Hashtbl.replace graph else_end_id succ;
+
                         (* Kill residual messed-up block wiring.*)
                         remove_flow_edges graph then_end_id [then_id];
                         remove_flow_edges graph else_id [then_id];
diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs
index 67c26f9b07d..920b47d23c8 100644
--- a/src/comp/driver/rustc.rs
+++ b/src/comp/driver/rustc.rs
@@ -11,7 +11,7 @@ import std.util.none;
 import std._str;
 import std._vec;
 
-io fn compile_input(session.session sess, str input, str output) {
+impure fn compile_input(session.session sess, str input, str output) {
           auto p = parser.new_parser(sess, 0, input);
           auto crate = parser.parse_crate(p);
           crate = resolve.resolve_crate(sess, crate);
@@ -36,7 +36,7 @@ fn usage(session.session sess, str argv0) {
     log "";
 }
 
-io fn main(vec[str] args) {
+impure fn main(vec[str] args) {
 
   auto sess = session.session();
   let option[str] input_file = none[str];
diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs
index 9ff12f1c086..fbeee8cbcfe 100644
--- a/src/comp/front/lexer.rs
+++ b/src/comp/front/lexer.rs
@@ -9,7 +9,7 @@ state type reader = state obj {
                           fn is_eof() -> bool;
                           fn curr() -> char;
                           fn next() -> char;
-                          io fn bump();
+                          impure fn bump();
                           fn mark();
                           fn get_filename() -> str;
                           fn get_mark_pos() -> common.pos;
@@ -55,7 +55,7 @@ fn new_reader(stdio_reader rdr, str filename) -> reader
                 ret n;
             }
 
-            io fn bump() {
+            impure fn bump() {
                 c = n;
 
                 if (c == (-1) as char) {
@@ -247,14 +247,14 @@ fn is_whitespace(char c) -> bool {
     ret c == ' ' || c == '\t' || c == '\r' || c == '\n';
 }
 
-io fn consume_any_whitespace(reader rdr) {
+impure fn consume_any_whitespace(reader rdr) {
     while (is_whitespace(rdr.curr())) {
         rdr.bump();
     }
     be consume_any_line_comment(rdr);
 }
 
-io fn consume_any_line_comment(reader rdr) {
+impure fn consume_any_line_comment(reader rdr) {
     if (rdr.curr() == '/') {
         alt (rdr.next()) {
             case ('/') {
@@ -277,7 +277,7 @@ io fn consume_any_line_comment(reader rdr) {
 }
 
 
-io fn consume_block_comment(reader rdr) {
+impure fn consume_block_comment(reader rdr) {
     let int level = 1;
     while (level > 0) {
         if (rdr.curr() == '/' && rdr.next() == '*') {
@@ -298,7 +298,7 @@ io fn consume_block_comment(reader rdr) {
     be consume_any_whitespace(rdr);
 }
 
-io fn next_token(reader rdr) -> token.token {
+impure fn next_token(reader rdr) -> token.token {
     auto accum_str = "";
     auto accum_int = 0;
 
@@ -359,7 +359,7 @@ io fn next_token(reader rdr) -> token.token {
         ret token.LIT_INT(accum_int);
     }
 
-    io fn binop(reader rdr, token.binop op) -> token.token {
+    impure fn binop(reader rdr, token.binop op) -> token.token {
         rdr.bump();
         if (rdr.next() == '=') {
             rdr.bump();
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index ceb686094c6..fd3bd1c05bd 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -13,14 +13,14 @@ import util.common.new_str_hash;
 state type parser =
     state obj {
           fn peek() -> token.token;
-          io fn bump();
-          io fn err(str s);
+          impure fn bump();
+          impure fn err(str s);
           fn get_session() -> session.session;
           fn get_span() -> common.span;
           fn next_def_id() -> ast.def_id;
     };
 
-io fn new_parser(session.session sess,
+impure fn new_parser(session.session sess,
                  ast.crate_num crate, str path) -> parser {
     state obj stdio_parser(session.session sess,
                            mutable token.token tok,
@@ -35,13 +35,13 @@ io fn new_parser(session.session sess,
                 ret tok;
             }
 
-            io fn bump() {
+            impure fn bump() {
                 tok = lexer.next_token(rdr);
                 lo = rdr.get_mark_pos();
                 hi = rdr.get_curr_pos();
             }
 
-            io fn err(str m) {
+            impure fn err(str m) {
                 auto span = rec(filename = rdr.get_filename(),
                                 lo = lo, hi = hi);
                 sess.span_err(span, m);
@@ -68,7 +68,7 @@ io fn new_parser(session.session sess,
                      npos, npos, 0, crate, rdr);
 }
 
-io fn expect(parser p, token.token t) {
+impure fn expect(parser p, token.token t) {
     if (p.peek() == t) {
         p.bump();
     } else {
@@ -86,7 +86,7 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
                                 hi=hi.hi));
 }
 
-io fn parse_ident(parser p) -> ast.ident {
+impure fn parse_ident(parser p) -> ast.ident {
     alt (p.peek()) {
         case (token.IDENT(?i)) { p.bump(); ret i; }
         case (_) {
@@ -96,7 +96,7 @@ io fn parse_ident(parser p) -> ast.ident {
     }
 }
 
-io fn parse_possibly_mutable_ty(parser p) -> tup(bool, @ast.ty) {
+impure fn parse_possibly_mutable_ty(parser p) -> tup(bool, @ast.ty) {
     auto mut;
     if (p.peek() == token.MUTABLE) {
         p.bump();
@@ -108,7 +108,7 @@ io fn parse_possibly_mutable_ty(parser p) -> tup(bool, @ast.ty) {
     ret tup(mut, parse_ty(p));
 }
 
-io fn parse_ty(parser p) -> @ast.ty {
+impure fn parse_ty(parser p) -> @ast.ty {
     auto lo = p.get_span();
     let ast.ty_ t;
     alt (p.peek()) {
@@ -144,7 +144,7 @@ io fn parse_ty(parser p) -> @ast.ty {
     ret @spanned(lo, lo, t);
 }
 
-io fn parse_arg(parser p) -> ast.arg {
+impure fn parse_arg(parser p) -> ast.arg {
     let ast.mode m = ast.val;
     if (p.peek() == token.BINOP(token.AND)) {
         m = ast.alias;
@@ -155,10 +155,10 @@ io fn parse_arg(parser p) -> ast.arg {
     ret rec(mode=m, ty=t, ident=i, id=p.next_def_id());
 }
 
-io fn parse_seq[T](token.token bra,
+impure fn parse_seq[T](token.token bra,
                       token.token ket,
                       option[token.token] sep,
-                      (io fn(parser) -> T) f,
+                      (impure fn(parser) -> T) f,
                       parser p) -> util.common.spanned[vec[T]] {
     let bool first = true;
     auto lo = p.get_span();
@@ -185,7 +185,7 @@ io fn parse_seq[T](token.token bra,
     ret spanned(lo, hi, v);
 }
 
-io fn parse_lit(parser p) -> option[ast.lit] {
+impure fn parse_lit(parser p) -> option[ast.lit] {
     auto lo = p.get_span();
     let ast.lit_ lit;
     alt (p.peek()) {
@@ -217,7 +217,7 @@ io fn parse_lit(parser p) -> option[ast.lit] {
     ret some(spanned(lo, lo, lit));
 }
 
-io fn parse_name(parser p, ast.ident id) -> ast.name {
+impure fn parse_name(parser p, ast.ident id) -> ast.name {
 
     auto lo = p.get_span();
 
@@ -240,7 +240,7 @@ io fn parse_name(parser p, ast.ident id) -> ast.name {
     ret spanned(lo, tys.span, rec(ident=id, types=tys.node));
 }
 
-io fn parse_possibly_mutable_expr(parser p) -> tup(bool, @ast.expr) {
+impure fn parse_possibly_mutable_expr(parser p) -> tup(bool, @ast.expr) {
     auto mut;
     if (p.peek() == token.MUTABLE) {
         p.bump();
@@ -252,7 +252,7 @@ io fn parse_possibly_mutable_expr(parser p) -> tup(bool, @ast.expr) {
     ret tup(mut, parse_expr(p));
 }
 
-io fn parse_bottom_expr(parser p) -> @ast.expr {
+impure fn parse_bottom_expr(parser p) -> @ast.expr {
 
     auto lo = p.get_span();
     auto hi = lo;
@@ -315,7 +315,7 @@ io fn parse_bottom_expr(parser p) -> @ast.expr {
 
         case (token.REC) {
             p.bump();
-            io fn parse_entry(parser p) ->
+            impure fn parse_entry(parser p) ->
                 tup(ast.ident, @ast.expr) {
                 auto i = parse_ident(p);
                 expect(p, token.EQ);
@@ -348,7 +348,7 @@ io fn parse_bottom_expr(parser p) -> @ast.expr {
     ret @spanned(lo, hi, ex);
 }
 
-io fn parse_path_expr(parser p) -> @ast.expr {
+impure fn parse_path_expr(parser p) -> @ast.expr {
     auto lo = p.get_span();
     auto e = parse_bottom_expr(p);
     auto hi = e.span;
@@ -381,7 +381,7 @@ io fn parse_path_expr(parser p) -> @ast.expr {
     ret e;
 }
 
-io fn parse_prefix_expr(parser p) -> @ast.expr {
+impure fn parse_prefix_expr(parser p) -> @ast.expr {
 
     auto lo = p.get_span();
     auto hi = lo;
@@ -443,8 +443,8 @@ io fn parse_prefix_expr(parser p) -> @ast.expr {
     ret @spanned(lo, hi, ex);
 }
 
-io fn parse_binops(parser p,
-                   (io fn(parser) -> @ast.expr) sub,
+impure fn parse_binops(parser p,
+                   (impure fn(parser) -> @ast.expr) sub,
                    vec[tup(token.binop, ast.binop)] ops)
     -> @ast.expr {
     auto lo = p.get_span();
@@ -472,8 +472,8 @@ io fn parse_binops(parser p,
     ret e;
 }
 
-io fn parse_binary_exprs(parser p,
-                            (io fn(parser) -> @ast.expr) sub,
+impure fn parse_binary_exprs(parser p,
+                            (impure fn(parser) -> @ast.expr) sub,
                             vec[tup(token.token, ast.binop)] ops)
     -> @ast.expr {
     auto lo = p.get_span();
@@ -496,42 +496,42 @@ io fn parse_binary_exprs(parser p,
     ret e;
 }
 
-io fn parse_factor_expr(parser p) -> @ast.expr {
+impure fn parse_factor_expr(parser p) -> @ast.expr {
     auto sub = parse_prefix_expr;
     ret parse_binops(p, sub, vec(tup(token.STAR, ast.mul),
                                  tup(token.SLASH, ast.div),
                                  tup(token.PERCENT, ast.rem)));
 }
 
-io fn parse_term_expr(parser p) -> @ast.expr {
+impure fn parse_term_expr(parser p) -> @ast.expr {
     auto sub = parse_factor_expr;
     ret parse_binops(p, sub, vec(tup(token.PLUS, ast.add),
                                  tup(token.MINUS, ast.sub)));
 }
 
-io fn parse_shift_expr(parser p) -> @ast.expr {
+impure fn parse_shift_expr(parser p) -> @ast.expr {
     auto sub = parse_term_expr;
     ret parse_binops(p, sub, vec(tup(token.LSL, ast.lsl),
                                  tup(token.LSR, ast.lsr),
                                  tup(token.ASR, ast.asr)));
 }
 
-io fn parse_bitand_expr(parser p) -> @ast.expr {
+impure fn parse_bitand_expr(parser p) -> @ast.expr {
     auto sub = parse_shift_expr;
     ret parse_binops(p, sub, vec(tup(token.AND, ast.bitand)));
 }
 
-io fn parse_bitxor_expr(parser p) -> @ast.expr {
+impure fn parse_bitxor_expr(parser p) -> @ast.expr {
     auto sub = parse_bitand_expr;
     ret parse_binops(p, sub, vec(tup(token.CARET, ast.bitxor)));
 }
 
-io fn parse_bitor_expr(parser p) -> @ast.expr {
+impure fn parse_bitor_expr(parser p) -> @ast.expr {
     auto sub = parse_bitxor_expr;
     ret parse_binops(p, sub, vec(tup(token.OR, ast.bitor)));
 }
 
-io fn parse_cast_expr(parser p) -> @ast.expr {
+impure fn parse_cast_expr(parser p) -> @ast.expr {
     auto lo = p.get_span();
     auto e = parse_bitor_expr(p);
     auto hi = e.span;
@@ -552,7 +552,7 @@ io fn parse_cast_expr(parser p) -> @ast.expr {
     ret e;
 }
 
-io fn parse_relational_expr(parser p) -> @ast.expr {
+impure fn parse_relational_expr(parser p) -> @ast.expr {
     auto sub = parse_cast_expr;
     ret parse_binary_exprs(p, sub, vec(tup(token.LT, ast.lt),
                                        tup(token.LE, ast.le),
@@ -561,23 +561,23 @@ io fn parse_relational_expr(parser p) -> @ast.expr {
 }
 
 
-io fn parse_equality_expr(parser p) -> @ast.expr {
+impure fn parse_equality_expr(parser p) -> @ast.expr {
     auto sub = parse_relational_expr;
     ret parse_binary_exprs(p, sub, vec(tup(token.EQEQ, ast.eq),
                                        tup(token.NE, ast.ne)));
 }
 
-io fn parse_and_expr(parser p) -> @ast.expr {
+impure fn parse_and_expr(parser p) -> @ast.expr {
     auto sub = parse_equality_expr;
     ret parse_binary_exprs(p, sub, vec(tup(token.ANDAND, ast.and)));
 }
 
-io fn parse_or_expr(parser p) -> @ast.expr {
+impure fn parse_or_expr(parser p) -> @ast.expr {
     auto sub = parse_and_expr;
     ret parse_binary_exprs(p, sub, vec(tup(token.OROR, ast.or)));
 }
 
-io fn parse_assign_expr(parser p) -> @ast.expr {
+impure fn parse_assign_expr(parser p) -> @ast.expr {
     auto lo = p.get_span();
     auto lhs = parse_or_expr(p);
     alt (p.peek()) {
@@ -591,7 +591,7 @@ io fn parse_assign_expr(parser p) -> @ast.expr {
     ret lhs;
 }
 
-io fn parse_if_expr(parser p) -> @ast.expr {
+impure fn parse_if_expr(parser p) -> @ast.expr {
     auto lo = p.get_span();
     auto hi = lo;
 
@@ -613,7 +613,7 @@ io fn parse_if_expr(parser p) -> @ast.expr {
     ret @spanned(lo, hi, ast.expr_if(cond, thn, els, none[@ast.ty]));
 }
 
-io fn parse_expr(parser p) -> @ast.expr {
+impure fn parse_expr(parser p) -> @ast.expr {
     alt (p.peek()) {
         case (token.LBRACE) {
             auto blk = parse_block(p);
@@ -630,7 +630,7 @@ io fn parse_expr(parser p) -> @ast.expr {
     }
 }
 
-io fn parse_initializer(parser p) -> option[@ast.expr] {
+impure fn parse_initializer(parser p) -> option[@ast.expr] {
     if (p.peek() == token.EQ) {
         p.bump();
         ret some(parse_expr(p));
@@ -639,7 +639,7 @@ io fn parse_initializer(parser p) -> option[@ast.expr] {
     ret none[@ast.expr];
 }
 
-io fn parse_let(parser p) -> @ast.decl {
+impure fn parse_let(parser p) -> @ast.decl {
     auto lo = p.get_span();
 
     expect(p, token.LET);
@@ -659,7 +659,7 @@ io fn parse_let(parser p) -> @ast.decl {
     ret @spanned(lo, hi, ast.decl_local(@local));
 }
 
-io fn parse_auto(parser p) -> @ast.decl {
+impure fn parse_auto(parser p) -> @ast.decl {
     auto lo = p.get_span();
 
     expect(p, token.AUTO);
@@ -678,7 +678,7 @@ io fn parse_auto(parser p) -> @ast.decl {
     ret @spanned(lo, hi, ast.decl_local(@local));
 }
 
-io fn parse_stmt(parser p) -> @ast.stmt {
+impure fn parse_stmt(parser p) -> @ast.stmt {
     auto lo = p.get_span();
     alt (p.peek()) {
 
@@ -760,7 +760,7 @@ io fn parse_stmt(parser p) -> @ast.stmt {
     fail;
 }
 
-io fn parse_block(parser p) -> ast.block {
+impure fn parse_block(parser p) -> ast.block {
     auto f = parse_stmt;
     // FIXME: passing parse_stmt as an lval doesn't work at the moment.
     auto stmts = parse_seq[@ast.stmt](token.LBRACE,
@@ -800,7 +800,7 @@ io fn parse_block(parser p) -> ast.block {
     ret spanned(stmts.span, stmts.span, b);
 }
 
-io fn parse_fn(parser p) -> tup(ast.ident, @ast.item) {
+impure fn parse_fn(parser p) -> tup(ast.ident, @ast.item) {
     auto lo = p.get_span();
     expect(p, token.FN);
     auto id = parse_ident(p);
@@ -832,7 +832,7 @@ io fn parse_fn(parser p) -> tup(ast.ident, @ast.item) {
     ret tup(id, @spanned(lo, body.span, item));
 }
 
-io fn parse_mod_items(parser p, token.token term) -> ast._mod {
+impure fn parse_mod_items(parser p, token.token term) -> ast._mod {
    let vec[@ast.item] items = vec();
     let hashmap[ast.ident,uint] index = new_str_hash[uint]();
     let uint u = 0u;
@@ -845,7 +845,7 @@ io fn parse_mod_items(parser p, token.token term) -> ast._mod {
     ret rec(items=items, index=index);
  }
 
-io fn parse_mod(parser p) -> tup(ast.ident, @ast.item) {
+impure fn parse_mod(parser p) -> tup(ast.ident, @ast.item) {
     auto lo = p.get_span();
     expect(p, token.MOD);
     auto id = parse_ident(p);
@@ -857,7 +857,7 @@ io fn parse_mod(parser p) -> tup(ast.ident, @ast.item) {
     ret tup(id, @spanned(lo, hi, item));
 }
 
-io fn parse_item(parser p) -> tup(ast.ident, @ast.item) {
+impure fn parse_item(parser p) -> tup(ast.ident, @ast.item) {
     alt (p.peek()) {
         case (token.FN) {
             ret parse_fn(p);
@@ -870,7 +870,7 @@ io fn parse_item(parser p) -> tup(ast.ident, @ast.item) {
     fail;
 }
 
-io fn parse_crate(parser p) -> @ast.crate {
+impure fn parse_crate(parser p) -> @ast.crate {
     auto lo = p.get_span();
     auto hi = lo;
     auto m = parse_mod_items(p, token.EOF);
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index cce0d38fc37..f9f3b0a63a6 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -30,7 +30,7 @@ mod util {
     mod common;
 }
 
-auth driver.rustc.main = state;
+auth driver.rustc.main = impure;
 auth middle.trans = unsafe;
 auth lib.llvm = unsafe;
 
diff --git a/src/lib/map.rs b/src/lib/map.rs
index 0b89769731f..4d7a6c03775 100644
--- a/src/lib/map.rs
+++ b/src/lib/map.rs
@@ -12,7 +12,7 @@ import std._vec;
 type hashfn[K] = fn(&K) -> uint;
 type eqfn[K] = fn(&K, &K) -> bool;
 
-state type hashmap[K, V] = state obj {
+abs state type hashmap[K, V] = state obj {
                                  fn size() -> uint;
                                  fn insert(&K key, &V val) -> bool;
                                  fn contains_key(&K key) -> bool;
diff --git a/src/lib/sys.rs b/src/lib/sys.rs
index 90e5cc49ff2..77eab003573 100644
--- a/src/lib/sys.rs
+++ b/src/lib/sys.rs
@@ -10,13 +10,13 @@ native "rust" mod rustrt {
     export size_of;
     export align_of;
     export refcount;
-    export gc;
+    export do_gc;
 
     fn last_os_error() -> str;
     fn size_of[T]() -> uint;
     fn align_of[T]() -> uint;
     fn refcount[T](@T t) -> uint;
-    fn gc();
+    fn do_gc();
     fn unsupervise();
 }
 
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 3a89cd5c445..d221e6e587b 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -69,7 +69,7 @@ refcount(rust_task *task, type_desc *t, size_t *v) {
 }
 
 extern "C" CDECL void
-gc(rust_task *task) {
+do_gc(rust_task *task) {
     task->gc(1);
 }
 
diff --git a/src/test/compile-fail/comm-makes-io.rs b/src/test/compile-fail/comm-makes-io.rs
index 50f87d0cacb..57a8e6e86f6 100644
--- a/src/test/compile-fail/comm-makes-io.rs
+++ b/src/test/compile-fail/comm-makes-io.rs
@@ -1,4 +1,4 @@
-// error-pattern: calculated effect is 'io'
+// error-pattern: calculated effect is 'impure'
 
 fn main() {
   let chan[int] c = chan();
diff --git a/src/test/compile-fail/impure-pred.rs b/src/test/compile-fail/impure-pred.rs
index 82d4cf6fa3c..c322850b6dd 100644
--- a/src/test/compile-fail/impure-pred.rs
+++ b/src/test/compile-fail/impure-pred.rs
@@ -5,7 +5,7 @@
 fn f(int a, int b) : lt(a,b) {
 }
 
-io fn lt(int a, int b) -> bool {
+impure fn lt(int a, int b) -> bool {
   let port[int] p = port();
   let chan[int] c = chan(p);
   c <| 10;
diff --git a/src/test/compile-fail/io-infects-caller.rs b/src/test/compile-fail/io-infects-caller.rs
index 2f5f003fae2..b07f46e6d20 100644
--- a/src/test/compile-fail/io-infects-caller.rs
+++ b/src/test/compile-fail/io-infects-caller.rs
@@ -1,6 +1,6 @@
-// error-pattern: calculated effect is 'io'
+// error-pattern: calculated effect is 'impure'
 
-io fn foo() {
+impure fn foo() {
   let chan[int] c = chan();
   c <| 10;
 }
diff --git a/src/test/compile-fail/unnecessary-io.rs b/src/test/compile-fail/unnecessary-io.rs
index 45a93798fed..fb50a54ccbf 100644
--- a/src/test/compile-fail/unnecessary-io.rs
+++ b/src/test/compile-fail/unnecessary-io.rs
@@ -1,4 +1,4 @@
 // error-pattern: calculated effect is ''
-io fn main() {
+impure fn main() {
   log "hi";
 }
\ No newline at end of file
diff --git a/src/test/run-fail/linked-failure.rs b/src/test/run-fail/linked-failure.rs
index 419fa0f3fd4..4990f33cf87 100644
--- a/src/test/run-fail/linked-failure.rs
+++ b/src/test/run-fail/linked-failure.rs
@@ -6,7 +6,7 @@ fn child() {
   check (1 == 2);
 }
 
-io fn main() {
+impure fn main() {
   let port[int] p = port();
   spawn child();
   let int x;
diff --git a/src/test/run-pass/acyclic-unwind.rs b/src/test/run-pass/acyclic-unwind.rs
index 38de90826a5..27cffad46d4 100644
--- a/src/test/run-pass/acyclic-unwind.rs
+++ b/src/test/run-pass/acyclic-unwind.rs
@@ -1,6 +1,6 @@
 // -*- rust -*-
 
-io fn f(chan[int] c)
+impure fn f(chan[int] c)
 {
   type t = tup(int,int,int);
 
@@ -23,7 +23,7 @@ io fn f(chan[int] c)
 }
 
 
-io fn main() {
+impure fn main() {
   let port[int] p = port();
   spawn f(chan(p));
   let int i;
diff --git a/src/test/run-pass/basic-1.rs b/src/test/run-pass/basic-1.rs
index bdd7ee25641..f61bf895112 100644
--- a/src/test/run-pass/basic-1.rs
+++ b/src/test/run-pass/basic-1.rs
@@ -1,10 +1,10 @@
 // -*- rust -*-
 
-io fn a(chan[int] c) {
+impure fn a(chan[int] c) {
     c <| 10;
 }
 
-io fn main() {
+impure fn main() {
     let port[int] p = port();
     spawn a(chan(p));
     spawn b(chan(p));
@@ -14,7 +14,7 @@ io fn main() {
 //    log "Finished.";
 }
 
-io fn b(chan[int] c) {
+impure fn b(chan[int] c) {
 //    log "task b0";
 //    log "task b1";
 //    log "task b2";
diff --git a/src/test/run-pass/basic-2.rs b/src/test/run-pass/basic-2.rs
index 975a0d4b896..d2b2e240f8d 100644
--- a/src/test/run-pass/basic-2.rs
+++ b/src/test/run-pass/basic-2.rs
@@ -1,12 +1,12 @@
 // -*- rust -*-
 
-io fn a(chan[int] c) {
+impure fn a(chan[int] c) {
     log "task a0";
     log "task a1";
     c <| 10;
 }
 
-io fn main() {
+impure fn main() {
     let port[int] p = port();
     spawn a(chan(p));
     spawn b(chan(p));
@@ -16,7 +16,7 @@ io fn main() {
     log "Finished.";
 }
 
-io fn b(chan[int] c) {
+impure fn b(chan[int] c) {
     log "task b0";
     log "task b1";
     log "task b2";
diff --git a/src/test/run-pass/basic.rs b/src/test/run-pass/basic.rs
index 95e4bff89e4..a92247c9832 100644
--- a/src/test/run-pass/basic.rs
+++ b/src/test/run-pass/basic.rs
@@ -1,6 +1,6 @@
 // -*- rust -*-
 
-io fn a(chan[int] c) {
+impure fn a(chan[int] c) {
   if (true) {
     log "task a";
     log "task a";
@@ -22,7 +22,7 @@ fn g(int x, str y) -> int {
   ret z;
 }
 
-io fn main() {
+impure fn main() {
     let int n = 2 + 3 * 7;
     let str s = "hello there";
     let port[int] p = port();
@@ -37,7 +37,7 @@ io fn main() {
     log "children finished, root finishing";
 }
 
-io fn b(chan[int] c) {
+impure fn b(chan[int] c) {
   if (true) {
     log "task b";
     log "task b";
diff --git a/src/test/run-pass/comm.rs b/src/test/run-pass/comm.rs
index 129b3bdc18e..a6610d57ff0 100644
--- a/src/test/run-pass/comm.rs
+++ b/src/test/run-pass/comm.rs
@@ -1,6 +1,6 @@
 // -*- rust -*-
 
-io fn main() {
+impure fn main() {
   let port[int] p = port();
   spawn child(chan(p));
   let int y;
@@ -10,7 +10,7 @@ io fn main() {
   check (y == 10);
 }
 
-io fn child(chan[int] c) {
+impure fn child(chan[int] c) {
   c <| 10;
 }
 
diff --git a/src/test/run-pass/lazychan.rs b/src/test/run-pass/lazychan.rs
index 9d560bd916a..b5bf8872712 100644
--- a/src/test/run-pass/lazychan.rs
+++ b/src/test/run-pass/lazychan.rs
@@ -1,6 +1,6 @@
 // -*- rust -*-
 
-io fn main() {
+impure fn main() {
   let port[int] p = port();
   auto c = chan(p);
   let int y;
@@ -18,6 +18,6 @@ io fn main() {
   check (y == 10);
 }
 
-io fn child(chan[int] c) {
+impure fn child(chan[int] c) {
   c <| 10;
 }
diff --git a/src/test/run-pass/lib-map.rs b/src/test/run-pass/lib-map.rs
index 3b46f355e1a..0ae8cc6b387 100644
--- a/src/test/run-pass/lib-map.rs
+++ b/src/test/run-pass/lib-map.rs
@@ -347,5 +347,5 @@ fn main() {
   test_growth();
   test_removal();
 
-  std.sys.rustrt.gc();
+  std.sys.rustrt.do_gc();
 }
diff --git a/src/test/run-pass/obj-dtor.rs b/src/test/run-pass/obj-dtor.rs
index 8b79047b16d..d1f54f8fa6c 100644
--- a/src/test/run-pass/obj-dtor.rs
+++ b/src/test/run-pass/obj-dtor.rs
@@ -5,7 +5,7 @@ obj worker(chan[int] c) {
   }
 }
 
-io fn do_work(chan[int] c) {
+impure fn do_work(chan[int] c) {
   log "in child task";
   {
     let worker w = worker(c);
@@ -20,7 +20,7 @@ io fn do_work(chan[int] c) {
   }
 }
 
-io fn main() {
+impure fn main() {
   let port[int] p = port();
   log "spawning worker";
   auto w = spawn do_work(chan(p));
diff --git a/src/test/run-pass/preempt.rs b/src/test/run-pass/preempt.rs
index ee37bcf44bf..06787097189 100644
--- a/src/test/run-pass/preempt.rs
+++ b/src/test/run-pass/preempt.rs
@@ -1,6 +1,6 @@
 // This checks that preemption works.
 
-io fn starve_main(chan[int] alive) {
+impure fn starve_main(chan[int] alive) {
   log "signalling main";
   alive <| 1;
   log "starving main";
@@ -10,7 +10,7 @@ io fn starve_main(chan[int] alive) {
   }
 }
 
-io fn main() {
+impure fn main() {
   let port[int] alive = port();
   log "main started";
   let task s = spawn starve_main(chan(alive));
diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs
index 28294422b5c..085f958e018 100644
--- a/src/test/run-pass/task-comm-0.rs
+++ b/src/test/run-pass/task-comm-0.rs
@@ -1,14 +1,14 @@
-io fn main() -> () {
+impure fn main() -> () {
     test05();
 }
 
-io fn test05_start(chan[int] ch) {
+impure fn test05_start(chan[int] ch) {
     ch <| 10;
     ch <| 20;
     ch <| 30;
 }
 
-io fn test05() {
+impure fn test05() {
     let port[int] po = port();
     let chan[int] ch = chan(po);
     spawn test05_start(chan(po));
diff --git a/src/test/run-pass/task-comm-11.rs b/src/test/run-pass/task-comm-11.rs
index 519eb699f8e..41069c7fd86 100644
--- a/src/test/run-pass/task-comm-11.rs
+++ b/src/test/run-pass/task-comm-11.rs
@@ -1,9 +1,9 @@
-io fn start(chan[chan[str]] c) {
+impure fn start(chan[chan[str]] c) {
     let port[str] p = port();
     c <| chan(p);
 }
 
-io fn main() {
+impure fn main() {
     let port[chan[str]] p = port();
     auto child = spawn "child" start(chan(p));
     auto c <- p;
diff --git a/src/test/run-pass/task-comm-13-thread.rs b/src/test/run-pass/task-comm-13-thread.rs
index 0dab20ed895..e7cfc24720d 100644
--- a/src/test/run-pass/task-comm-13-thread.rs
+++ b/src/test/run-pass/task-comm-13-thread.rs
@@ -1,7 +1,7 @@
 use std;
 import std._task;
 
-io fn start(chan[int] c, int start, int number_of_messages) {
+impure fn start(chan[int] c, int start, int number_of_messages) {
     let int i = 0;
     while (i < number_of_messages) {
         c <| start + i;
diff --git a/src/test/run-pass/task-comm-13.rs b/src/test/run-pass/task-comm-13.rs
index 97bdcb6ac87..6b29ec1ee2a 100644
--- a/src/test/run-pass/task-comm-13.rs
+++ b/src/test/run-pass/task-comm-13.rs
@@ -1,7 +1,7 @@
 use std;
 import std._task;
 
-io fn start(chan[int] c, int start, int number_of_messages) {
+impure fn start(chan[int] c, int start, int number_of_messages) {
     let int i = 0;
     while (i < number_of_messages) {
         c <| start + i;
diff --git a/src/test/run-pass/task-comm-4.rs b/src/test/run-pass/task-comm-4.rs
index b185d425013..31b94603975 100644
--- a/src/test/run-pass/task-comm-4.rs
+++ b/src/test/run-pass/task-comm-4.rs
@@ -1,8 +1,8 @@
-io fn main() -> () {
+impure fn main() -> () {
    test00();
 }
 
-io fn test00() {
+impure fn test00() {
     let int r = 0;    
     let int sum = 0;
     let port[int] p = port();
diff --git a/src/test/run-pass/task-comm-5.rs b/src/test/run-pass/task-comm-5.rs
index 950f41496b6..76606094d0a 100644
--- a/src/test/run-pass/task-comm-5.rs
+++ b/src/test/run-pass/task-comm-5.rs
@@ -1,8 +1,8 @@
-io fn main() -> () {
+impure fn main() -> () {
    test00();
 }
 
-io fn test00() {
+impure fn test00() {
     let int r = 0;    
     let int sum = 0;
     let port[int] p = port();
diff --git a/src/test/run-pass/task-comm-6.rs b/src/test/run-pass/task-comm-6.rs
index 2774c0ba545..4ab9713557c 100644
--- a/src/test/run-pass/task-comm-6.rs
+++ b/src/test/run-pass/task-comm-6.rs
@@ -1,8 +1,8 @@
-io fn main() -> () {
+impure fn main() -> () {
    test00();
 }
 
-io fn test00() {
+impure fn test00() {
     let int r = 0;    
     let int sum = 0;
     let port[int] p = port();
diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs
index bb59807d5c5..099f8d6b6d4 100644
--- a/src/test/run-pass/task-comm-7.rs
+++ b/src/test/run-pass/task-comm-7.rs
@@ -1,8 +1,8 @@
-io fn main() -> () {
+impure fn main() -> () {
    test00();
 }
 
-io fn test00_start(chan[int] c, int start, int number_of_messages) {
+impure fn test00_start(chan[int] c, int start, int number_of_messages) {
     let int i = 0;
     while (i < number_of_messages) {
         c <| start + i;
@@ -10,7 +10,7 @@ io fn test00_start(chan[int] c, int start, int number_of_messages) {
     }    
 }
 
-io fn test00() {
+impure fn test00() {
     let int r = 0;    
     let int sum = 0;
     let port[int] p = port();