about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2012-01-28 11:50:48 -0500
committerJosh Matthews <josh@joshmatthews.net>2012-01-28 11:50:48 -0500
commita831e7ce13aa19acf0f65e508097351f8dabca84 (patch)
treee8b14ee2373337d3867ee573d61227387191c962
parentfcb381410d59b89336a528103582a956334c9777 (diff)
parent0794195fbdb6efa34388dfdf3dfc968bbbf06215 (diff)
downloadrust-a831e7ce13aa19acf0f65e508097351f8dabca84.tar.gz
rust-a831e7ce13aa19acf0f65e508097351f8dabca84.zip
Merge remote-tracking branch 'mozilla/master'
-rw-r--r--AUTHORS.txt1
-rw-r--r--mk/install.mk8
-rw-r--r--src/comp/metadata/decoder.rs20
-rw-r--r--src/comp/metadata/encoder.rs4
-rw-r--r--src/comp/metadata/tydecode.rs4
-rw-r--r--src/comp/middle/mut.rs22
-rw-r--r--src/comp/middle/trans/base.rs4
-rw-r--r--src/comp/middle/ty.rs31
-rw-r--r--src/comp/middle/typeck.rs29
-rw-r--r--src/comp/syntax/parse/lexer.rs2
-rw-r--r--src/comp/util/ppaux.rs2
-rw-r--r--src/compiletest/procsrv.rs8
-rw-r--r--src/libcore/extfmt.rs5
-rw-r--r--src/libcore/str.rs69
-rw-r--r--src/libcore/uint.rs4
-rw-r--r--src/libcore/vec.rs8
-rw-r--r--src/libstd/freebsd_os.rs3
-rw-r--r--src/libstd/generic_os.rs2
-rw-r--r--src/libstd/io.rs11
-rw-r--r--src/libstd/linux_os.rs3
-rw-r--r--src/libstd/list.rs2
-rw-r--r--src/libstd/macos_os.rs3
-rw-r--r--src/libstd/run_program.rs4
-rw-r--r--src/libstd/uvtmp.rs18
-rw-r--r--src/libstd/win32_os.rs3
-rw-r--r--src/rt/rust_uvtmp.cpp66
-rw-r--r--src/rt/rustrt.def.in1
-rw-r--r--src/test/bench/task-perf-word-count-generic.rs2
-rw-r--r--src/test/compile-fail/attempted-access-non-fatal.rs6
-rw-r--r--src/test/compile-fail/occurs-check.rs2
-rw-r--r--src/test/compile-fail/recursive-enum.rs5
-rw-r--r--src/test/run-pass/hashmap-memory.rs2
32 files changed, 254 insertions, 100 deletions
diff --git a/AUTHORS.txt b/AUTHORS.txt
index 1697ecd2fcb..3fd634894d5 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -5,6 +5,7 @@ Graydon Hoare <graydon@mozilla.com>
 Other authors:
 
 Adam Bozanich <adam.boz@gmail.com>
+Aleksander Balicki <balicki.aleksander@gmail.com>
 Andreas Gal <gal@mozilla.com>
 Austin Seipp <mad.one@gmail.com>
 Ben Striegel <ben.striegel@gmail.com>
diff --git a/mk/install.mk b/mk/install.mk
index 244f4c05a59..9a5ad5a6c9f 100644
--- a/mk/install.mk
+++ b/mk/install.mk
@@ -5,12 +5,12 @@
 # Installation macro. Call with source directory as arg 1,
 # destination directory as arg 2, and filename/libname-glob as arg 3
 ifdef VERBOSE
- INSTALL = cp $(1)/$(3) $(2)/$(3)
- INSTALL_LIB = cp `ls -rt1 $(1)/$(3) | tail -1` $(2)/
+ INSTALL = install -m755 -T $(1)/$(3) $(2)/$(3)
+ INSTALL_LIB = install -m644 `ls -rt1 $(1)/$(3) | tail -1` $(2)/
 else
- INSTALL = $(Q)$(call E, install: $(2)/$(3)) && cp $(1)/$(3) $(2)/$(3)
+ INSTALL = $(Q)$(call E, install: $(2)/$(3)) && install -m755 -T $(1)/$(3) $(2)/$(3)
  INSTALL_LIB = $(Q)$(call E, install_lib: $(2)/$(3)) &&                    \
-	       cp `ls -rt1 $(1)/$(3) | tail -1` $(2)/
+	       install -m644 `ls -rt1 $(1)/$(3) | tail -1` $(2)/
 endif
 
 # The stage we install from
diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs
index 01466fbc52b..426263d654a 100644
--- a/src/comp/metadata/decoder.rs
+++ b/src/comp/metadata/decoder.rs
@@ -83,7 +83,7 @@ fn item_family(item: ebml::doc) -> u8 {
 
 fn item_symbol(item: ebml::doc) -> str {
     let sym = ebml::get_doc(item, tag_items_data_item_symbol);
-    ret str::unsafe_from_bytes(ebml::doc_data(sym));
+    ret str::from_bytes(ebml::doc_data(sym));
 }
 
 fn variant_enum_id(d: ebml::doc) -> ast::def_id {
@@ -162,7 +162,7 @@ fn enum_variant_ids(item: ebml::doc, cdata: cmd) -> [ast::def_id] {
 // definition the path refers to.
 fn resolve_path(path: [ast::ident], data: @[u8]) -> [ast::def_id] {
     fn eq_item(data: [u8], s: str) -> bool {
-        ret str::eq(str::unsafe_from_bytes(data), s);
+        ret str::eq(str::from_bytes(data), s);
     }
     let s = str::connect(path, "::");
     let md = ebml::new_doc(data);
@@ -178,7 +178,7 @@ fn resolve_path(path: [ast::ident], data: @[u8]) -> [ast::def_id] {
 
 fn item_name(item: ebml::doc) -> ast::ident {
     let name = ebml::get_doc(item, tag_paths_data_name);
-    str::unsafe_from_bytes(ebml::doc_data(name))
+    str::from_bytes(ebml::doc_data(name))
 }
 
 fn lookup_item_name(data: @[u8], id: ast::node_id) -> ast::ident {
@@ -325,7 +325,7 @@ fn read_path(d: ebml::doc) -> {path: str, pos: uint} {
     let desc = ebml::doc_data(d);
     let pos = ebml::be_uint_from_bytes(@desc, 0u, 4u);
     let pathbytes = vec::slice::<u8>(desc, 4u, vec::len::<u8>(desc));
-    let path = str::unsafe_from_bytes(pathbytes);
+    let path = str::from_bytes(pathbytes);
     ret {path: path, pos: pos};
 }
 
@@ -358,21 +358,21 @@ fn get_meta_items(md: ebml::doc) -> [@ast::meta_item] {
     let items: [@ast::meta_item] = [];
     ebml::tagged_docs(md, tag_meta_item_word) {|meta_item_doc|
         let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name);
-        let n = str::unsafe_from_bytes(ebml::doc_data(nd));
+        let n = str::from_bytes(ebml::doc_data(nd));
         items += [attr::mk_word_item(n)];
     };
     ebml::tagged_docs(md, tag_meta_item_name_value) {|meta_item_doc|
         let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name);
         let vd = ebml::get_doc(meta_item_doc, tag_meta_item_value);
-        let n = str::unsafe_from_bytes(ebml::doc_data(nd));
-        let v = str::unsafe_from_bytes(ebml::doc_data(vd));
+        let n = str::from_bytes(ebml::doc_data(nd));
+        let v = str::from_bytes(ebml::doc_data(vd));
         // FIXME (#611): Should be able to decode meta_name_value variants,
         // but currently they can't be encoded
         items += [attr::mk_name_value_item_str(n, v)];
     };
     ebml::tagged_docs(md, tag_meta_item_list) {|meta_item_doc|
         let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name);
-        let n = str::unsafe_from_bytes(ebml::doc_data(nd));
+        let n = str::from_bytes(ebml::doc_data(nd));
         let subitems = get_meta_items(meta_item_doc);
         items += [attr::mk_list_item(n, subitems)];
     };
@@ -427,7 +427,7 @@ fn get_crate_deps(data: @[u8]) -> [crate_dep] {
     let depsdoc = ebml::get_doc(cratedoc, tag_crate_deps);
     let crate_num = 1;
     ebml::tagged_docs(depsdoc, tag_crate_dep) {|depdoc|
-        let depname = str::unsafe_from_bytes(ebml::doc_data(depdoc));
+        let depname = str::from_bytes(ebml::doc_data(depdoc));
         deps += [{cnum: crate_num, ident: depname}];
         crate_num += 1;
     };
@@ -447,7 +447,7 @@ fn list_crate_deps(data: @[u8], out: io::writer) {
 fn get_crate_hash(data: @[u8]) -> str {
     let cratedoc = ebml::new_doc(data);
     let hashdoc = ebml::get_doc(cratedoc, tag_crate_hash);
-    ret str::unsafe_from_bytes(ebml::doc_data(hashdoc));
+    ret str::from_bytes(ebml::doc_data(hashdoc));
 }
 
 fn list_crate_items(bytes: @[u8], md: ebml::doc, out: io::writer) {
diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs
index b7b4d97fc21..e74a2d62ced 100644
--- a/src/comp/metadata/encoder.rs
+++ b/src/comp/metadata/encoder.rs
@@ -661,7 +661,7 @@ fn encode_hash(ebml_w: ebml::writer, hash: str) {
     ebml::end_tag(ebml_w);
 }
 
-fn encode_metadata(cx: @crate_ctxt, crate: @crate) -> str {
+fn encode_metadata(cx: @crate_ctxt, crate: @crate) -> [u8] {
 
     let abbrevs = ty::new_ty_hash();
     let ecx = @{ccx: cx, type_abbrevs: abbrevs};
@@ -694,7 +694,7 @@ fn encode_metadata(cx: @crate_ctxt, crate: @crate) -> str {
     // Pad this, since something (LLVM, presumably) is cutting off the
     // remaining % 4 bytes.
     buf_w.write([0u8, 0u8, 0u8, 0u8]);
-    io::mem_buffer_str(buf)
+    io::mem_buffer_buf(buf)
 }
 
 // Get the encoded string for a type
diff --git a/src/comp/metadata/tydecode.rs b/src/comp/metadata/tydecode.rs
index d9087df05f8..b7adcfadf12 100644
--- a/src/comp/metadata/tydecode.rs
+++ b/src/comp/metadata/tydecode.rs
@@ -39,7 +39,7 @@ fn parse_ident_(st: @pstate, is_last: fn@(char) -> bool) ->
    ast::ident {
     let rslt = "";
     while !is_last(peek(st) as char) {
-        rslt += str::unsafe_from_byte(next(st));
+        rslt += str::from_byte(next(st));
     }
     ret rslt;
 }
@@ -226,7 +226,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
         while peek(st) as char != ']' {
             let name = "";
             while peek(st) as char != '=' {
-                name += str::unsafe_from_byte(next(st));
+                name += str::from_byte(next(st));
             }
             st.pos = st.pos + 1u;
             fields += [{ident: name, mt: parse_mt(st, conv)}];
diff --git a/src/comp/middle/mut.rs b/src/comp/middle/mut.rs
index 87a2c596fde..7ecdd8be8f1 100644
--- a/src/comp/middle/mut.rs
+++ b/src/comp/middle/mut.rs
@@ -5,7 +5,7 @@ import syntax::visit;
 import syntax::ast_util;
 import driver::session::session;
 
-enum deref_t { unbox, field, index, }
+enum deref_t { unbox(bool), field, index, }
 
 type deref = @{mut: bool, kind: deref_t, outer_t: ty::t};
 
@@ -20,15 +20,15 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
         while true {
             alt ty::struct(tcx, t) {
               ty::ty_box(mt) {
-                ds += [@{mut: mt.mut == mut, kind: unbox, outer_t: t}];
+                ds += [@{mut: mt.mut == mut, kind: unbox(false), outer_t: t}];
                 t = mt.ty;
               }
               ty::ty_uniq(mt) {
-                ds += [@{mut: mt.mut == mut, kind: unbox, outer_t: t}];
+                ds += [@{mut: mt.mut == mut, kind: unbox(false), outer_t: t}];
                 t = mt.ty;
               }
               ty::ty_res(_, inner, tps) {
-                ds += [@{mut: false, kind: unbox, outer_t: t}];
+                ds += [@{mut: false, kind: unbox(false), outer_t: t}];
                 t = ty::substitute_type_params(tcx, tps, inner);
               }
               ty::ty_enum(did, tps) {
@@ -37,7 +37,7 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
                        vec::len(variants[0].args) != 1u {
                     break;
                 }
-                ds += [@{mut: false, kind: unbox, outer_t: t}];
+                ds += [@{mut: false, kind: unbox(false), outer_t: t}];
                 t = ty::substitute_type_params(tcx, tps, variants[0].args[0]);
               }
               _ { break; }
@@ -85,15 +85,16 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
           expr_unary(op, base) {
             if op == deref {
                 let base_t = ty::expr_ty(tcx, base);
-                let is_mut = false;
+                let is_mut = false, ptr = false;
                 alt ty::struct(tcx, base_t) {
                   ty::ty_box(mt) { is_mut = mt.mut == mut; }
                   ty::ty_uniq(mt) { is_mut = mt.mut == mut; }
                   ty::ty_res(_, _, _) { }
                   ty::ty_enum(_, _) { }
-                  ty::ty_ptr(mt) { is_mut = mt.mut == mut; }
+                  ty::ty_ptr(mt) { is_mut = mt.mut == mut; ptr = true; }
                 }
-                ds += [@{mut: is_mut, kind: unbox, outer_t: base_t}];
+                ds += [@{mut: is_mut, kind: unbox(ptr && is_mut),
+                         outer_t: base_t}];
                 ex = base;
             } else { break; }
           }
@@ -187,7 +188,7 @@ fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
         } else if !root.ds[0].mut {
             let name =
                 alt root.ds[0].kind {
-                  mut::unbox { "immutable box" }
+                  mut::unbox(_) { "immutable box" }
                   mut::field { "immutable field" }
                   mut::index { "immutable vec content" }
                 };
@@ -212,7 +213,8 @@ fn check_move_rhs(cx: @ctx, src: @expr) {
         let root = expr_root(cx.tcx, src, false);
 
         // Not a path and no-derefs means this is a temporary.
-        if vec::len(*root.ds) != 0u {
+        if vec::len(*root.ds) != 0u &&
+           root.ds[vec::len(*root.ds) - 1u].kind != unbox(true) {
             cx.tcx.sess.span_err(src.span, "moving out of a data structure");
         }
       }
diff --git a/src/comp/middle/trans/base.rs b/src/comp/middle/trans/base.rs
index bcee44962ca..9b423be389e 100644
--- a/src/comp/middle/trans/base.rs
+++ b/src/comp/middle/trans/base.rs
@@ -268,7 +268,7 @@ fn sanitize(s: str) -> str {
                            c != ' ' as u8 && c != '\t' as u8 && c != ';' as u8
                        {
                         let v = [c];
-                        result += str::unsafe_from_bytes(v);
+                        result += str::from_bytes(v);
                     }
                 }
             }
@@ -5412,7 +5412,7 @@ fn fill_crate_map(ccx: @crate_ctxt, map: ValueRef) {
 
 fn write_metadata(cx: @crate_ctxt, crate: @ast::crate) {
     if !cx.sess.building_library { ret; }
-    let llmeta = C_postr(metadata::encoder::encode_metadata(cx, crate));
+    let llmeta = C_bytes(metadata::encoder::encode_metadata(cx, crate));
     let llconst = C_struct([llmeta]);
     let llglobal = str::as_buf("rust_metadata", {|buf|
         llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst), buf)
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 160bb832f13..502510063df 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -172,6 +172,7 @@ export type_is_str;
 export type_is_unique;
 export type_is_enum;
 export type_is_c_like_enum;
+export type_structurally_contains;
 export type_structurally_contains_uniques;
 export type_autoderef;
 export type_param;
@@ -2420,7 +2421,8 @@ mod unify {
     fn fixup_vars(tcx: ty_ctxt, sp: option::t<span>, vb: @var_bindings,
                   typ: t) -> fixup_result {
         fn subst_vars(tcx: ty_ctxt, sp: option::t<span>, vb: @var_bindings,
-                      unresolved: @mutable option::t<int>, vid: int) -> t {
+                      unresolved: @mutable option::t<int>,
+                      vars_seen: std::list::list<int>, vid: int) -> t {
             // Should really return a fixup_result instead of a t, but fold_ty
             // doesn't allow returning anything but a t.
             if vid as uint >= ufind::set_count(vb.sets) {
@@ -2431,21 +2433,28 @@ mod unify {
             alt smallintmap::find::<t>(vb.types, root_id) {
               none { *unresolved = some(vid); ret ty::mk_var(tcx, vid); }
               some(rt) {
-                if occurs_check_fails(tcx, sp, vid, rt) {
-                    // Return the type unchanged, so we can error out
-                    // downstream
-                    ret rt;
+                let give_up = false;
+                std::list::iter(vars_seen) {|v|
+                    if v == vid {
+                        give_up = true;
+                        option::may(sp) {|sp|
+                            tcx.sess.span_fatal(
+                                sp, "can not instantiate infinite type");
+                        }
+                    }
                 }
-                ret fold_ty(tcx,
-                            fm_var(bind subst_vars(tcx, sp, vb, unresolved,
-                                                   _)), rt);
+                // Return the type unchanged, so we can error out
+                // downstream
+                if give_up { ret rt; }
+                ret fold_ty(tcx, fm_var(bind subst_vars(
+                    tcx, sp, vb, unresolved, std::list::cons(vid, @vars_seen),
+                    _)), rt);
               }
             }
         }
         let unresolved = @mutable none::<int>;
-        let rty =
-            fold_ty(tcx, fm_var(bind subst_vars(tcx, sp, vb, unresolved, _)),
-                    typ);
+        let rty = fold_ty(tcx, fm_var(bind subst_vars(
+            tcx, sp, vb, unresolved, std::list::nil, _)), typ);
         let ur = *unresolved;
         alt ur {
           none { ret fix_ok(rty); }
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 1d54ec2befc..8a06314a96b 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -259,10 +259,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
     alt tcx.ast_ty_to_ty_cache.find(ast_ty) {
       some(some(ty)) { ret ty; }
       some(none) {
-        tcx.sess.span_fatal(ast_ty.span,
-                            "illegal recursive type \
-                              insert a enum in the cycle, \
-                              if this is desired)");
+        tcx.sess.span_fatal(ast_ty.span, "illegal recursive type. \
+                                          insert a enum in the cycle, \
+                                          if this is desired)");
       }
       none { }
     } /* go on */
@@ -2298,7 +2297,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
                 let msg = #fmt["attempted access of field %s on type %s, but \
                                 no method implementation was found",
                                field, ty_to_str(tcx, t_err)];
-                tcx.sess.span_fatal(expr.span, msg);
+                tcx.sess.span_err(expr.span, msg);
+                // NB: Adding a bogus type to allow typechecking to continue
+                write::ty_only_fixup(fcx, id, ty::mk_nil(tcx));
               }
             }
         }
@@ -2490,7 +2491,7 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
     demand::simple(fcx, e.span, declty, cty);
 }
 
-fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
+fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
                       id: ast::node_id) {
     // FIXME: this is kinda a kludge; we manufacture a fake function context
     // and statement context for checking the initializer expression.
@@ -2512,7 +2513,7 @@ fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
           some(e) {
             check_expr(fcx, e);
             let cty = expr_ty(fcx.ccx.tcx, e);
-            let declty =ty::mk_int(fcx.ccx.tcx);
+            let declty = ty::mk_int(fcx.ccx.tcx);
             demand::simple(fcx, e.span, declty, cty);
             // FIXME: issue #1417
             // Also, check_expr (from check_const pass) doesn't guarantee that
@@ -2537,6 +2538,20 @@ fn check_enum_variants(ccx: @crate_ctxt, _sp: span, vs: [ast::variant],
         disr_vals += [disr_val];
         disr_val += 1;
     }
+    let outer = true, did = local_def(id);
+    if ty::type_structurally_contains(ccx.tcx, rty, {|sty|
+        alt sty {
+          ty::ty_enum(id, _) if id == did {
+            if outer { outer = false; false }
+            else { true }
+          }
+          _ { false }
+        }
+    }) {
+        ccx.tcx.sess.span_fatal(sp, "illegal recursive enum type. \
+                                     wrap the inner value in a box to \
+                                     make it represenable");
+    }
 }
 
 // A generic function for checking the pred in a check
diff --git a/src/comp/syntax/parse/lexer.rs b/src/comp/syntax/parse/lexer.rs
index 66e0f87d982..d2fbe02d63a 100644
--- a/src/comp/syntax/parse/lexer.rs
+++ b/src/comp/syntax/parse/lexer.rs
@@ -672,7 +672,7 @@ fn gather_comments_and_literals(cm: codemap::codemap,
                                 path: str,
                                 srdr: io::reader) ->
    {cmnts: [cmnt], lits: [lit]} {
-    let src = @str::unsafe_from_bytes(srdr.read_whole_stream());
+    let src = @str::from_bytes(srdr.read_whole_stream());
     let itr = @interner::mk::<str>(str::hash, str::eq);
     let rdr = new_reader(cm, span_diagnostic,
                          codemap::new_filemap(path, src, 0u, 0u), itr);
diff --git a/src/comp/util/ppaux.rs b/src/comp/util/ppaux.rs
index f2c342a2956..2ae8a860a27 100644
--- a/src/comp/util/ppaux.rs
+++ b/src/comp/util/ppaux.rs
@@ -118,7 +118,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
       }
       ty_var(v) { "<T" + int::str(v) + ">" }
       ty_param(id, _) {
-        "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)])
+        "'" + str::from_bytes([('a' as u8) + (id as u8)])
       }
       _ { ty_to_short_str(cx, typ) }
     }
diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs
index a758e9a21bb..6f3fd87466a 100644
--- a/src/compiletest/procsrv.rs
+++ b/src/compiletest/procsrv.rs
@@ -85,7 +85,7 @@ fn readclose(fd: fd_t) -> str {
     let buf = "";
     while !reader.eof() {
         let bytes = reader.read_bytes(4096u);
-        buf += str::unsafe_from_bytes(bytes);
+        buf += str::from_bytes(bytes);
     }
     os::fclose(file);
     ret buf;
@@ -114,8 +114,8 @@ fn worker(p: port<request>) {
                 // the alt discriminant are wrong.
                 alt recv(p) {
                   exec(lib_path, prog, args, respchan) {
-                    {lib_path: str::unsafe_from_bytes(lib_path),
-                     prog: str::unsafe_from_bytes(prog),
+                    {lib_path: str::from_bytes(lib_path),
+                     prog: str::from_bytes(prog),
                      args: clone_vecu8str(args),
                      respchan: respchan}
                   }
@@ -189,7 +189,7 @@ fn clone_vecstr(v: [str]) -> [[u8]] {
 fn clone_vecu8str(v: [[u8]]) -> [str] {
     let r = [];
     for t in vec::slice(v, 0u, vec::len(v)) {
-        r += [str::unsafe_from_bytes(t)];
+        r += [str::from_bytes(t)];
     }
     ret r;
 }
diff --git a/src/libcore/extfmt.rs b/src/libcore/extfmt.rs
index 38b36f59d32..eb91c2cb5d5 100644
--- a/src/libcore/extfmt.rs
+++ b/src/libcore/extfmt.rs
@@ -390,7 +390,7 @@ mod rt {
     fn str_init_elt(n_elts: uint, c: char) -> str {
         let svec = vec::init_elt::<u8>(n_elts, c as u8);
 
-        ret str::unsafe_from_bytes(svec);
+        ret str::from_bytes(svec);
     }
     enum pad_mode { pad_signed, pad_unsigned, pad_nozero, }
     fn pad(cv: conv, s: str, mode: pad_mode) -> str {
@@ -439,7 +439,8 @@ mod rt {
         if signed && zero_padding && str::byte_len(s) > 0u {
             let head = s[0];
             if head == '+' as u8 || head == '-' as u8 || head == ' ' as u8 {
-                let headstr = str::unsafe_from_bytes([head]);
+                let headstr = str::from_bytes([head]);
+                // FIXME: not UTF-8 safe
                 let bytelen = str::byte_len(s);
                 let numpart = str::substr(s, 1u, bytelen - 1u);
                 ret headstr + padstr + numpart;
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 823f7cc78c6..dad10eced7f 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -13,6 +13,7 @@ export
    // Creating a string
    from_bytes,
    unsafe_from_bytes,
+   from_byte,
    unsafe_from_byte,
    //push_utf8_bytes,
    from_char,
@@ -117,14 +118,11 @@ Section: Creating a string
 /*
 Function: from_bytes
 
-Safely convert a vector of bytes to a UTF-8 string, or error
+Convert a vector of bytes to a UTF-8 string.  Fails if invalid UTF-8.
 */
-fn from_bytes(vv: [u8]) -> result::t<str, str> {
-   if is_utf8(vv) {
-      ret result::ok(unsafe_from_bytes(vv));
-   } else {
-      ret result::err("vector doesn't contain valid UTF-8");
-   }
+fn from_bytes(vv: [u8]) -> str {
+   assert is_utf8(vv);
+   ret unsafe_from_bytes(vv);
 }
 
 /*
@@ -133,7 +131,7 @@ Function: unsafe_from_bytes
 Converts a vector of bytes to a string. Does not verify that the
 vector contains valid UTF-8.
 
-// FIXME: remove?
+FIXME: stop exporting
 */
 fn unsafe_from_bytes(v: [const u8]) -> str unsafe {
     let vcopy: [u8] = v + [0u8];
@@ -148,10 +146,20 @@ Function: unsafe_from_byte
 Converts a byte to a string. Does not verify that the byte is
 valid UTF-8.
 
-FIXME: rename to 'from_byte'
+FIXME: stop exporting
 */
 fn unsafe_from_byte(u: u8) -> str { unsafe_from_bytes([u]) }
 
+
+/*
+Function: from_byte
+
+Convert a byte to a UTF-8 string.  Fails if invalid UTF-8.
+*/
+fn from_byte(uu: u8) -> str {
+    from_bytes([uu])
+}
+
 fn push_utf8_bytes(&s: str, ch: char) {
     let code = ch as uint;
     let bytes =
@@ -209,16 +217,16 @@ Function: from_cstr
 Create a Rust string from a null-terminated C string
 */
 unsafe fn from_cstr(cstr: sbuf) -> str {
-    let res = "";
+    let res = [];
     let start = cstr;
     let curr = start;
     let i = 0u;
     while *curr != 0u8 {
-        push_byte(res, *curr);
+        vec::push(res, *curr);
         i += 1u;
         curr = ptr::offset(start, i);
     }
-    ret res;
+    ret from_bytes(res);
 }
 
 /*
@@ -526,7 +534,7 @@ fn split(s: str, sep: u8) -> [str] {
             v += [accum];
             accum = "";
             ends_with_sep = true;
-        } else { accum += unsafe_from_byte(c); ends_with_sep = false; }
+        } else { accum += from_byte(c); ends_with_sep = false; }
     }
     if byte_len(accum) != 0u || ends_with_sep { v += [accum]; }
     ret v;
@@ -554,7 +562,7 @@ fn splitn(s: str, sep: u8, count: uint) -> [str] {
             v += [accum];
             accum = "";
             ends_with_sep = true;
-        } else { accum += unsafe_from_byte(c); ends_with_sep = false; }
+        } else { accum += from_byte(c); ends_with_sep = false; }
     }
     if byte_len(accum) != 0u || ends_with_sep { v += [accum]; }
     ret v;
@@ -575,12 +583,12 @@ FIXME: should behave like split and split_char:
 */
 fn split_str(s: str, sep: str) -> [str] {
     assert byte_len(sep) > 0u;
-    let v: [str] = [], accum = "", sep_match = 0u, leading = true;
+    let v: [str] = [], accum = [], sep_match = 0u, leading = true;
     for c: u8 in s {
         // Did we match the entire separator?
         if sep_match == byte_len(sep) {
-            if !leading { v += [accum]; }
-            accum = "";
+            if !leading { vec::push(v, from_bytes(accum)); }
+            accum = [];
             sep_match = 0u;
         }
 
@@ -588,13 +596,13 @@ fn split_str(s: str, sep: str) -> [str] {
             sep_match += 1u;
         } else {
             sep_match = 0u;
-            accum += unsafe_from_byte(c);
+            vec::push(accum, c);
             leading = false;
         }
     }
 
-    if byte_len(accum) > 0u { v += [accum]; }
-    if sep_match == byte_len(sep) { v += [""]; }
+    if vec::len(accum) > 0u { vec::push(v, from_bytes(accum)); }
+    if sep_match == byte_len(sep) { vec::push(v, ""); }
 
     ret v;
 }
@@ -1783,7 +1791,24 @@ mod tests {
                   0x20_u8, 0x4e_u8, 0x61_u8,
                   0x6d_u8];
 
-         assert ss == result::get(from_bytes(bb));
+         assert ss == from_bytes(bb);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_from_bytes_fail() {
+        let bb = [0xff_u8, 0xb8_u8, 0xa8_u8,
+                  0xe0_u8, 0xb9_u8, 0x84_u8,
+                  0xe0_u8, 0xb8_u8, 0x97_u8,
+                  0xe0_u8, 0xb8_u8, 0xa2_u8,
+                  0xe4_u8, 0xb8_u8, 0xad_u8,
+                  0xe5_u8, 0x8d_u8, 0x8e_u8,
+                  0x56_u8, 0x69_u8, 0xe1_u8,
+                  0xbb_u8, 0x87_u8, 0x74_u8,
+                  0x20_u8, 0x4e_u8, 0x61_u8,
+                  0x6d_u8];
+
+         let _x = from_bytes(bb);
     }
 
     #[test]
@@ -1821,7 +1846,7 @@ mod tests {
         let s1: str = "All mimsy were the borogoves";
 
         let v: [u8] = bytes(s1);
-        let s2: str = unsafe_from_bytes(v);
+        let s2: str = from_bytes(v);
         let i: uint = 0u;
         let n1: uint = byte_len(s1);
         let n2: uint = vec::len::<u8>(v);
diff --git a/src/libcore/uint.rs b/src/libcore/uint.rs
index 8d032610e17..2112399ba80 100644
--- a/src/libcore/uint.rs
+++ b/src/libcore/uint.rs
@@ -236,12 +236,12 @@ fn to_str(num: uint, radix: uint) -> str {
     if n == 0u { ret "0"; }
     let s: str = "";
     while n != 0u {
-        s += str::unsafe_from_byte(digit(n % radix) as u8);
+        s += str::from_byte(digit(n % radix) as u8);
         n /= radix;
     }
     let s1: str = "";
     let len: uint = str::byte_len(s);
-    while len != 0u { len -= 1u; s1 += str::unsafe_from_byte(s[len]); }
+    while len != 0u { len -= 1u; s1 += str::from_byte(s[len]); }
     ret s1;
 }
 
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 8b7ea91becd..4dabab99c23 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -307,6 +307,14 @@ fn pop<T: copy>(&v: [const T]) -> T {
     let e = v[ln];
     v = slice(v, 0u, ln);
     ret e;
+// FIXME use this implementation after the next snapshot (27.01.2012)
+/*  let new_ln = len(v) - 1u;
+    assert (new_ln > 0u);
+    let valptr = ptr::mut_addr_of(v[new_ln]);
+    let val <- *valptr;
+    unsafe::set_len(v, new_ln);
+    val
+*/
 }
 
 /*
diff --git a/src/libstd/freebsd_os.rs b/src/libstd/freebsd_os.rs
index 847262ca10c..89aad5d7777 100644
--- a/src/libstd/freebsd_os.rs
+++ b/src/libstd/freebsd_os.rs
@@ -129,7 +129,8 @@ fn dylib_filename(base: str) -> str { ret "lib" + base + ".so"; }
 /// followed by a path separator
 fn get_exe_path() -> option::t<fs::path> unsafe {
     let bufsize = 1023u;
-    let path = str::unsafe_from_bytes(vec::init_elt(bufsize, 0u8));
+    // FIXME: path "strings" will likely need fixing...
+    let path = str::from_bytes(vec::init_elt(bufsize, 0u8));
     let mib = [libc_constants::CTL_KERN,
                libc_constants::KERN_PROC,
                libc_constants::KERN_PROC_PATHNAME, -1i32];
diff --git a/src/libstd/generic_os.rs b/src/libstd/generic_os.rs
index 750b333f1a6..934352e7788 100644
--- a/src/libstd/generic_os.rs
+++ b/src/libstd/generic_os.rs
@@ -75,7 +75,7 @@ fn getenv(n: str) -> option::t<str> {
             unsafe {
                 vec::unsafe::set_len(v, res);
             }
-            ret option::some(str::unsafe_from_bytes(v));
+            ret option::some(str::from_bytes(v)); // UTF-8 or fail
         } else { nsize = res; }
     }
     fail;
diff --git a/src/libstd/io.rs b/src/libstd/io.rs
index 1db355dd385..5cc08813d6a 100644
--- a/src/libstd/io.rs
+++ b/src/libstd/io.rs
@@ -109,7 +109,7 @@ impl reader_util for reader {
             if ch == -1 || ch == 10 { break; }
             buf += [ch as u8];
         }
-        str::unsafe_from_bytes(buf)
+        str::from_bytes(buf)
     }
 
     fn read_c_str() -> str {
@@ -118,7 +118,7 @@ impl reader_util for reader {
             let ch = self.read_byte();
             if ch < 1 { break; } else { buf += [ch as u8]; }
         }
-        str::unsafe_from_bytes(buf)
+        str::from_bytes(buf)
     }
 
     // FIXME deal with eof?
@@ -461,7 +461,10 @@ fn mk_mem_buffer() -> mem_buffer {
 }
 fn mem_buffer_writer(b: mem_buffer) -> writer { b as writer }
 fn mem_buffer_buf(b: mem_buffer) -> [u8] { vec::from_mut(b.buf) }
-fn mem_buffer_str(b: mem_buffer) -> str { str::unsafe_from_bytes(b.buf) }
+fn mem_buffer_str(b: mem_buffer) -> str {
+   let b_ = vec::from_mut(b.buf);
+   str::from_bytes(b_)
+}
 
 // Utility functions
 fn seek_in_buf(offset: int, pos: uint, len: uint, whence: seek_style) ->
@@ -479,7 +482,7 @@ fn seek_in_buf(offset: int, pos: uint, len: uint, whence: seek_style) ->
 
 fn read_whole_file_str(file: str) -> result::t<str, str> {
     result::chain(read_whole_file(file), { |bytes|
-        result::ok(str::unsafe_from_bytes(bytes))
+        result::ok(str::from_bytes(bytes))
     })
 }
 
diff --git a/src/libstd/linux_os.rs b/src/libstd/linux_os.rs
index 7bc0212c1c2..82b1197a51f 100644
--- a/src/libstd/linux_os.rs
+++ b/src/libstd/linux_os.rs
@@ -125,7 +125,8 @@ fn dylib_filename(base: str) -> str { ret "lib" + base + ".so"; }
 /// followed by a path separator
 fn get_exe_path() -> option::t<fs::path> {
     let bufsize = 1023u;
-    let path = str::unsafe_from_bytes(vec::init_elt(bufsize, 0u8));
+    // FIXME: path "strings" will likely need fixing...
+    let path = str::from_bytes(vec::init_elt(bufsize, 0u8));
     ret str::as_buf("/proc/self/exe", { |proc_self_buf|
         str::as_buf(path, { |path_buf|
             if libc::readlink(proc_self_buf, path_buf, bufsize) != -1 {
diff --git a/src/libstd/list.rs b/src/libstd/list.rs
index 2081a21de23..e393b42b9f2 100644
--- a/src/libstd/list.rs
+++ b/src/libstd/list.rs
@@ -128,7 +128,7 @@ Function: tail
 
 Returns all but the first element of a list
 */
-pure fn tail<T: copy>(ls: list<T>) : is_not_empty(ls) -> list<T> {
+pure fn tail<T: copy>(ls: list<T>) -> list<T> {
     alt ls {
         cons(_, tl) { ret *tl; }
         nil { fail "list empty" }
diff --git a/src/libstd/macos_os.rs b/src/libstd/macos_os.rs
index b72fc732379..cd984870781 100644
--- a/src/libstd/macos_os.rs
+++ b/src/libstd/macos_os.rs
@@ -133,8 +133,9 @@ fn dylib_filename(base: str) -> str { ret "lib" + base + ".dylib"; }
 
 fn get_exe_path() -> option::t<fs::path> {
     // FIXME: This doesn't handle the case where the buffer is too small
+    // FIXME: path "strings" will likely need fixing...
     let bufsize = 1023u32;
-    let path = str::unsafe_from_bytes(vec::init_elt(bufsize as uint, 0u8));
+    let path = str::from_bytes(vec::init_elt(bufsize as uint, 0u8));
     ret str::as_buf(path, { |path_buf|
         if mac_libc::_NSGetExecutablePath(path_buf,
                                           ptr::mut_addr_of(bufsize)) == 0i32 {
diff --git a/src/libstd/run_program.rs b/src/libstd/run_program.rs
index e40526b5884..5b2de1e57d0 100644
--- a/src/libstd/run_program.rs
+++ b/src/libstd/run_program.rs
@@ -216,7 +216,7 @@ fn read_all(rd: io::reader) -> str {
     let buf = "";
     while !rd.eof() {
         let bytes = rd.read_bytes(4096u);
-        buf += str::unsafe_from_bytes(bytes);
+        buf += str::from_bytes(bytes);
     }
     ret buf;
 }
@@ -347,7 +347,7 @@ mod tests {
             let buf = "";
             while !reader.eof() {
                 let bytes = reader.read_bytes(4096u);
-                buf += str::unsafe_from_bytes(bytes);
+                buf += str::from_bytes(bytes);
             }
             os::fclose(file);
             ret buf;
diff --git a/src/libstd/uvtmp.rs b/src/libstd/uvtmp.rs
index fb9df4bfbd3..ae08cd5ed5e 100644
--- a/src/libstd/uvtmp.rs
+++ b/src/libstd/uvtmp.rs
@@ -27,6 +27,11 @@ native mod rustrt {
         thread: thread,
         req_id: u32,
         chan: comm::chan<iomsg>);
+    fn rust_uvtmp_timer(
+        thread: thread,
+        timeout: u32,
+        req_id: u32,
+        chan: comm::chan<iomsg>);
     fn rust_uvtmp_delete_buf(buf: *u8);
     fn rust_uvtmp_get_req_id(cd: connect_data) -> u32;
 }
@@ -39,7 +44,9 @@ enum iomsg {
     whatever,
     connected(connect_data),
     wrote(connect_data),
-    read(connect_data, *u8, ctypes::ssize_t)
+    read(connect_data, *u8, ctypes::ssize_t),
+    timer(u32),
+    exit
 }
 
 fn create_thread() -> thread {
@@ -80,6 +87,11 @@ fn read_start(thread: thread, req_id: u32,
     rustrt::rust_uvtmp_read_start(thread, req_id, chan);
 }
 
+fn timer_start(thread: thread, timeout: u32, req_id: u32,
+              chan: comm::chan<iomsg>) {
+    rustrt::rust_uvtmp_timer(thread, timeout, req_id, chan);
+}
+
 fn delete_buf(buf: *u8) {
     rustrt::rust_uvtmp_delete_buf(buf);
 }
@@ -138,7 +150,7 @@ fn test_http() {
                     unsafe {
                         log(error, len);
                         let buf = vec::unsafe::from_buf(buf, len as uint);
-                        let str = str::unsafe_from_bytes(buf);
+                        let str = str::from_bytes(buf);
                         #error("read something");
                         io::println(str);
                     }
@@ -153,4 +165,4 @@ fn test_http() {
     }
     join_thread(thread);
     delete_thread(thread);
-}
\ No newline at end of file
+}
diff --git a/src/libstd/win32_os.rs b/src/libstd/win32_os.rs
index 949c818a7ed..83306c757a4 100644
--- a/src/libstd/win32_os.rs
+++ b/src/libstd/win32_os.rs
@@ -113,8 +113,9 @@ fn getcwd() -> str { ret rustrt::rust_getcwd(); }
 
 fn get_exe_path() -> option::t<fs::path> {
     // FIXME: This doesn't handle the case where the buffer is too small
+    // FIXME: path "strings" will likely need fixing...
     let bufsize = 1023u;
-    let path = str::unsafe_from_bytes(vec::init_elt(bufsize, 0u8));
+    let path = str::from_bytes(vec::init_elt(bufsize, 0u8));
     ret str::as_buf(path, { |path_buf|
         if kernel32::GetModuleFileNameA(0u, path_buf,
                                         bufsize as u32) != 0u32 {
diff --git a/src/rt/rust_uvtmp.cpp b/src/rt/rust_uvtmp.cpp
index 27e0021bc6c..7f4b425e5ec 100644
--- a/src/rt/rust_uvtmp.cpp
+++ b/src/rt/rust_uvtmp.cpp
@@ -15,9 +15,12 @@ struct connect_data {
     chan_handle chan;
 };
 
+const intptr_t whatever_tag = 0;
 const intptr_t connected_tag = 1;
 const intptr_t wrote_tag = 2;
 const intptr_t read_tag = 3;
+const intptr_t timer_tag = 4;
+const intptr_t exit_tag = 5;
 
 struct iomsg {
     intptr_t tag;
@@ -29,6 +32,7 @@ struct iomsg {
 	    uint8_t *buf;
 	    ssize_t nread;
 	} read_val;
+        uint32_t timer_req_id;
     } val;
 };
 
@@ -44,6 +48,13 @@ struct read_start_data {
     chan_handle chan;
 };
 
+struct timer_start_data {
+    rust_uvtmp_thread *thread;
+    uint32_t timeout;
+    uint32_t req_id;
+    chan_handle chan;
+};
+
 // FIXME: Copied from rust_builtins.cpp. Could bitrot easily
 static void
 send(rust_task *task, chan_handle chan, void *data) {
@@ -72,7 +83,7 @@ private:
     std::queue<connect_data*> close_connection_queue;
     std::queue<write_data*> write_queue;
     std::queue<read_start_data*> read_start_queue;
-
+    std::queue<timer_start_data*> timer_start_queue;
 public:
 
     rust_uvtmp_thread() {
@@ -139,6 +150,17 @@ public:
         read_start_queue.push(rd);
     }
 
+    void
+    timer(uint32_t timeout, uint32_t req_id, chan_handle chan) {
+        scoped_lock with(lock);
+
+        timer_start_data *td = new timer_start_data();
+        td->timeout = timeout;
+        td->req_id = req_id;
+        td->chan = chan;
+        timer_start_queue.push(td);
+    }
+
 private:
 
     virtual void
@@ -159,6 +181,7 @@ private:
 	close_connections();
 	write_buffers();
 	start_reads();
+        start_timers();
 	close_idle_if_stop();
     }
 
@@ -246,7 +269,7 @@ private:
     void
     on_write(uv_write_t *handle, write_data *wd) {
 	iomsg msg;
-	msg.tag = wrote_tag;
+	msg.tag = timer_tag;
 	msg.val.wrote_val = wd->cd;
 
 	send(task, wd->chan, &msg);
@@ -300,6 +323,40 @@ private:
     }
 
     void
+    start_timers() {
+	assert (lock.lock_held_by_current_thread());
+	while (!timer_start_queue.empty()) {
+	    timer_start_data *td = timer_start_queue.front();
+	    timer_start_queue.pop();
+
+            td->thread = this;
+
+            uv_timer_t *timer = (uv_timer_t *)malloc(sizeof(uv_timer_t));
+            timer->data = td;
+            uv_timer_init(loop, timer);
+            uv_timer_start(timer, timer_cb, td->timeout, 0);
+	}
+    }
+
+    static void
+    timer_cb(uv_timer_t *handle, int what) {
+	timer_start_data *td = (timer_start_data*)handle->data;
+	rust_uvtmp_thread *self = td->thread;
+	self->on_timer(td);
+        free(handle);
+    }
+
+    void
+    on_timer(timer_start_data *rd) {
+	iomsg msg;
+	msg.tag = timer_tag;
+        msg.val.timer_req_id = rd->req_id;
+
+	send(task, rd->chan, &msg);
+        delete rd;
+    }
+
+    void
     close_idle_if_stop() {
 	assert(lock.lock_held_by_current_thread());
 	if (stop_flag) {
@@ -354,6 +411,11 @@ rust_uvtmp_read_start(rust_uvtmp_thread *thread, uint32_t req_id,
 }
 
 extern "C" void
+rust_uvtmp_timer(rust_uvtmp_thread *thread, uint32_t timeout, uint32_t req_id, chan_handle *chan) {
+    thread->timer(timeout, req_id, *chan);
+}
+
+extern "C" void
 rust_uvtmp_delete_buf(uint8_t *buf) {
     delete [] buf;
 }
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 17a0274d96e..052f4a42779 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -96,6 +96,7 @@ rust_uvtmp_connect
 rust_uvtmp_close_connection
 rust_uvtmp_write
 rust_uvtmp_read_start
+rust_uvtmp_timer
 rust_uvtmp_delete_buf
 rust_uvtmp_get_req_id
 
diff --git a/src/test/bench/task-perf-word-count-generic.rs b/src/test/bench/task-perf-word-count-generic.rs
index 55fbc6705b6..8be28fabd79 100644
--- a/src/test/bench/task-perf-word-count-generic.rs
+++ b/src/test/bench/task-perf-word-count-generic.rs
@@ -32,7 +32,7 @@ import comm::recv;
 import comm::send;
 
 fn map(&&filename: [u8], emit: map_reduce::putter<[u8], int>) {
-    let f = io::file_reader(str::unsafe_from_bytes(filename));
+    let f = io::file_reader(str::from_bytes(filename));
 
     while true {
         alt read_word(f) {
diff --git a/src/test/compile-fail/attempted-access-non-fatal.rs b/src/test/compile-fail/attempted-access-non-fatal.rs
new file mode 100644
index 00000000000..7ead10b3f63
--- /dev/null
+++ b/src/test/compile-fail/attempted-access-non-fatal.rs
@@ -0,0 +1,6 @@
+// Check that bogus field access is non-fatal
+fn main() {
+    let x = 0;
+    log(debug, x.foo); //! ERROR attempted access of field
+    log(debug, x.bar); //! ERROR attempted access of field
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/occurs-check.rs b/src/test/compile-fail/occurs-check.rs
index aba5b5c5928..069bd0a5bbd 100644
--- a/src/test/compile-fail/occurs-check.rs
+++ b/src/test/compile-fail/occurs-check.rs
@@ -1,2 +1,2 @@
-// error-pattern: Type inference failed because I could not find
+// error-pattern: can not instantiate infinite type
 fn main() { let f; f = @f; }
diff --git a/src/test/compile-fail/recursive-enum.rs b/src/test/compile-fail/recursive-enum.rs
new file mode 100644
index 00000000000..b3764036b99
--- /dev/null
+++ b/src/test/compile-fail/recursive-enum.rs
@@ -0,0 +1,5 @@
+// error-pattern: illegal recursive enum type
+
+enum list<T> { cons(T, list<T>), nil }
+
+fn main() {}
diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs
index 777b56c7520..9301d93874e 100644
--- a/src/test/run-pass/hashmap-memory.rs
+++ b/src/test/run-pass/hashmap-memory.rs
@@ -81,7 +81,7 @@ mod map_reduce {
               mapper_done { num_mappers -= 1; }
               find_reducer(k, cc) {
                 let c;
-                alt reducers.find(str::unsafe_from_bytes(k)) {
+                alt reducers.find(str::from_bytes(k)) {
                   some(_c) { c = _c; }
                   none { c = 0; }
                 }