]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #7996 : erickt/rust/cleanup-strs, r=erickt
authorbors <bors@rust-lang.org>
Wed, 24 Jul 2013 20:25:36 +0000 (13:25 -0700)
committerbors <bors@rust-lang.org>
Wed, 24 Jul 2013 20:25:36 +0000 (13:25 -0700)
This is a cleanup pull request that does:

* removes `os::as_c_charp`
* moves `str::as_buf` and `str::as_c_str` into `StrSlice`
* converts some functions from `StrSlice::as_buf` to `StrSlice::as_c_str`
* renames `StrSlice::as_buf` to `StrSlice::as_imm_buf` (and adds `StrSlice::as_mut_buf` to match `vec.rs`.
* renames `UniqueStr::as_bytes_with_null_consume` to `UniqueStr::to_bytes`
* and other misc cleanups and minor optimizations

1  2 
src/libextra/future.rs
src/libextra/getopts.rs
src/librustc/back/passes.rs
src/librustc/middle/trans/asm.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/controlflow.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/trans/glue.rs
src/libstd/str.rs
src/libstd/vec.rs

diff --combined src/libextra/future.rs
index 5e37efa647ad695225c7b8315fdc761879e208e1,3e5bca60a957b6cc2d2aac9addee0b09fa38c775..7d2a0658969ab7cc62ea8273fc0c5d3d85c61432
@@@ -19,7 -19,7 +19,7 @@@
   * # fn make_a_sandwich() {};
   * let mut delayed_fib = extra::future::spawn (|| fib(5000) );
   * make_a_sandwich();
 - * println(fmt!("fib(5000) = %?", delayed_fib.get()))
 + * printfln!("fib(5000) = %?", delayed_fib.get())
   * ~~~
   */
  
@@@ -194,7 -194,7 +194,7 @@@ mod test 
  
      #[test]
      fn test_interface_unwrap() {
-         let mut f = from_value(~"fail");
+         let f = from_value(~"fail");
          assert_eq!(f.unwrap(), ~"fail");
      }
  
diff --combined src/libextra/getopts.rs
index ad452125239de6404b5e2c55a14c3c4f6a4d7d6a,c6db3637eedcc7b2b6de433bd9056d4fd49b858a..6c9f9857a881abfed1b48c23eb0072853d0c6465
@@@ -44,7 -44,7 +44,7 @@@
   *    }
   *
   *    fn print_usage(program: &str, _opts: &[Opt]) {
 - *        println(fmt!("Usage: %s [options]", program));
 + *        printfln!("Usage: %s [options]", program);
   *        println("-o\t\tOutput");
   *        println("-h --help\tUsage");
   *    }
@@@ -457,7 -457,7 +457,7 @@@ pub fn opt_default(mm: &Matches, nm: &s
      let vals = opt_vals(mm, nm);
      if vals.is_empty() { return None::<~str>; }
      return match vals[0] { Val(ref s) => Some::<~str>((*s).clone()),
-                            _      => Some::<~str>(str::to_owned(def)) }
+                            _      => Some::<~str>(def.to_owned()) }
  }
  
  #[deriving(Eq)]
@@@ -497,10 -497,10 +497,10 @@@ pub mod groups 
                    desc: &str, hint: &str) -> OptGroup {
          let len = short_name.len();
          assert!(len == 1 || len == 0);
-         return OptGroup { short_name: str::to_owned(short_name),
-                 long_name: str::to_owned(long_name),
-                 hint: str::to_owned(hint),
-                 desc: str::to_owned(desc),
+         return OptGroup { short_name: short_name.to_owned(),
+                 long_name: long_name.to_owned(),
+                 hint: hint.to_owned(),
+                 desc: desc.to_owned(),
                  hasarg: Yes,
                  occur: Req};
      }
                    desc: &str, hint: &str) -> OptGroup {
          let len = short_name.len();
          assert!(len == 1 || len == 0);
-         return OptGroup {short_name: str::to_owned(short_name),
-                 long_name: str::to_owned(long_name),
-                 hint: str::to_owned(hint),
-                 desc: str::to_owned(desc),
+         return OptGroup {short_name: short_name.to_owned(),
+                 long_name: long_name.to_owned(),
+                 hint: hint.to_owned(),
+                 desc: desc.to_owned(),
                  hasarg: Yes,
                  occur: Optional};
      }
                     desc: &str) -> OptGroup {
          let len = short_name.len();
          assert!(len == 1 || len == 0);
-         return OptGroup {short_name: str::to_owned(short_name),
-                 long_name: str::to_owned(long_name),
+         return OptGroup {short_name: short_name.to_owned(),
+                 long_name: long_name.to_owned(),
                  hint: ~"",
-                 desc: str::to_owned(desc),
+                 desc: desc.to_owned(),
                  hasarg: No,
                  occur: Optional};
      }
                        desc: &str, hint: &str) -> OptGroup {
          let len = short_name.len();
          assert!(len == 1 || len == 0);
-         return OptGroup {short_name: str::to_owned(short_name),
-                 long_name: str::to_owned(long_name),
-                 hint: str::to_owned(hint),
-                 desc: str::to_owned(desc),
+         return OptGroup {short_name: short_name.to_owned(),
+                 long_name: long_name.to_owned(),
+                 hint: hint.to_owned(),
+                 desc: desc.to_owned(),
                  hasarg: Maybe,
                  occur: Optional};
      }
                      desc: &str, hint: &str) -> OptGroup {
          let len = short_name.len();
          assert!(len == 1 || len == 0);
-         return OptGroup {short_name: str::to_owned(short_name),
-                 long_name: str::to_owned(long_name),
-                 hint: str::to_owned(hint),
-                 desc: str::to_owned(desc),
+         return OptGroup {short_name: short_name.to_owned(),
+                 long_name: long_name.to_owned(),
+                 hint: hint.to_owned(),
+                 desc: desc.to_owned(),
                  hasarg: Yes,
                  occur: Multi};
      }
              row
          });
  
-         return str::to_owned(brief) +
+         return brief.to_owned() +
                 "\n\nOptions:\n" +
                 rows.collect::<~[~str]>().connect("\n") +
                 "\n\n";
index 48a685058bbd5ce96e2cce4fbffa725ad87a2770,4533aeebbcb37ef3927a0fd237acd8e523b406ea..7b4db63c6ed7a3b244469c6a4c9c76ff4147ef27
@@@ -8,7 -8,6 +8,6 @@@
  // option. This file may not be copied, modified, or distributed
  // except according to those terms.
  
- use std::str;
  use std::io;
  
  use driver::session::{OptLevel, No, Less, Aggressive};
@@@ -174,7 -173,7 +173,7 @@@ pub fn populate_pass_manager(sess: Sess
  }
  
  pub fn create_pass(name:&str) -> Option<PassRef> {
-     do str::as_c_str(name) |s| {
+     do name.as_c_str |s| {
          unsafe {
              let p = llvm::LLVMCreatePass(s);
              if p.is_null() {
@@@ -191,15 -190,15 +190,15 @@@ pub fn list_passes() 
  
      io::println("\nAnalysis Passes:");
      for analysis_passes.iter().advance |&(name, desc)| {
 -        io::println(fmt!("    %-30s -- %s", name, desc));
 +        printfln!("    %-30s -- %s", name, desc);
      }
      io::println("\nTransformation Passes:");
      for transform_passes.iter().advance |&(name, desc)| {
 -        io::println(fmt!("    %-30s -- %s", name, desc));
 +        printfln!("    %-30s -- %s", name, desc);
      }
      io::println("\nUtility Passes:");
      for utility_passes.iter().advance |&(name, desc)| {
 -        io::println(fmt!("    %-30s -- %s", name, desc));
 +        printfln!("    %-30s -- %s", name, desc);
      }
  }
  
@@@ -344,7 -343,7 +343,7 @@@ fn passes_exist() 
      if failed.len() > 0 {
          io::println("Some passes don't exist:");
          for failed.iter().advance |&n| {
 -            io::println(fmt!("    %s", n));
 +            printfln!("    %s", n);
          }
          fail!();
      }
index b76b76ff603d58066c9645ce2428f2de82f8ce96,903f36c4f8a71e49dc622f061ec7fa2de37f9fe4..9f302ee6676ff835c376504d284a7d4af3055adf
@@@ -21,11 -21,10 +21,10 @@@ use middle::ty
  
  use middle::trans::type_::Type;
  
- use std::str;
  use syntax::ast;
  
  // Take an inline assembly expression and splat it out via LLVM
 -pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
 +pub fn trans_inline_asm(bcx: @mut Block, ia: &ast::inline_asm) -> @mut Block {
  
      let mut bcx = bcx;
      let mut constraints = ~[];
          ast::asm_intel => lib::llvm::AD_Intel
      };
  
-     let r = do str::as_c_str(ia.asm) |a| {
-         do str::as_c_str(constraints) |c| {
+     let r = do ia.asm.as_c_str |a| {
+         do constraints.as_c_str |c| {
              InlineAsmCall(bcx, a, c, inputs, output, ia.volatile, ia.alignstack, dialect)
          }
      };
index fba67d57994e4d1b5fae91976dbc3008ce428021,9c3eeed5a344a0aedde62ab301a834f58c4623e8..d3ae69b23dae4e55b922af70052b9576d36eda0e
@@@ -70,7 -70,6 +70,6 @@@ use std::hashmap::{HashMap, HashSet}
  use std::int;
  use std::io;
  use std::libc::c_uint;
- use std::str;
  use std::uint;
  use std::vec;
  use std::local_data;
@@@ -131,7 -130,7 +130,7 @@@ pub fn push_ctxt(s: &'static str) -> _I
      _InsnCtxt { _x: () }
  }
  
 -fn fcx_has_nonzero_span(fcx: fn_ctxt) -> bool {
 +fn fcx_has_nonzero_span(fcx: &FunctionContext) -> bool {
      match fcx.span {
          None => true,
          Some(span) => *span.lo != 0 || *span.hi != 0
@@@ -228,13 -227,13 +227,13 @@@ pub fn get_extern_const(externs: &mut E
          return c;
      }
  }
 -pub fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
 +pub fn umax(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef {
      let _icx = push_ctxt("umax");
      let cond = ICmp(cx, lib::llvm::IntULT, a, b);
      return Select(cx, cond, b, a);
  }
  
 -pub fn umin(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
 +pub fn umin(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef {
      let _icx = push_ctxt("umin");
      let cond = ICmp(cx, lib::llvm::IntULT, a, b);
      return Select(cx, cond, a, b);
  // Given a pointer p, returns a pointer sz(p) (i.e., inc'd by sz bytes).
  // The type of the returned pointer is always i8*.  If you care about the
  // return type, use bump_ptr().
 -pub fn ptr_offs(bcx: block, base: ValueRef, sz: ValueRef) -> ValueRef {
 +pub fn ptr_offs(bcx: @mut Block, base: ValueRef, sz: ValueRef) -> ValueRef {
      let _icx = push_ctxt("ptr_offs");
      let raw = PointerCast(bcx, base, Type::i8p());
      InBoundsGEP(bcx, raw, [sz])
  
  // Increment a pointer by a given amount and then cast it to be a pointer
  // to a given type.
 -pub fn bump_ptr(bcx: block, t: ty::t, base: ValueRef, sz: ValueRef) ->
 +pub fn bump_ptr(bcx: @mut Block, t: ty::t, base: ValueRef, sz: ValueRef) ->
     ValueRef {
      let _icx = push_ctxt("bump_ptr");
      let ccx = bcx.ccx();
  // known.
  //
  // The runtime equivalent is box_body() in "rust_internal.h".
 -pub fn opaque_box_body(bcx: block,
 +pub fn opaque_box_body(bcx: @mut Block,
                         body_t: ty::t,
                         boxptr: ValueRef) -> ValueRef {
      let _icx = push_ctxt("opaque_box_body");
  
  // malloc_raw_dyn: allocates a box to contain a given type, but with a
  // potentially dynamic size.
 -pub fn malloc_raw_dyn(bcx: block,
 +pub fn malloc_raw_dyn(bcx: @mut Block,
                        t: ty::t,
                        heap: heap,
                        size: ValueRef) -> Result {
      let _icx = push_ctxt("malloc_raw");
      let ccx = bcx.ccx();
  
 -    fn require_alloc_fn(bcx: block, t: ty::t, it: LangItem) -> ast::def_id {
 +    fn require_alloc_fn(bcx: @mut Block, t: ty::t, it: LangItem) -> ast::def_id {
          let li = &bcx.tcx().lang_items;
          match li.require(it) {
              Ok(id) => id,
  // malloc_raw: expects an unboxed type and returns a pointer to
  // enough space for a box of that type.  This includes a rust_opaque_box
  // header.
 -pub fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> Result {
 +pub fn malloc_raw(bcx: @mut Block, t: ty::t, heap: heap) -> Result {
      let ty = type_of(bcx.ccx(), t);
      let size = llsize_of(bcx.ccx(), ty);
      malloc_raw_dyn(bcx, t, heap, size)
  }
  
  pub struct MallocResult {
 -    bcx: block,
 +    bcx: @mut Block,
      box: ValueRef,
      body: ValueRef
  }
  
  // malloc_general_dyn: usefully wraps malloc_raw_dyn; allocates a box,
  // and pulls out the body
 -pub fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
 +pub fn malloc_general_dyn(bcx: @mut Block, t: ty::t, heap: heap, size: ValueRef)
      -> MallocResult {
      assert!(heap != heap_exchange);
      let _icx = push_ctxt("malloc_general");
      MallocResult { bcx: bcx, box: llbox, body: body }
  }
  
 -pub fn malloc_general(bcx: block, t: ty::t, heap: heap) -> MallocResult {
 +pub fn malloc_general(bcx: @mut Block, t: ty::t, heap: heap) -> MallocResult {
      let ty = type_of(bcx.ccx(), t);
      assert!(heap != heap_exchange);
      malloc_general_dyn(bcx, t, heap, llsize_of(bcx.ccx(), ty))
  }
 -pub fn malloc_boxed(bcx: block, t: ty::t)
 +pub fn malloc_boxed(bcx: @mut Block, t: ty::t)
      -> MallocResult {
      malloc_general(bcx, t, heap_managed)
  }
  
 -pub fn heap_for_unique(bcx: block, t: ty::t) -> heap {
 +pub fn heap_for_unique(bcx: @mut Block, t: ty::t) -> heap {
      if ty::type_contents(bcx.tcx(), t).contains_managed() {
          heap_managed_unique
      } else {
      }
  }
  
 -pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
 +pub fn maybe_set_managed_unique_rc(bcx: @mut Block, bx: ValueRef, heap: heap) {
      assert!(heap != heap_exchange);
      if heap == heap_managed_unique {
          // In cases where we are looking at a unique-typed allocation in the
@@@ -549,11 -548,11 +548,11 @@@ pub fn get_res_dtor(ccx: @mut CrateCont
  // Structural comparison: a rather involved form of glue.
  pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
      if cx.sess.opts.save_temps {
-         let _: () = str::as_c_str(s, |buf| {
+         do s.as_c_str |buf| {
              unsafe {
                  llvm::LLVMSetValueName(v, buf)
              }
-         });
+         }
      }
  }
  
  pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, }
  
  // NB: This produces an i1, not a Rust bool (i8).
 -pub fn compare_scalar_types(cx: block,
 +pub fn compare_scalar_types(cx: @mut Block,
                              lhs: ValueRef,
                              rhs: ValueRef,
                              t: ty::t,
  
  
  // A helper function to do the actual comparison of scalar values.
 -pub fn compare_scalar_values(cx: block,
 +pub fn compare_scalar_values(cx: @mut Block,
                               lhs: ValueRef,
                               rhs: ValueRef,
                               nt: scalar_type,
                               op: ast::binop)
                            -> ValueRef {
      let _icx = push_ctxt("compare_scalar_values");
 -    fn die(cx: block) -> ! {
 +    fn die(cx: @mut Block) -> ! {
          cx.tcx().sess.bug("compare_scalar_values: must be a\
                             comparison operator");
      }
      }
  }
  
 -pub type val_and_ty_fn<'self> = &'self fn(block, ValueRef, ty::t) -> block;
 +pub type val_and_ty_fn<'self> = &'self fn(@mut Block, ValueRef, ty::t) -> @mut Block;
  
 -pub fn load_inbounds(cx: block, p: ValueRef, idxs: &[uint]) -> ValueRef {
 +pub fn load_inbounds(cx: @mut Block, p: ValueRef, idxs: &[uint]) -> ValueRef {
      return Load(cx, GEPi(cx, p, idxs));
  }
  
 -pub fn store_inbounds(cx: block, v: ValueRef, p: ValueRef, idxs: &[uint]) {
 +pub fn store_inbounds(cx: @mut Block, v: ValueRef, p: ValueRef, idxs: &[uint]) {
      Store(cx, v, GEPi(cx, p, idxs));
  }
  
  // Iterates through the elements of a structural type.
 -pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
 -                          f: val_and_ty_fn) -> block {
 +pub fn iter_structural_ty(cx: @mut Block, av: ValueRef, t: ty::t,
 +                          f: val_and_ty_fn) -> @mut Block {
      let _icx = push_ctxt("iter_structural_ty");
  
 -    fn iter_variant(cx: block, repr: &adt::Repr, av: ValueRef,
 +    fn iter_variant(cx: @mut Block, repr: &adt::Repr, av: ValueRef,
                      variant: @ty::VariantInfo,
 -                    tps: &[ty::t], f: val_and_ty_fn) -> block {
 +                    tps: &[ty::t], f: val_and_ty_fn) -> @mut Block {
          let _icx = push_ctxt("iter_variant");
          let tcx = cx.tcx();
          let mut cx = cx;
      return cx;
  }
  
 -pub fn cast_shift_expr_rhs(cx: block, op: ast::binop,
 +pub fn cast_shift_expr_rhs(cx: @mut Block, op: ast::binop,
                             lhs: ValueRef, rhs: ValueRef) -> ValueRef {
      cast_shift_rhs(op, lhs, rhs,
                     |a,b| Trunc(cx, a, b),
@@@ -798,8 -797,8 +797,8 @@@ pub fn cast_shift_rhs(op: ast::binop
      }
  }
  
 -pub fn fail_if_zero(cx: block, span: span, divrem: ast::binop,
 -                    rhs: ValueRef, rhs_t: ty::t) -> block {
 +pub fn fail_if_zero(cx: @mut Block, span: span, divrem: ast::binop,
 +                    rhs: ValueRef, rhs_t: ty::t) -> @mut Block {
      let text = if divrem == ast::div {
          @"attempted to divide by zero"
      } else {
      }
  }
  
 -pub fn null_env_ptr(bcx: block) -> ValueRef {
 +pub fn null_env_ptr(bcx: @mut Block) -> ValueRef {
      C_null(Type::opaque_box(bcx.ccx()).ptr_to())
  }
  
@@@ -844,8 -843,8 +843,8 @@@ pub fn trans_external_path(ccx: &mut Cr
      };
  }
  
 -pub fn invoke(bcx: block, llfn: ValueRef, llargs: ~[ValueRef])
 -           -> (ValueRef, block) {
 +pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef])
 +           -> (ValueRef, @mut Block) {
      let _icx = push_ctxt("invoke_");
      if bcx.unreachable {
          return (C_null(Type::i8()), bcx);
      }
  }
  
 -pub fn need_invoke(bcx: block) -> bool {
 +pub fn need_invoke(bcx: @mut Block) -> bool {
      if (bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0) {
          return false;
      }
      }
  }
  
 -pub fn have_cached_lpad(bcx: block) -> bool {
 +pub fn have_cached_lpad(bcx: @mut Block) -> bool {
      let mut res = false;
      do in_lpad_scope_cx(bcx) |inf| {
          match inf.landing_pad {
      return res;
  }
  
 -pub fn in_lpad_scope_cx(bcx: block, f: &fn(si: &mut scope_info)) {
 +pub fn in_lpad_scope_cx(bcx: @mut Block, f: &fn(si: &mut ScopeInfo)) {
      let mut bcx = bcx;
      let mut cur_scope = bcx.scope;
      loop {
      }
  }
  
 -pub fn get_landing_pad(bcx: block) -> BasicBlockRef {
 +pub fn get_landing_pad(bcx: @mut Block) -> BasicBlockRef {
      let _icx = push_ctxt("get_landing_pad");
  
      let mut cached = None;
      return pad_bcx.llbb;
  }
  
 -pub fn find_bcx_for_scope(bcx: block, scope_id: ast::node_id) -> block {
 +pub fn find_bcx_for_scope(bcx: @mut Block, scope_id: ast::node_id) -> @mut Block {
      let mut bcx_sid = bcx;
      let mut cur_scope = bcx_sid.scope;
      loop {
  }
  
  
 -pub fn do_spill(bcx: block, v: ValueRef, t: ty::t) -> ValueRef {
 +pub fn do_spill(bcx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
      if ty::type_is_bot(t) {
          return C_null(Type::i8p());
      }
  
  // Since this function does *not* root, it is the caller's responsibility to
  // ensure that the referent is pointed to by a root.
 -pub fn do_spill_noroot(cx: block, v: ValueRef) -> ValueRef {
 +pub fn do_spill_noroot(cx: @mut Block, v: ValueRef) -> ValueRef {
      let llptr = alloca(cx, val_ty(v), "");
      Store(cx, v, llptr);
      return llptr;
  }
  
 -pub fn spill_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
 +pub fn spill_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
      let _icx = push_ctxt("spill_if_immediate");
      if ty::type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); }
      return v;
  }
  
 -pub fn load_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
 +pub fn load_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
      let _icx = push_ctxt("load_if_immediate");
      if ty::type_is_immediate(cx.tcx(), t) { return Load(cx, v); }
      return v;
  }
  
 -pub fn trans_trace(bcx: block, sp_opt: Option<span>, trace_str: @str) {
 +pub fn trans_trace(bcx: @mut Block, sp_opt: Option<span>, trace_str: @str) {
      if !bcx.sess().trace() { return; }
      let _icx = push_ctxt("trans_trace");
      add_comment(bcx, trace_str);
      Call(bcx, ccx.upcalls.trace, args);
  }
  
 -pub fn ignore_lhs(_bcx: block, local: &ast::Local) -> bool {
 +pub fn ignore_lhs(_bcx: @mut Block, local: &ast::Local) -> bool {
      match local.pat.node {
          ast::pat_wild => true, _ => false
      }
  }
  
 -pub fn init_local(bcx: block, local: &ast::Local) -> block {
 +pub fn init_local(bcx: @mut Block, local: &ast::Local) -> @mut Block {
  
      debug!("init_local(bcx=%s, local.id=%?)",
             bcx.to_str(), local.id);
      _match::store_local(bcx, local.pat, local.init)
  }
  
 -pub fn trans_stmt(cx: block, s: &ast::stmt) -> block {
 +pub fn trans_stmt(cx: @mut Block, s: &ast::stmt) -> @mut Block {
      let _icx = push_ctxt("trans_stmt");
      debug!("trans_stmt(%s)", stmt_to_str(s, cx.tcx().sess.intr()));
  
  
  // You probably don't want to use this one. See the
  // next three functions instead.
 -pub fn new_block(cx: fn_ctxt, parent: Option<block>, scope: Option<@mut scope_info>,
 -                 is_lpad: bool, name: &str, opt_node_info: Option<NodeInfo>)
 -    -> block {
 -
 +pub fn new_block(cx: @mut FunctionContext,
 +                 parent: Option<@mut Block>,
 +                 scope: Option<@mut ScopeInfo>,
 +                 is_lpad: bool,
 +                 name: &str,
 +                 opt_node_info: Option<NodeInfo>)
 +              -> @mut Block {
      unsafe {
          let llbb = do name.as_c_str |buf| {
              llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf)
          };
 -        let bcx = mk_block(llbb,
 -                           parent,
 -                           is_lpad,
 -                           opt_node_info,
 -                           cx);
 +        let bcx = @mut Block::new(llbb,
 +                                  parent,
 +                                  is_lpad,
 +                                  opt_node_info,
 +                                  cx);
          bcx.scope = scope;
          for parent.iter().advance |cx| {
              if cx.unreachable {
      }
  }
  
 -pub fn simple_block_scope(parent: Option<@mut scope_info>,
 -                          node_info: Option<NodeInfo>) -> @mut scope_info {
 -    @mut scope_info {
 +pub fn simple_block_scope(parent: Option<@mut ScopeInfo>,
 +                          node_info: Option<NodeInfo>) -> @mut ScopeInfo {
 +    @mut ScopeInfo {
          parent: parent,
          loop_break: None,
          loop_label: None,
  }
  
  // Use this when you're at the top block of a function or the like.
 -pub fn top_scope_block(fcx: fn_ctxt, opt_node_info: Option<NodeInfo>)
 -                    -> block {
 +pub fn top_scope_block(fcx: @mut FunctionContext, opt_node_info: Option<NodeInfo>)
 +                    -> @mut Block {
      return new_block(fcx, None, Some(simple_block_scope(None, opt_node_info)), false,
                    "function top level", opt_node_info);
  }
  
 -pub fn scope_block(bcx: block,
 +pub fn scope_block(bcx: @mut Block,
                     opt_node_info: Option<NodeInfo>,
 -                   n: &str) -> block {
 +                   n: &str) -> @mut Block {
      return new_block(bcx.fcx, Some(bcx), Some(simple_block_scope(None, opt_node_info)), bcx.is_lpad,
                    n, opt_node_info);
  }
  
 -pub fn loop_scope_block(bcx: block,
 -                        loop_break: block,
 +pub fn loop_scope_block(bcx: @mut Block,
 +                        loop_break: @mut Block,
                          loop_label: Option<ident>,
                          n: &str,
 -                        opt_node_info: Option<NodeInfo>) -> block {
 -    return new_block(bcx.fcx, Some(bcx), Some(@mut scope_info {
 +                        opt_node_info: Option<NodeInfo>) -> @mut Block {
 +    return new_block(bcx.fcx, Some(bcx), Some(@mut ScopeInfo {
          parent: None,
          loop_break: Some(loop_break),
          loop_label: loop_label,
  }
  
  // Use this when creating a block for the inside of a landing pad.
 -pub fn lpad_block(bcx: block, n: &str) -> block {
 +pub fn lpad_block(bcx: @mut Block, n: &str) -> @mut Block {
      new_block(bcx.fcx, Some(bcx), None, true, n, None)
  }
  
  // Use this when you're making a general CFG BB within a scope.
 -pub fn sub_block(bcx: block, n: &str) -> block {
 +pub fn sub_block(bcx: @mut Block, n: &str) -> @mut Block {
      new_block(bcx.fcx, Some(bcx), None, bcx.is_lpad, n, None)
  }
  
 -pub fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
 -    mk_block(llbb, None, is_lpad, None, fcx)
 +pub fn raw_block(fcx: @mut FunctionContext, is_lpad: bool, llbb: BasicBlockRef) -> @mut Block {
 +    @mut Block::new(llbb, None, is_lpad, None, fcx)
  }
  
  
  // need to make sure those variables go out of scope when the block ends.  We
  // do that by running a 'cleanup' function for each variable.
  // trans_block_cleanups runs all the cleanup functions for the block.
 -pub fn trans_block_cleanups(bcx: block, cleanups: ~[cleanup]) -> block {
 +pub fn trans_block_cleanups(bcx: @mut Block, cleanups: ~[cleanup]) -> @mut Block {
      trans_block_cleanups_(bcx, cleanups, false)
  }
  
 -pub fn trans_block_cleanups_(bcx: block,
 +pub fn trans_block_cleanups_(bcx: @mut Block,
                               cleanups: &[cleanup],
                               /* cleanup_cx: block, */
 -                             is_lpad: bool) -> block {
 +                             is_lpad: bool) -> @mut Block {
      let _icx = push_ctxt("trans_block_cleanups");
      // NB: Don't short-circuit even if this block is unreachable because
      // GC-based cleanup needs to the see that the roots are live.
  // In the last argument, Some(block) mean jump to this block, and none means
  // this is a landing pad and leaving should be accomplished with a resume
  // instruction.
 -pub fn cleanup_and_leave(bcx: block,
 +pub fn cleanup_and_leave(bcx: @mut Block,
                           upto: Option<BasicBlockRef>,
                           leave: Option<BasicBlockRef>) {
      let _icx = push_ctxt("cleanup_and_leave");
      }
  }
  
 -pub fn cleanup_block(bcx: block, upto: Option<BasicBlockRef>) -> block{
 +pub fn cleanup_block(bcx: @mut Block, upto: Option<BasicBlockRef>) -> @mut Block{
      let _icx = push_ctxt("cleanup_block");
      let mut cur = bcx;
      let mut bcx = bcx;
      bcx
  }
  
 -pub fn cleanup_and_Br(bcx: block, upto: block, target: BasicBlockRef) {
 +pub fn cleanup_and_Br(bcx: @mut Block, upto: @mut Block, target: BasicBlockRef) {
      let _icx = push_ctxt("cleanup_and_Br");
      cleanup_and_leave(bcx, Some(upto.llbb), Some(target));
  }
  
 -pub fn leave_block(bcx: block, out_of: block) -> block {
 +pub fn leave_block(bcx: @mut Block, out_of: @mut Block) -> @mut Block {
      let _icx = push_ctxt("leave_block");
      let next_cx = sub_block(block_parent(out_of), "next");
      if bcx.unreachable { Unreachable(next_cx); }
      next_cx
  }
  
 -pub fn with_scope(bcx: block,
 +pub fn with_scope(bcx: @mut Block,
                    opt_node_info: Option<NodeInfo>,
                    name: &str,
 -                  f: &fn(block) -> block) -> block {
 +                  f: &fn(@mut Block) -> @mut Block) -> @mut Block {
      let _icx = push_ctxt("with_scope");
  
      debug!("with_scope(bcx=%s, opt_node_info=%?, name=%s)",
      ret
  }
  
 -pub fn with_scope_result(bcx: block,
 +pub fn with_scope_result(bcx: @mut Block,
                           opt_node_info: Option<NodeInfo>,
                           _name: &str,
 -                         f: &fn(block) -> Result) -> Result {
 +                         f: &fn(@mut Block) -> Result) -> Result {
      let _icx = push_ctxt("with_scope_result");
  
      let scope = simple_block_scope(bcx.scope, opt_node_info);
      rslt(out_bcx, val)
  }
  
 -pub fn with_scope_datumblock(bcx: block, opt_node_info: Option<NodeInfo>,
 -                             name: &str, f: &fn(block) -> datum::DatumBlock)
 +pub fn with_scope_datumblock(bcx: @mut Block, opt_node_info: Option<NodeInfo>,
 +                             name: &str, f: &fn(@mut Block) -> datum::DatumBlock)
                            -> datum::DatumBlock {
      use middle::trans::datum::DatumBlock;
  
@@@ -1463,7 -1459,7 +1462,7 @@@ pub fn block_locals(b: &ast::Block, it
      }
  }
  
 -pub fn with_cond(bcx: block, val: ValueRef, f: &fn(block) -> block) -> block {
 +pub fn with_cond(bcx: @mut Block, val: ValueRef, f: &fn(@mut Block) -> @mut Block) -> @mut Block {
      let _icx = push_ctxt("with_cond");
      let next_cx = base::sub_block(bcx, "next");
      let cond_cx = base::sub_block(bcx, "cond");
      next_cx
  }
  
 -pub fn call_memcpy(cx: block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
 +pub fn call_memcpy(cx: @mut Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
      let _icx = push_ctxt("call_memcpy");
      let ccx = cx.ccx();
      let key = match ccx.sess.targ_cfg.arch {
      Call(cx, memcpy, [dst_ptr, src_ptr, size, align, volatile]);
  }
  
 -pub fn memcpy_ty(bcx: block, dst: ValueRef, src: ValueRef, t: ty::t) {
 +pub fn memcpy_ty(bcx: @mut Block, dst: ValueRef, src: ValueRef, t: ty::t) {
      let _icx = push_ctxt("memcpy_ty");
      let ccx = bcx.ccx();
      if ty::type_is_structural(t) {
      }
  }
  
 -pub fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) {
 +pub fn zero_mem(cx: @mut Block, llptr: ValueRef, t: ty::t) {
      if cx.unreachable { return; }
      let _icx = push_ctxt("zero_mem");
      let bcx = cx;
@@@ -1534,7 -1530,7 +1533,7 @@@ pub fn memzero(b: &Builder, llptr: Valu
      b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile]);
  }
  
 -pub fn alloc_ty(bcx: block, t: ty::t, name: &str) -> ValueRef {
 +pub fn alloc_ty(bcx: @mut Block, t: ty::t, name: &str) -> ValueRef {
      let _icx = push_ctxt("alloc_ty");
      let ccx = bcx.ccx();
      let ty = type_of::type_of(ccx, t);
      return val;
  }
  
 -pub fn alloca(cx: block, ty: Type, name: &str) -> ValueRef {
 +pub fn alloca(cx: @mut Block, ty: Type, name: &str) -> ValueRef {
      alloca_maybe_zeroed(cx, ty, name, false)
  }
  
 -pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> ValueRef {
 +pub fn alloca_maybe_zeroed(cx: @mut Block, ty: Type, name: &str, zero: bool) -> ValueRef {
      let _icx = push_ctxt("alloca");
      if cx.unreachable {
          unsafe {
      p
  }
  
 -pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
 +pub fn arrayalloca(cx: @mut Block, ty: Type, v: ValueRef) -> ValueRef {
      let _icx = push_ctxt("arrayalloca");
      if cx.unreachable {
          unsafe {
@@@ -1580,22 -1576,24 +1579,24 @@@ pub struct BasicBlocks 
  pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
      unsafe {
          let cx = task_llcx();
-         str::as_c_str("static_allocas",
-                       |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
+         do "static_allocas".as_c_str | buf| {
+             llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
+         }
      }
  }
  
  pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
      unsafe {
          let cx = task_llcx();
-         str::as_c_str("return",
-                       |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
+         do "return".as_c_str |buf| {
+             llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
+         }
      }
  }
  
  // Creates and returns space for, or returns the argument representing, the
  // slot where the return value of the function must go.
 -pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
 +pub fn make_return_pointer(fcx: @mut FunctionContext, output_type: ty::t) -> ValueRef {
      unsafe {
          if !ty::type_is_immediate(fcx.ccx.tcx, output_type) {
              llvm::LLVMGetParam(fcx.llfn, 0)
@@@ -1622,7 -1620,7 +1623,7 @@@ pub fn new_fn_ctxt_w_id(ccx: @mut Crate
                          param_substs: Option<@param_substs>,
                          opt_node_info: Option<NodeInfo>,
                          sp: Option<span>)
 -                     -> fn_ctxt {
 +                     -> @mut FunctionContext {
      for param_substs.iter().advance |p| { p.validate(); }
  
      debug!("new_fn_ctxt_w_id(path=%s, id=%?, \
          }
      };
      let is_immediate = ty::type_is_immediate(ccx.tcx, substd_output_type);
 -    let fcx = @mut fn_ctxt_ {
 +    let fcx = @mut FunctionContext {
            llfn: llfndecl,
            llenv: unsafe {
                llvm::LLVMGetUndef(Type::i8p().to_ref())
@@@ -1683,7 -1681,7 +1684,7 @@@ pub fn new_fn_ctxt(ccx: @mut CrateConte
                     llfndecl: ValueRef,
                     output_type: ty::t,
                     sp: Option<span>)
 -                -> fn_ctxt {
 +                -> @mut FunctionContext {
      new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, None, sp)
  }
  
  // spaces that have been created for them (by code in the llallocas field of
  // the function's fn_ctxt).  create_llargs_for_fn_args populates the llargs
  // field of the fn_ctxt with
 -pub fn create_llargs_for_fn_args(cx: fn_ctxt,
 +pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
                                   self_arg: self_arg,
                                   args: &[ast::arg])
                                -> ~[ValueRef] {
      })
  }
  
 -pub fn copy_args_to_allocas(fcx: fn_ctxt,
 -                            bcx: block,
 +pub fn copy_args_to_allocas(fcx: @mut FunctionContext,
 +                            bcx: @mut Block,
                              args: &[ast::arg],
                              raw_llargs: &[ValueRef],
 -                            arg_tys: &[ty::t]) -> block {
 +                            arg_tys: &[ty::t]) -> @mut Block {
      let _icx = push_ctxt("copy_args_to_allocas");
      let mut bcx = bcx;
  
  
  // Ties up the llstaticallocas -> llloadenv -> lltop edges,
  // and builds the return block.
 -pub fn finish_fn(fcx: fn_ctxt, last_bcx: block) {
 +pub fn finish_fn(fcx: @mut FunctionContext, last_bcx: @mut Block) {
      let _icx = push_ctxt("finish_fn");
  
      let ret_cx = match fcx.llreturn {
  }
  
  // Builds the return block for a function.
 -pub fn build_return_block(fcx: fn_ctxt, ret_cx: block) {
 +pub fn build_return_block(fcx: &FunctionContext, ret_cx: @mut Block) {
      // Return the value if this function immediate; otherwise, return void.
      if fcx.llretptr.is_some() && fcx.has_immediate_return_value {
          Ret(ret_cx, Load(ret_cx, fcx.llretptr.get()))
@@@ -1840,8 -1838,8 +1841,8 @@@ pub fn trans_closure(ccx: @mut CrateCon
                       id: ast::node_id,
                       attributes: &[ast::Attribute],
                       output_type: ty::t,
 -                     maybe_load_env: &fn(fn_ctxt),
 -                     finish: &fn(block)) {
 +                     maybe_load_env: &fn(@mut FunctionContext),
 +                     finish: &fn(@mut Block)) {
      ccx.stats.n_closures += 1;
      let _icx = push_ctxt("trans_closure");
      set_uwtable(llfndecl);
@@@ -1947,7 -1945,7 +1948,7 @@@ pub fn trans_fn(ccx: @mut CrateContext
                    |_bcx| { });
  }
  
 -fn insert_synthetic_type_entries(bcx: block,
 +fn insert_synthetic_type_entries(bcx: @mut Block,
                                   fn_args: &[ast::arg],
                                   arg_tys: &[ty::t])
  {
@@@ -2356,11 -2354,11 +2357,11 @@@ pub fn create_entry_wrapper(ccx: @mut C
              };
              decl_cdecl_fn(ccx.llmod, main_name, llfty)
          };
-         let llbb = str::as_c_str("top", |buf| {
+         let llbb = do "top".as_c_str |buf| {
              unsafe {
                  llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
              }
-         });
+         };
          let bld = ccx.builder.B;
          unsafe {
              llvm::LLVMPositionBuilderAtEnd(bld, llbb);
      }
  }
  
 -pub fn fill_fn_pair(bcx: block, pair: ValueRef, llfn: ValueRef,
 +pub fn fill_fn_pair(bcx: @mut Block, pair: ValueRef, llfn: ValueRef,
                      llenvptr: ValueRef) {
      let ccx = bcx.ccx();
      let code_cell = GEPi(bcx, pair, [0u, abi::fn_field_code]);
@@@ -2449,7 -2447,7 +2450,7 @@@ pub fn get_item_val(ccx: @mut CrateCont
          let val = match item {
            ast_map::node_item(i, pth) => {
              let my_path = vec::append((*pth).clone(), [path_name(i.ident)]);
 -            match i.node {
 +            let v = match i.node {
                ast::item_static(_, m, expr) => {
                  let typ = ty::node_id_to_type(ccx.tcx, i.id);
                  let s = mangle_exported_name(ccx, my_path, typ);
                  exprt = m == ast::m_mutbl;
                  unsafe {
                      let llty = llvm::LLVMTypeOf(v);
-                     let g = str::as_c_str(s, |buf| {
+                     let g = do s.as_c_str |buf| {
                          llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
-                     });
+                     };
                      ccx.item_symbols.insert(i.id, s);
                      g
                  }
                  llfn
                }
                _ => fail!("get_item_val: weird result in table")
 +            };
 +            match (attr::first_attr_value_str_by_name(i.attrs, "link_section")) {
 +                Some(sect) => unsafe {
 +                    do sect.as_c_str |buf| {
 +                        llvm::LLVMSetSection(v, buf);
 +                    }
 +                },
 +                None => ()
              }
 +            v
            }
            ast_map::node_trait_method(trait_method, _, pth) => {
              debug!("get_item_val(): processing a node_trait_method");
                  ast::foreign_item_static(*) => {
                      let typ = ty::node_id_to_type(ccx.tcx, ni.id);
                      let ident = token::ident_to_str(&ni.ident);
-                     let g = do str::as_c_str(ident) |buf| {
+                     let g = do ident.as_c_str |buf| {
                          unsafe {
                              let ty = type_of(ccx, typ);
                              llvm::LLVMAddGlobal(ccx.llmod, ty.to_ref(), buf)
@@@ -2621,11 -2610,11 +2622,11 @@@ pub fn trans_constant(ccx: &mut CrateCo
              let s = mangle_exported_name(ccx, p, ty::mk_int()).to_managed();
              let disr_val = vi[i].disr_val;
              note_unique_llvm_symbol(ccx, s);
-             let discrim_gvar = str::as_c_str(s, |buf| {
+             let discrim_gvar = do s.as_c_str |buf| {
                  unsafe {
                      llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
                  }
-             });
+             };
              unsafe {
                  llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, disr_val));
                  llvm::LLVMSetGlobalConstant(discrim_gvar, True);
@@@ -2649,7 -2638,7 +2650,7 @@@ pub fn trans_constants(ccx: @mut CrateC
          })));
  }
  
 -pub fn vp2i(cx: block, v: ValueRef) -> ValueRef {
 +pub fn vp2i(cx: @mut Block, v: ValueRef) -> ValueRef {
      let ccx = cx.ccx();
      return PtrToInt(cx, v, ccx.int_type);
  }
@@@ -2749,7 -2738,7 +2750,7 @@@ pub fn declare_dbg_intrinsics(llmod: Mo
      ifn!("llvm.dbg.value",   [Type::metadata(), Type::i64(), Type::metadata()], Type::void());
  }
  
 -pub fn trap(bcx: block) {
 +pub fn trap(bcx: @mut Block) {
      match bcx.ccx().intrinsics.find_equiv(& &"llvm.trap") {
        Some(&x) => { Call(bcx, x, []); },
        _ => bcx.sess().bug("unbound llvm.trap in trap")
@@@ -2762,7 -2751,7 +2763,7 @@@ pub fn decl_gc_metadata(ccx: &mut Crate
      }
  
      let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id;
-     let gc_metadata = do str::as_c_str(gc_metadata_name) |buf| {
+     let gc_metadata = do gc_metadata_name.as_c_str |buf| {
          unsafe {
              llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
          }
@@@ -2825,11 -2814,11 +2826,11 @@@ pub fn decl_crate_map(sess: session::Se
      let sym_name = ~"_rust_crate_map_" + mapname;
      let arrtype = Type::array(&int_type, n_subcrates as u64);
      let maptype = Type::struct_([Type::i32(), Type::i8p(), int_type, arrtype], false);
-     let map = str::as_c_str(sym_name, |buf| {
+     let map = do sym_name.as_c_str |buf| {
          unsafe {
              llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
          }
-     });
+     };
      lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage);
      return map;
  }
@@@ -2844,11 -2833,11 +2845,11 @@@ pub fn fill_crate_map(ccx: @mut CrateCo
                        cdata.name,
                        cstore::get_crate_vers(cstore, i),
                        cstore::get_crate_hash(cstore, i));
-         let cr = str::as_c_str(nm, |buf| {
+         let cr = do nm.as_c_str |buf| {
              unsafe {
                  llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
              }
-         });
+         };
          subcrates.push(p2i(ccx, cr));
          i += 1;
      }
@@@ -2907,16 -2896,16 +2908,16 @@@ pub fn write_metadata(cx: &mut CrateCon
      let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
      let llmeta = C_bytes(encoder::encode_metadata(encode_parms, crate));
      let llconst = C_struct([llmeta]);
-     let mut llglobal = str::as_c_str("rust_metadata", |buf| {
+     let mut llglobal = do "rust_metadata".as_c_str |buf| {
          unsafe {
              llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst).to_ref(), buf)
          }
-     });
+     };
      unsafe {
          llvm::LLVMSetInitializer(llglobal, llconst);
-         str::as_c_str(cx.sess.targ_cfg.target_strs.meta_sect_name, |buf| {
+         do cx.sess.targ_cfg.target_strs.meta_sect_name.as_c_str |buf| {
              llvm::LLVMSetSection(llglobal, buf)
-         });
+         };
          lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
  
          let t_ptr_i8 = Type::i8p();
@@@ -2935,7 -2924,7 +2936,7 @@@ fn mk_global(ccx: &CrateContext
               internal: bool)
            -> ValueRef {
      unsafe {
-         let llglobal = do str::as_c_str(name) |buf| {
+         let llglobal = do name.as_c_str |buf| {
              llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval).to_ref(), buf)
          };
          llvm::LLVMSetInitializer(llglobal, llval);
@@@ -3011,15 -3000,17 +3012,15 @@@ pub fn trans_crate(sess: session::Sessi
      write_metadata(ccx, crate);
      if ccx.sess.trans_stats() {
          io::println("--- trans stats ---");
 -        io::println(fmt!("n_static_tydescs: %u",
 -                         ccx.stats.n_static_tydescs));
 -        io::println(fmt!("n_glues_created: %u",
 -                         ccx.stats.n_glues_created));
 -        io::println(fmt!("n_null_glues: %u", ccx.stats.n_null_glues));
 -        io::println(fmt!("n_real_glues: %u", ccx.stats.n_real_glues));
 -
 -        io::println(fmt!("n_fns: %u", ccx.stats.n_fns));
 -        io::println(fmt!("n_monos: %u", ccx.stats.n_monos));
 -        io::println(fmt!("n_inlines: %u", ccx.stats.n_inlines));
 -        io::println(fmt!("n_closures: %u", ccx.stats.n_closures));
 +        printfln!("n_static_tydescs: %u", ccx.stats.n_static_tydescs);
 +        printfln!("n_glues_created: %u", ccx.stats.n_glues_created);
 +        printfln!("n_null_glues: %u", ccx.stats.n_null_glues);
 +        printfln!("n_real_glues: %u", ccx.stats.n_real_glues);
 +
 +        printfln!("n_fns: %u", ccx.stats.n_fns);
 +        printfln!("n_monos: %u", ccx.stats.n_monos);
 +        printfln!("n_inlines: %u", ccx.stats.n_inlines);
 +        printfln!("n_closures: %u", ccx.stats.n_closures);
          io::println("fn stats:");
          do sort::quick_sort(ccx.stats.fn_stats) |&(_, _, insns_a), &(_, _, insns_b)| {
              insns_a > insns_b
          for ccx.stats.fn_stats.iter().advance |tuple| {
              match *tuple {
                  (ref name, ms, insns) => {
 -                    io::println(fmt!("%u insns, %u ms, %s", insns, ms, *name));
 +                    printfln!("%u insns, %u ms, %s", insns, ms, *name);
                  }
              }
          }
      }
      if ccx.sess.count_llvm_insns() {
          for ccx.stats.llvm_insns.iter().advance |(k, v)| {
 -            io::println(fmt!("%-7u %s", *v, *k));
 +            printfln!("%-7u %s", *v, *k);
          }
      }
  
index fef6607bbed8e925eeda2f00c3c9ac6ad69089d1,60c2bad4a65cb20fda08addaaec4a85fd8e123ce..713939a5d83192da1d1ff5488c51aea1d81472a2
@@@ -157,7 -157,7 +157,7 @@@ impl Repr for param_substs 
  
  // Function context.  Every LLVM function we create will have one of
  // these.
 -pub struct fn_ctxt_ {
 +pub struct FunctionContext {
      // The ValueRef returned from a call to llvm::LLVMAddFunction; the
      // address of the first instruction in the sequence of
      // instructions for this function that will go in the .text
      // always be Some.
      llretptr: Option<ValueRef>,
  
 -    entry_bcx: Option<block>,
 +    entry_bcx: Option<@mut Block>,
  
      // These elements: "hoisted basic blocks" containing
      // administrative activities that have to happen in only one place in
      ccx: @mut CrateContext
  }
  
 -impl fn_ctxt_ {
 +impl FunctionContext {
      pub fn arg_pos(&self, arg: uint) -> uint {
          if self.has_immediate_return_value {
              arg + 1u
      }
  }
  
 -pub type fn_ctxt = @mut fn_ctxt_;
 -
  pub fn warn_not_to_commit(ccx: &mut CrateContext, msg: &str) {
      if !ccx.do_not_commit_warning_issued {
          ccx.do_not_commit_warning_issued = true;
@@@ -289,8 -291,8 +289,8 @@@ pub enum cleantype 
  }
  
  pub enum cleanup {
 -    clean(@fn(block) -> block, cleantype),
 -    clean_temp(ValueRef, @fn(block) -> block, cleantype),
 +    clean(@fn(@mut Block) -> @mut Block, cleantype),
 +    clean_temp(ValueRef, @fn(@mut Block) -> @mut Block, cleantype),
  }
  
  // Can't use deriving(Clone) because of the managed closure.
@@@ -312,13 -314,13 +312,13 @@@ pub struct cleanup_path 
      dest: BasicBlockRef
  }
  
 -pub fn shrink_scope_clean(scope_info: &mut scope_info, size: uint) {
 +pub fn shrink_scope_clean(scope_info: &mut ScopeInfo, size: uint) {
      scope_info.landing_pad = None;
      scope_info.cleanup_paths = scope_info.cleanup_paths.iter()
              .take_while(|&cu| cu.size <= size).transform(|&x|x).collect();
  }
  
 -pub fn grow_scope_clean(scope_info: &mut scope_info) {
 +pub fn grow_scope_clean(scope_info: &mut ScopeInfo) {
      scope_info.landing_pad = None;
  }
  
@@@ -330,7 -332,7 +330,7 @@@ pub fn cleanup_type(cx: ty::ctxt, ty: t
      }
  }
  
 -pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
 +pub fn add_clean(bcx: @mut Block, val: ValueRef, t: ty::t) {
      if !ty::type_needs_drop(bcx.tcx(), t) { return; }
  
      debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
      }
  }
  
 -pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) {
 +pub fn add_clean_temp_immediate(cx: @mut Block, val: ValueRef, ty: ty::t) {
      if !ty::type_needs_drop(cx.tcx(), ty) { return; }
      debug!("add_clean_temp_immediate(%s, %s, %s)",
             cx.to_str(), cx.val_to_str(val),
      }
  }
  
 -pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
 +pub fn add_clean_temp_mem(bcx: @mut Block, val: ValueRef, t: ty::t) {
      add_clean_temp_mem_in_scope_(bcx, None, val, t);
  }
  
 -pub fn add_clean_temp_mem_in_scope(bcx: block, scope_id: ast::node_id, val: ValueRef, t: ty::t) {
 +pub fn add_clean_temp_mem_in_scope(bcx: @mut Block,
 +                                   scope_id: ast::node_id,
 +                                   val: ValueRef,
 +                                   t: ty::t) {
      add_clean_temp_mem_in_scope_(bcx, Some(scope_id), val, t);
  }
  
 -pub fn add_clean_temp_mem_in_scope_(bcx: block, scope_id: Option<ast::node_id>,
 +pub fn add_clean_temp_mem_in_scope_(bcx: @mut Block, scope_id: Option<ast::node_id>,
                                      val: ValueRef, t: ty::t) {
      if !ty::type_needs_drop(bcx.tcx(), t) { return; }
      debug!("add_clean_temp_mem(%s, %s, %s)",
          grow_scope_clean(scope_info);
      }
  }
 -pub fn add_clean_return_to_mut(bcx: block,
 +pub fn add_clean_return_to_mut(bcx: @mut Block,
                                 scope_id: ast::node_id,
                                 root_key: root_map_key,
                                 frozen_val_ref: ValueRef,
          grow_scope_clean(scope_info);
      }
  }
 -pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
 +pub fn add_clean_free(cx: @mut Block, ptr: ValueRef, heap: heap) {
      let free_fn = match heap {
        heap_managed | heap_managed_unique => {
 -        let f: @fn(block) -> block = |a| glue::trans_free(a, ptr);
 +        let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_free(a, ptr);
          f
        }
        heap_exchange | heap_exchange_closure => {
 -        let f: @fn(block) -> block = |a| glue::trans_exchange_free(a, ptr);
 +        let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_exchange_free(a, ptr);
          f
        }
      };
  // to a system where we can also cancel the cleanup on local variables, but
  // this will be more involved. For now, we simply zero out the local, and the
  // drop glue checks whether it is zero.
 -pub fn revoke_clean(cx: block, val: ValueRef) {
 +pub fn revoke_clean(cx: @mut Block, val: ValueRef) {
      do in_scope_cx(cx, None) |scope_info| {
          let cleanup_pos = scope_info.cleanups.iter().position(
              |cu| match *cu {
      }
  }
  
 -pub fn block_cleanups(bcx: block) -> ~[cleanup] {
 +pub fn block_cleanups(bcx: @mut Block) -> ~[cleanup] {
      match bcx.scope {
         None  => ~[],
         Some(inf) => inf.cleanups.clone(),
      }
  }
  
 -pub struct scope_info {
 -    parent: Option<@mut scope_info>,
 -    loop_break: Option<block>,
 +pub struct ScopeInfo {
 +    parent: Option<@mut ScopeInfo>,
 +    loop_break: Option<@mut Block>,
      loop_label: Option<ident>,
      // A list of functions that must be run at when leaving this
      // block, cleaning up any variables that were introduced in the
      node_info: Option<NodeInfo>,
  }
  
 -impl scope_info {
 +impl ScopeInfo {
      pub fn empty_cleanups(&mut self) -> bool {
          self.cleanups.is_empty()
      }
@@@ -514,7 -513,7 +514,7 @@@ pub struct NodeInfo 
  // code.  Each basic block we generate is attached to a function, typically
  // with many basic blocks per function.  All the basic blocks attached to a
  // function are organized as a directed graph.
 -pub struct block_ {
 +pub struct Block {
      // The BasicBlockRef returned from a call to
      // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
      // block to the function pointed to by llfn.  We insert
      llbb: BasicBlockRef,
      terminated: bool,
      unreachable: bool,
 -    parent: Option<block>,
 +    parent: Option<@mut Block>,
      // The current scope within this basic block
 -    scope: Option<@mut scope_info>,
 +    scope: Option<@mut ScopeInfo>,
      // Is this block part of a landing pad?
      is_lpad: bool,
      // info about the AST node this block originated from, if any
      node_info: Option<NodeInfo>,
      // The function context for the function to which this block is
      // attached.
 -    fcx: fn_ctxt
 -}
 +    fcx: @mut FunctionContext
 +}
 +
 +impl Block {
 +
 +    pub fn new(llbb: BasicBlockRef,
 +               parent: Option<@mut Block>,
 +               is_lpad: bool,
 +               node_info: Option<NodeInfo>,
 +               fcx: @mut FunctionContext)
 +            -> Block {
 +        Block {
 +            llbb: llbb,
 +            terminated: false,
 +            unreachable: false,
 +            parent: parent,
 +            scope: None,
 +            is_lpad: is_lpad,
 +            node_info: node_info,
 +            fcx: fcx
 +        }
 +    }
 +
 +    pub fn ccx(&self) -> @mut CrateContext { self.fcx.ccx }
 +    pub fn tcx(&self) -> ty::ctxt { self.fcx.ccx.tcx }
 +    pub fn sess(&self) -> Session { self.fcx.ccx.sess }
  
 -pub fn block_(llbb: BasicBlockRef, parent: Option<block>,
 -              is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
 -    -> block_ {
 +    pub fn ident(&self, ident: ident) -> @str {
 +        token::ident_to_str(&ident)
 +    }
  
 -    block_ {
 -        llbb: llbb,
 -        terminated: false,
 -        unreachable: false,
 -        parent: parent,
 -        scope: None,
 -        is_lpad: is_lpad,
 -        node_info: node_info,
 -        fcx: fcx
 +    pub fn node_id_to_str(&self, id: ast::node_id) -> ~str {
 +        ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr())
 +    }
 +
 +    pub fn expr_to_str(&self, e: @ast::expr) -> ~str {
 +        e.repr(self.tcx())
 +    }
 +
 +    pub fn expr_is_lval(&self, e: &ast::expr) -> bool {
 +        ty::expr_is_lval(self.tcx(), self.ccx().maps.method_map, e)
 +    }
 +
 +    pub fn expr_kind(&self, e: &ast::expr) -> ty::ExprKind {
 +        ty::expr_kind(self.tcx(), self.ccx().maps.method_map, e)
 +    }
 +
 +    pub fn def(&self, nid: ast::node_id) -> ast::def {
 +        match self.tcx().def_map.find(&nid) {
 +            Some(&v) => v,
 +            None => {
 +                self.tcx().sess.bug(fmt!(
 +                    "No def associated with node id %?", nid));
 +            }
 +        }
 +    }
 +
 +    pub fn val_to_str(&self, val: ValueRef) -> ~str {
 +        self.ccx().tn.val_to_str(val)
 +    }
 +
 +    pub fn llty_str(&self, ty: Type) -> ~str {
 +        self.ccx().tn.type_to_str(ty)
      }
 -}
  
 -pub type block = @mut block_;
 +    pub fn ty_to_str(&self, t: ty::t) -> ~str {
 +        t.repr(self.tcx())
 +    }
  
 -pub fn mk_block(llbb: BasicBlockRef, parent: Option<block>,
 -            is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
 -    -> block {
 -    @mut block_(llbb, parent, is_lpad, node_info, fcx)
 +    pub fn to_str(&self) -> ~str {
 +        unsafe {
 +            match self.node_info {
 +                Some(node_info) => fmt!("[block %d]", node_info.id),
 +                None => fmt!("[block %x]", transmute(&*self)),
 +            }
 +        }
 +    }
  }
  
  pub struct Result {
 -    bcx: block,
 +    bcx: @mut Block,
      val: ValueRef
  }
  
 -pub fn rslt(bcx: block, val: ValueRef) -> Result {
 +pub fn rslt(bcx: @mut Block, val: ValueRef) -> Result {
      Result {bcx: bcx, val: val}
  }
  
  impl Result {
 -    pub fn unpack(&self, bcx: &mut block) -> ValueRef {
 +    pub fn unpack(&self, bcx: &mut @mut Block) -> ValueRef {
          *bcx = self.bcx;
          return self.val;
      }
@@@ -633,7 -580,7 +633,7 @@@ pub fn val_ty(v: ValueRef) -> Type 
      }
  }
  
 -pub fn in_scope_cx(cx: block, scope_id: Option<ast::node_id>, f: &fn(si: &mut scope_info)) {
 +pub fn in_scope_cx(cx: @mut Block, scope_id: Option<ast::node_id>, f: &fn(si: &mut ScopeInfo)) {
      let mut cur = cx;
      let mut cur_scope = cur.scope;
      loop {
      }
  }
  
 -pub fn block_parent(cx: block) -> block {
 +pub fn block_parent(cx: @mut Block) -> @mut Block {
      match cx.parent {
        Some(b) => b,
        None    => cx.sess().bug(fmt!("block_parent called on root block %?",
      }
  }
  
 -// Accessors
 -
 -impl block_ {
 -    pub fn ccx(&self) -> @mut CrateContext { self.fcx.ccx }
 -    pub fn tcx(&self) -> ty::ctxt { self.fcx.ccx.tcx }
 -    pub fn sess(&self) -> Session { self.fcx.ccx.sess }
 -
 -    pub fn ident(&self, ident: ident) -> @str {
 -        token::ident_to_str(&ident)
 -    }
 -
 -    pub fn node_id_to_str(&self, id: ast::node_id) -> ~str {
 -        ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr())
 -    }
 -
 -    pub fn expr_to_str(&self, e: @ast::expr) -> ~str {
 -        e.repr(self.tcx())
 -    }
 -
 -    pub fn expr_is_lval(&self, e: &ast::expr) -> bool {
 -        ty::expr_is_lval(self.tcx(), self.ccx().maps.method_map, e)
 -    }
 -
 -    pub fn expr_kind(&self, e: &ast::expr) -> ty::ExprKind {
 -        ty::expr_kind(self.tcx(), self.ccx().maps.method_map, e)
 -    }
 -
 -    pub fn def(&self, nid: ast::node_id) -> ast::def {
 -        match self.tcx().def_map.find(&nid) {
 -            Some(&v) => v,
 -            None => {
 -                self.tcx().sess.bug(fmt!(
 -                    "No def associated with node id %?", nid));
 -            }
 -        }
 -    }
 -
 -    pub fn val_to_str(&self, val: ValueRef) -> ~str {
 -        self.ccx().tn.val_to_str(val)
 -    }
 -
 -    pub fn llty_str(&self, ty: Type) -> ~str {
 -        self.ccx().tn.type_to_str(ty)
 -    }
 -
 -    pub fn ty_to_str(&self, t: ty::t) -> ~str {
 -        t.repr(self.tcx())
 -    }
 -
 -    pub fn to_str(&self) -> ~str {
 -        unsafe {
 -            match self.node_info {
 -                Some(node_info) => fmt!("[block %d]", node_info.id),
 -                None => fmt!("[block %x]", transmute(&*self)),
 -            }
 -        }
 -    }
 -}
  
  // Let T be the content of a box @T.  tuplify_box_ty(t) returns the
  // representation of @T as a tuple (i.e., the ty::t version of what T_box()
@@@ -783,15 -788,6 +783,6 @@@ pub fn C_estr_slice(cx: &mut CrateConte
      }
  }
  
- // Returns a Plain Old LLVM String:
- pub fn C_postr(s: &str) -> ValueRef {
-     unsafe {
-         do s.as_c_str |buf| {
-             llvm::LLVMConstStringInContext(base::task_llcx(), buf, s.len() as c_uint, False)
-         }
-     }
- }
  pub fn C_zero_byte_arr(size: uint) -> ValueRef {
      unsafe {
          let mut i = 0u;
@@@ -839,14 -835,6 +830,6 @@@ pub fn C_bytes(bytes: &[u8]) -> ValueRe
      }
  }
  
- pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef {
-     unsafe {
-         return llvm::LLVMConstStringInContext(base::task_llcx(),
-             cast::transmute(vec::raw::to_ptr(bytes)),
-             bytes.len() as c_uint, False);
-     }
- }
  pub fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
      unsafe {
          llvm::LLVMGetParam(fndecl, param as c_uint)
@@@ -935,17 -923,17 +918,17 @@@ pub struct mono_id_ 
  
  pub type mono_id = @mono_id_;
  
 -pub fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
 +pub fn umax(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef {
      let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
      return build::Select(cx, cond, b, a);
  }
  
 -pub fn umin(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
 +pub fn umin(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef {
      let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
      return build::Select(cx, cond, a, b);
  }
  
 -pub fn align_to(cx: block, off: ValueRef, align: ValueRef) -> ValueRef {
 +pub fn align_to(cx: @mut Block, off: ValueRef, align: ValueRef) -> ValueRef {
      let mask = build::Sub(cx, align, C_int(cx.ccx(), 1));
      let bumped = build::Add(cx, off, mask);
      return build::And(cx, bumped, build::Not(cx, mask));
@@@ -969,7 -957,7 +952,7 @@@ pub fn path_str(sess: session::Session
      r
  }
  
 -pub fn monomorphize_type(bcx: block, t: ty::t) -> ty::t {
 +pub fn monomorphize_type(bcx: @mut Block, t: ty::t) -> ty::t {
      match bcx.fcx.param_substs {
          Some(substs) => {
              ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t)
      }
  }
  
 -pub fn node_id_type(bcx: block, id: ast::node_id) -> ty::t {
 +pub fn node_id_type(bcx: @mut Block, id: ast::node_id) -> ty::t {
      let tcx = bcx.tcx();
      let t = ty::node_id_to_type(tcx, id);
      monomorphize_type(bcx, t)
  }
  
 -pub fn expr_ty(bcx: block, ex: &ast::expr) -> ty::t {
 +pub fn expr_ty(bcx: @mut Block, ex: &ast::expr) -> ty::t {
      node_id_type(bcx, ex.id)
  }
  
 -pub fn expr_ty_adjusted(bcx: block, ex: &ast::expr) -> ty::t {
 +pub fn expr_ty_adjusted(bcx: @mut Block, ex: &ast::expr) -> ty::t {
      let tcx = bcx.tcx();
      let t = ty::expr_ty_adjusted(tcx, ex);
      monomorphize_type(bcx, t)
  }
  
 -pub fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] {
 +pub fn node_id_type_params(bcx: @mut Block, id: ast::node_id) -> ~[ty::t] {
      let tcx = bcx.tcx();
      let params = ty::node_id_to_type_params(tcx, id);
  
      }
  }
  
 -pub fn node_vtables(bcx: block, id: ast::node_id)
 +pub fn node_vtables(bcx: @mut Block, id: ast::node_id)
                   -> Option<typeck::vtable_res> {
      let raw_vtables = bcx.ccx().maps.vtable_map.find(&id);
      raw_vtables.map(
          |&vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
  }
  
 -pub fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res)
 +pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
      -> typeck::vtable_res {
      resolve_vtables_under_param_substs(fcx.ccx.tcx,
                                         fcx.param_substs,
@@@ -1046,9 -1034,9 +1029,9 @@@ pub fn resolve_vtables_under_param_subs
  }
  
  
 -// Apply the typaram substitutions in the fn_ctxt to a vtable. This should
 +// Apply the typaram substitutions in the FunctionContext to a vtable. This should
  // eliminate any vtable_params.
 -pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: &typeck::vtable_origin)
 +pub fn resolve_vtable_in_fn_ctxt(fcx: &FunctionContext, vt: &typeck::vtable_origin)
      -> typeck::vtable_origin {
      resolve_vtable_under_param_substs(fcx.ccx.tcx,
                                        fcx.param_substs,
@@@ -1120,7 -1108,7 +1103,7 @@@ pub fn dummy_substs(tps: ~[ty::t]) -> t
      }
  }
  
 -pub fn filename_and_line_num_from_span(bcx: block,
 +pub fn filename_and_line_num_from_span(bcx: @mut Block,
                                         span: span) -> (ValueRef, ValueRef) {
      let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
      let filename_cstr = C_cstr(bcx.ccx(), loc.file.name);
  }
  
  // Casts a Rust bool value to an i1.
 -pub fn bool_to_i1(bcx: block, llval: ValueRef) -> ValueRef {
 +pub fn bool_to_i1(bcx: @mut Block, llval: ValueRef) -> ValueRef {
      build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false))
  }
  
 -pub fn langcall(bcx: block, span: Option<span>, msg: &str,
 +pub fn langcall(bcx: @mut Block, span: Option<span>, msg: &str,
                  li: LangItem) -> ast::def_id {
      match bcx.tcx().lang_items.require(li) {
          Ok(id) => id,
index 9c66beaa8601bc3bdce36857a91043b47fc555ef,1c967131b0ac778d4d09d519570bfb761598d32c..2b6c1d8241860e4477305b9f48678139ea561344
@@@ -27,14 -27,13 +27,13 @@@ use util::ppaux
  
  use middle::trans::type_::Type;
  
- use std::str;
  use syntax::ast;
  use syntax::ast::ident;
  use syntax::ast_map::path_mod;
  use syntax::ast_util;
  use syntax::codemap::span;
  
 -pub fn trans_block(bcx: block, b: &ast::Block, dest: expr::Dest) -> block {
 +pub fn trans_block(bcx: @mut Block, b: &ast::Block, dest: expr::Dest) -> @mut Block {
      let _icx = push_ctxt("trans_block");
      let mut bcx = bcx;
      for b.stmts.iter().advance |s| {
      return bcx;
  }
  
 -pub fn trans_if(bcx: block,
 +pub fn trans_if(bcx: @mut Block,
              cond: @ast::expr,
              thn: &ast::Block,
              els: Option<@ast::expr>,
              dest: expr::Dest)
 -         -> block {
 +         -> @mut Block {
      debug!("trans_if(bcx=%s, cond=%s, thn=%?, dest=%s)",
             bcx.to_str(), bcx.expr_to_str(cond), thn.id,
             dest.to_str(bcx.ccx()));
      return next_bcx;
  
      // trans `else [ if { .. } ... | { .. } ]`
 -    fn trans_if_else(bcx: block, elexpr: @ast::expr,
 -                     dest: expr::Dest, scope_name: &str) -> (block, block) {
 +    fn trans_if_else(bcx: @mut Block, elexpr: @ast::expr,
 +                     dest: expr::Dest, scope_name: &str) -> (@mut Block, @mut Block) {
          let else_bcx_in = scope_block(bcx, elexpr.info(), scope_name);
          let else_bcx_out = match elexpr.node {
              ast::expr_if(_, _, _) => {
      }
  }
  
 -pub fn join_blocks(parent_bcx: block, in_cxs: &[block]) -> block {
 +pub fn join_blocks(parent_bcx: @mut Block, in_cxs: &[@mut Block]) -> @mut Block {
      let out = sub_block(parent_bcx, "join");
      let mut reachable = false;
      for in_cxs.iter().advance |bcx| {
      return out;
  }
  
 -pub fn trans_while(bcx: block, cond: @ast::expr, body: &ast::Block) -> block {
 +pub fn trans_while(bcx: @mut Block, cond: @ast::expr, body: &ast::Block) -> @mut Block {
      let _icx = push_ctxt("trans_while");
      let next_bcx = sub_block(bcx, "while next");
  
      return next_bcx;
  }
  
 -pub fn trans_loop(bcx:block,
 +pub fn trans_loop(bcx:@mut Block,
                    body: &ast::Block,
                    opt_label: Option<ident>)
 -               -> block {
 +               -> @mut Block {
      let _icx = push_ctxt("trans_loop");
      let next_bcx = sub_block(bcx, "next");
      let body_bcx_in = loop_scope_block(bcx, next_bcx, opt_label, "`loop`",
  
  pub fn trans_log(log_ex: &ast::expr,
                   lvl: @ast::expr,
 -                 bcx: block,
 -                 e: @ast::expr) -> block {
 +                 bcx: @mut Block,
 +                 e: @ast::expr) -> @mut Block {
      let _icx = push_ctxt("trans_log");
      let ccx = bcx.ccx();
      let mut bcx = bcx;
              ccx, modpath, "loglevel");
          let global;
          unsafe {
-             global = str::as_c_str(s, |buf| {
+             global = do s.as_c_str |buf| {
                  llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
-             });
+             };
              llvm::LLVMSetGlobalConstant(global, False);
              llvm::LLVMSetInitializer(global, C_null(Type::i32()));
              lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
      }
  }
  
 -pub fn trans_break_cont(bcx: block,
 +pub fn trans_break_cont(bcx: @mut Block,
                          opt_label: Option<ident>,
                          to_end: bool)
 -                     -> block {
 +                     -> @mut Block {
      let _icx = push_ctxt("trans_break_cont");
      // Locate closest loop block, outputting cleanup as we go.
      let mut unwind = bcx;
      let mut target;
      loop {
          cur_scope = match cur_scope {
 -            Some(@scope_info {
 +            Some(@ScopeInfo {
                  loop_break: Some(brk),
                  loop_label: l,
                  parent,
      return bcx;
  }
  
 -pub fn trans_break(bcx: block, label_opt: Option<ident>) -> block {
 +pub fn trans_break(bcx: @mut Block, label_opt: Option<ident>) -> @mut Block {
      return trans_break_cont(bcx, label_opt, true);
  }
  
 -pub fn trans_cont(bcx: block, label_opt: Option<ident>) -> block {
 +pub fn trans_cont(bcx: @mut Block, label_opt: Option<ident>) -> @mut Block {
      return trans_break_cont(bcx, label_opt, false);
  }
  
 -pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
 +pub fn trans_ret(bcx: @mut Block, e: Option<@ast::expr>) -> @mut Block {
      let _icx = push_ctxt("trans_ret");
      let mut bcx = bcx;
      let dest = match bcx.fcx.loop_ret {
      return bcx;
  }
  
 -pub fn trans_fail_expr(bcx: block,
 +pub fn trans_fail_expr(bcx: @mut Block,
                         sp_opt: Option<span>,
                         fail_expr: Option<@ast::expr>)
 -                    -> block {
 +                    -> @mut Block {
      let _icx = push_ctxt("trans_fail_expr");
      let mut bcx = bcx;
      match fail_expr {
      }
  }
  
 -pub fn trans_fail(bcx: block,
 +pub fn trans_fail(bcx: @mut Block,
                    sp_opt: Option<span>,
                    fail_str: @str)
 -               -> block {
 +               -> @mut Block {
      let _icx = push_ctxt("trans_fail");
      let V_fail_str = C_cstr(bcx.ccx(), fail_str);
      return trans_fail_value(bcx, sp_opt, V_fail_str);
  }
  
 -fn trans_fail_value(bcx: block,
 +fn trans_fail_value(bcx: @mut Block,
                      sp_opt: Option<span>,
                      V_fail_str: ValueRef)
 -                 -> block {
 +                 -> @mut Block {
      let _icx = push_ctxt("trans_fail_value");
      let ccx = bcx.ccx();
      let (V_filename, V_line) = match sp_opt {
      return bcx;
  }
  
 -pub fn trans_fail_bounds_check(bcx: block, sp: span,
 -                               index: ValueRef, len: ValueRef) -> block {
 +pub fn trans_fail_bounds_check(bcx: @mut Block, sp: span,
 +                               index: ValueRef, len: ValueRef) -> @mut Block {
      let _icx = push_ctxt("trans_fail_bounds_check");
      let (filename, line) = filename_and_line_num_from_span(bcx, sp);
      let args = ~[filename, line, index, len];
index 11d21abb2e6d0c19b2b04c8122e5d43cee0bf124,4249e47d1478521a9338ab24083ba4db0019f3ac..cc690f070ccfcf5d4e8cfaae5983a538daf09593
@@@ -65,7 -65,6 +65,6 @@@ use util::ppaux::ty_to_str
  use std::hashmap::HashMap;
  use std::libc::{c_uint, c_ulonglong, c_longlong};
  use std::ptr;
- use std::str::as_c_str;
  use std::vec;
  use syntax::codemap::span;
  use syntax::{ast, codemap, ast_util, ast_map};
@@@ -134,7 -133,7 +133,7 @@@ pub fn finalize(cx: @mut CrateContext) 
  ///
  /// Adds the created metadata nodes directly to the crate's IR.
  /// The return value should be ignored if called from outside of the debuginfo module.
 -pub fn create_local_var_metadata(bcx: block, local: @ast::Local) -> DIVariable {
 +pub fn create_local_var_metadata(bcx: @mut Block, local: @ast::Local) -> DIVariable {
      let cx = bcx.ccx();
  
      let ident = match local.pat.node {
          Some(_) => lexical_block_metadata(bcx)
      };
  
-     let var_metadata = do as_c_str(name) |name| {
+     let var_metadata = do name.as_c_str |name| {
          unsafe {
              llvm::LLVMDIBuilderCreateLocalVariable(
                  DIB(cx),
  ///
  /// Adds the created metadata nodes directly to the crate's IR.
  /// The return value should be ignored if called from outside of the debuginfo module.
 -pub fn create_argument_metadata(bcx: block, arg: &ast::arg, span: span) -> Option<DIVariable> {
 +pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) -> Option<DIVariable> {
      debug!("create_argument_metadata");
      if true {
          // XXX create_argument_metadata disabled for now because "node_id_type(bcx, arg.id)" below
              // XXX: This is wrong; it should work for multiple bindings.
              let ident = path.idents.last();
              let name: &str = cx.sess.str_of(*ident);
-             let var_metadata = do as_c_str(name) |name| {
+             let var_metadata = do name.as_c_str |name| {
                  unsafe {
                      llvm::LLVMDIBuilderCreateLocalVariable(
                          DIB(cx),
  /// Sets the current debug location at the beginning of the span
  ///
  /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...)
 -pub fn update_source_pos(bcx: block, span: span) {
 +pub fn update_source_pos(bcx: @mut Block, span: span) {
      if !bcx.sess().opts.debuginfo || (*span.lo == 0 && *span.hi == 0) {
          return;
      }
  ///
  /// Adds the created metadata nodes directly to the crate's IR.
  /// The return value should be ignored if called from outside of the debuginfo module.
 -pub fn create_function_metadata(fcx: fn_ctxt) -> DISubprogram {
 +pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
      let cx = fcx.ccx;
 -    let fcx = &mut *fcx;
      let span = fcx.span.get();
  
      let fnitem = cx.tcx.items.get_copy(&fcx.id);
      };
  
      let fn_metadata =
-         do as_c_str(cx.sess.str_of(ident)) |name| {
-         do as_c_str(cx.sess.str_of(ident)) |linkage| {
+         do cx.sess.str_of(ident).as_c_str |name| {
+         do cx.sess.str_of(ident).as_c_str |linkage| {
              unsafe {
                  llvm::LLVMDIBuilderCreateFunction(
                      DIB(cx),
@@@ -401,11 -401,11 +400,11 @@@ fn compile_unit_metadata(cx: @mut Crate
      let work_dir = cx.sess.working_dir.to_str();
      let producer = fmt!("rustc version %s", env!("CFG_VERSION"));
  
-     do as_c_str(crate_name) |crate_name| {
-     do as_c_str(work_dir) |work_dir| {
-     do as_c_str(producer) |producer| {
-     do as_c_str("") |flags| {
-     do as_c_str("") |split_name| {
+     do crate_name.as_c_str |crate_name| {
+     do work_dir.as_c_str |work_dir| {
+     do producer.as_c_str |producer| {
+     do "".as_c_str |flags| {
+     do "".as_c_str |split_name| {
          unsafe {
              llvm::LLVMDIBuilderCreateCompileUnit(dcx.builder,
                  DW_LANG_RUST as c_uint, crate_name, work_dir, producer,
@@@ -432,8 -432,8 +431,8 @@@ fn file_metadata(cx: &mut CrateContext
          };
  
      let file_metadata =
-         do as_c_str(file_name) |file_name| {
-         do as_c_str(work_dir) |work_dir| {
+         do file_name.as_c_str |file_name| {
+         do work_dir.as_c_str |work_dir| {
              unsafe {
                  llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
              }
  }
  
  /// Get or create the lexical block metadata node for the given LLVM basic block.
 -fn lexical_block_metadata(bcx: block) -> DILexicalBlock {
 +fn lexical_block_metadata(bcx: @mut Block) -> DILexicalBlock {
      let cx = bcx.ccx();
      let mut bcx = bcx;
  
@@@ -521,7 -521,7 +520,7 @@@ fn basic_type_metadata(cx: &mut CrateCo
  
      let llvm_type = type_of::type_of(cx, t);
      let (size, align) = size_and_align_of(cx, llvm_type);
-     let ty_metadata = do as_c_str(name) |name| {
+     let ty_metadata = do name.as_c_str |name| {
          unsafe {
              llvm::LLVMDIBuilderCreateBasicType(
                  DIB(cx),
@@@ -542,7 -542,7 +541,7 @@@ fn pointer_type_metadata(cx: &mut Crate
      let pointer_llvm_type = type_of::type_of(cx, pointer_type);
      let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
      let name = ty_to_str(cx.tcx, pointer_type);
-     let ptr_metadata = do as_c_str(name) |name| {
+     let ptr_metadata = do name.as_c_str |name| {
          unsafe {
              llvm::LLVMDIBuilderCreatePointerType(
                  DIB(cx),
@@@ -1037,7 -1037,7 +1036,7 @@@ fn unimplemented_type_metadata(cx: &mu
      debug!("unimplemented_type_metadata: %?", ty::get(t));
  
      let name = ty_to_str(cx.tcx, t);
-     let metadata = do as_c_str(fmt!("NYI<%s>", name)) |name| {
+     let metadata = do fmt!("NYI<%s>", name).as_c_str |name| {
          unsafe {
              llvm::LLVMDIBuilderCreateBasicType(
                  DIB(cx),
index 024ab7af0814def9ef0f708d7960026c88a904e8,d66b43167cec110d194b587c50625fd2e51c01e8..75f553f397177fe6f8c9ffeec86309c64e08acad
@@@ -37,11 -37,11 +37,10 @@@ use util::ppaux::ty_to_short_str
  
  use middle::trans::type_::Type;
  
 -use std::io;
  use std::libc::c_uint;
- use std::str;
  use syntax::ast;
  
 -pub fn trans_free(cx: block, v: ValueRef) -> block {
 +pub fn trans_free(cx: @mut Block, v: ValueRef) -> @mut Block {
      let _icx = push_ctxt("trans_free");
      callee::trans_lang_call(cx,
          langcall(cx, None, "", FreeFnLangItem),
@@@ -49,7 -49,7 +48,7 @@@
          Some(expr::Ignore)).bcx
  }
  
 -pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
 +pub fn trans_exchange_free(cx: @mut Block, v: ValueRef) -> @mut Block {
      let _icx = push_ctxt("trans_exchange_free");
      callee::trans_lang_call(cx,
          langcall(cx, None, "", ExchangeFreeFnLangItem),
@@@ -57,7 -57,7 +56,7 @@@
          Some(expr::Ignore)).bcx
  }
  
 -pub fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {
 +pub fn take_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
      // NB: v is an *alias* of type t here, not a direct value.
      let _icx = push_ctxt("take_ty");
      if ty::type_needs_drop(cx.tcx(), t) {
@@@ -66,7 -66,7 +65,7 @@@
      return cx;
  }
  
 -pub fn drop_ty(cx: block, v: ValueRef, t: ty::t) -> block {
 +pub fn drop_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
      // NB: v is an *alias* of type t here, not a direct value.
      let _icx = push_ctxt("drop_ty");
      if ty::type_needs_drop(cx.tcx(), t) {
@@@ -75,7 -75,7 +74,7 @@@
      return cx;
  }
  
 -pub fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
 +pub fn drop_ty_immediate(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
      let _icx = push_ctxt("drop_ty_immediate");
      match ty::get(t).sty {
          ty::ty_uniq(_)
@@@ -92,7 -92,7 +91,7 @@@
      }
  }
  
 -pub fn free_ty(cx: block, v: ValueRef, t: ty::t) -> block {
 +pub fn free_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
      // NB: v is an *alias* of type t here, not a direct value.
      let _icx = push_ctxt("free_ty");
      if ty::type_needs_drop(cx.tcx(), t) {
      return cx;
  }
  
 -pub fn free_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
 +pub fn free_ty_immediate(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
      let _icx = push_ctxt("free_ty_immediate");
      match ty::get(t).sty {
        ty::ty_uniq(_) |
@@@ -272,7 -272,7 +271,7 @@@ pub fn lazily_emit_tydesc_glue(ccx: @mu
  }
  
  // See [Note-arg-mode]
 -pub fn call_tydesc_glue_full(bcx: block,
 +pub fn call_tydesc_glue_full(bcx: @mut Block,
                               v: ValueRef,
                               tydesc: ValueRef,
                               field: uint,
  }
  
  // See [Note-arg-mode]
 -pub fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: uint)
 -    -> block {
 +pub fn call_tydesc_glue(cx: @mut Block, v: ValueRef, t: ty::t, field: uint)
 +    -> @mut Block {
      let _icx = push_ctxt("call_tydesc_glue");
      let ti = get_tydesc(cx.ccx(), t);
      call_tydesc_glue_full(cx, v, ti.tydesc, field, Some(ti));
      return cx;
  }
  
 -pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
 +pub fn make_visit_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
      let _icx = push_ctxt("make_visit_glue");
      do with_scope(bcx, None, "visitor cleanup") |bcx| {
          let mut bcx = bcx;
      }
  }
  
 -pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
 +pub fn make_free_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
      // NB: v0 is an *alias* of type t here, not a direct value.
      let _icx = push_ctxt("make_free_glue");
      match ty::get(t).sty {
      }
  }
  
 -pub fn trans_struct_drop_flag(bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
 -                              class_did: ast::def_id, substs: &ty::substs) -> block {
 +pub fn trans_struct_drop_flag(bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
 +                              class_did: ast::def_id, substs: &ty::substs) -> @mut Block {
      let repr = adt::represent_type(bcx.ccx(), t);
      let drop_flag = adt::trans_drop_flag_ptr(bcx, repr, v0);
      do with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) |cx| {
      }
  }
  
 -pub fn trans_struct_drop(mut bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
 -                         class_did: ast::def_id, substs: &ty::substs) -> block {
 +pub fn trans_struct_drop(mut bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
 +                         class_did: ast::def_id, substs: &ty::substs) -> @mut Block {
      let repr = adt::represent_type(bcx.ccx(), t);
  
      // Find and call the actual destructor
      bcx
  }
  
 -pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) -> block {
 +pub fn make_drop_glue(bcx: @mut Block, v0: ValueRef, t: ty::t) -> @mut Block {
      // NB: v0 is an *alias* of type t here, not a direct value.
      let _icx = push_ctxt("make_drop_glue");
      let ccx = bcx.ccx();
  }
  
  // box_ptr_ptr is optional, it is constructed if not supplied.
 -pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef,
 +pub fn decr_refcnt_maybe_free(bcx: @mut Block, box_ptr: ValueRef,
                                box_ptr_ptr: Option<ValueRef>,
                                t: ty::t)
 -                           -> block {
 +                           -> @mut Block {
      let _icx = push_ctxt("decr_refcnt_maybe_free");
      let ccx = bcx.ccx();
  
  }
  
  
 -pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
 +pub fn make_take_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
      let _icx = push_ctxt("make_take_glue");
      // NB: v is a *pointer* to type t here, not a direct value.
      match ty::get(t).sty {
      }
  }
  
 -pub fn incr_refcnt_of_boxed(cx: block, box_ptr: ValueRef) {
 +pub fn incr_refcnt_of_boxed(cx: @mut Block, box_ptr: ValueRef) {
      let _icx = push_ctxt("incr_refcnt_of_boxed");
      let ccx = cx.ccx();
      let rc_ptr = GEPi(cx, box_ptr, [0u, abi::box_field_refcnt]);
@@@ -648,8 -648,8 +647,8 @@@ pub fn declare_tydesc(ccx: &mut CrateCo
      let llty = type_of(ccx, t);
  
      if ccx.sess.count_type_sizes() {
 -        io::println(fmt!("%u\t%s", llsize_of_real(ccx, llty),
 -                         ppaux::ty_to_str(ccx.tcx, t)));
 +        printfln!("%u\t%s", llsize_of_real(ccx, llty),
 +                  ppaux::ty_to_str(ccx.tcx, t));
      }
  
      let llsize = llsize_of(ccx, llty);
      let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
      note_unique_llvm_symbol(ccx, name);
      debug!("+++ declare_tydesc %s %s", ppaux::ty_to_str(ccx.tcx, t), name);
-     let gvar = str::as_c_str(name, |buf| {
+     let gvar = do name.as_c_str |buf| {
          unsafe {
              llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type.to_ref(), buf)
          }
-     });
+     };
      let inf = @mut tydesc_info {
          ty: t,
          tydesc: gvar,
      return inf;
  }
  
 -pub type glue_helper<'self> = &'self fn(block, ValueRef, ty::t) -> block;
 +pub type glue_helper<'self> = &'self fn(@mut Block, ValueRef, ty::t) -> @mut Block;
  
  pub fn declare_generic_glue(ccx: &mut CrateContext, t: ty::t, llfnty: Type,
                              name: &str) -> ValueRef {
diff --combined src/libstd/str.rs
index 5b83112fe6bc048e72a58c6b801569e24f39146e,49a7eccaca8a0c62fab4a28d841d20a043d94a1c..636bbc48f8eb42100bb4441a153e0b2ee3ecac73
@@@ -17,7 -17,6 +17,6 @@@
   */
  
  use at_vec;
- use cast::transmute;
  use cast;
  use char;
  use char::Char;
@@@ -33,7 -32,7 +32,7 @@@ use ptr::RawPtr
  use to_str::ToStr;
  use uint;
  use vec;
- use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector};
+ use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector, MutableVector};
  
  /*
  Section: Conditions
@@@ -121,23 -120,17 +120,17 @@@ pub fn from_bytes_slice<'a>(vector: &'
      }
  }
  
- /// Copy a slice into a new unique str
- #[inline]
- pub fn to_owned(s: &str) -> ~str {
-     unsafe { raw::slice_bytes_owned(s, 0, s.len()) }
- }
  impl ToStr for ~str {
      #[inline]
-     fn to_str(&self) -> ~str { to_owned(*self) }
+     fn to_str(&self) -> ~str { self.to_owned() }
  }
  impl<'self> ToStr for &'self str {
      #[inline]
-     fn to_str(&self) -> ~str { to_owned(*self) }
+     fn to_str(&self) -> ~str { self.to_owned() }
  }
  impl ToStr for @str {
      #[inline]
-     fn to_str(&self) -> ~str { to_owned(*self) }
+     fn to_str(&self) -> ~str { self.to_owned() }
  }
  
  /**
@@@ -187,15 -180,13 +180,13 @@@ impl<'self, S: Str> StrVector for &'sel
  
          let len = self.iter().transform(|s| s.as_slice().len()).sum();
  
-         let mut s = ~"";
-         s.reserve(len);
+         let mut s = with_capacity(len);
  
          unsafe {
-             do as_buf(s) |buf, _| {
-                 let mut buf = ::cast::transmute_mut_unsafe(buf);
+             do s.as_mut_buf |buf, _| {
+                 let mut buf = buf;
                  for self.iter().advance |ss| {
-                     do as_buf(ss.as_slice()) |ssbuf, sslen| {
+                     do ss.as_slice().as_imm_buf |ssbuf, sslen| {
                          let sslen = sslen - 1;
                          ptr::copy_memory(buf, ssbuf, sslen);
                          buf = buf.offset(sslen);
          s.reserve(len);
  
          unsafe {
-             do as_buf(s) |buf, _| {
-                 do as_buf(sep) |sepbuf, seplen| {
+             do s.as_mut_buf |buf, _| {
+                 do sep.as_imm_buf |sepbuf, seplen| {
                      let seplen = seplen - 1;
                      let mut buf = ::cast::transmute_mut_unsafe(buf);
                      for self.iter().advance |ss| {
-                         do as_buf(ss.as_slice()) |ssbuf, sslen| {
+                         do ss.as_slice().as_imm_buf |ssbuf, sslen| {
                              let sslen = sslen - 1;
                              if first {
                                  first = false;
@@@ -534,8 -525,8 +525,8 @@@ Section: Comparing string
  #[lang="str_eq"]
  #[inline]
  pub fn eq_slice(a: &str, b: &str) -> bool {
-     do as_buf(a) |ap, alen| {
-         do as_buf(b) |bp, blen| {
+     do a.as_imm_buf |ap, alen| {
+         do b.as_imm_buf |bp, blen| {
              if (alen != blen) { false }
              else {
                  unsafe {
  #[cfg(test)]
  #[inline]
  pub fn eq_slice(a: &str, b: &str) -> bool {
-     do as_buf(a) |ap, alen| {
-         do as_buf(b) |bp, blen| {
+     do a.as_imm_buf |ap, alen| {
+         do b.as_imm_buf |bp, blen| {
              if (alen != blen) { false }
              else {
                  unsafe {
@@@ -685,6 -676,7 +676,7 @@@ pub fn from_utf16(v: &[u16]) -> ~str 
   * Allocates a new string with the specified capacity. The string returned is
   * the empty string, but has capacity for much more.
   */
+ #[inline]
  pub fn with_capacity(capacity: uint) -> ~str {
      let mut buf = ~"";
      buf.reserve(capacity);
@@@ -774,75 -766,13 +766,13 @@@ static TAG_THREE_B: uint = 224u
  static MAX_THREE_B: uint = 65536u;
  static TAG_FOUR_B: uint = 240u;
  
- /**
-  * A dummy trait to hold all the utility methods that we implement on strings.
-  */
- pub trait StrUtil {
-     /**
-      * Work with the byte buffer of a string as a null-terminated C string.
-      *
-      * Allows for unsafe manipulation of strings, which is useful for foreign
-      * interop. This is similar to `str::as_buf`, but guarantees null-termination.
-      * If the given slice is not already null-terminated, this function will
-      * allocate a temporary, copy the slice, null terminate it, and pass
-      * that instead.
-      *
-      * # Example
-      *
-      * ~~~ {.rust}
-      * let s = "PATH".as_c_str(|path| libc::getenv(path));
-      * ~~~
-      */
-     fn as_c_str<T>(self, f: &fn(*libc::c_char) -> T) -> T;
- }
- impl<'self> StrUtil for &'self str {
-     #[inline]
-     fn as_c_str<T>(self, f: &fn(*libc::c_char) -> T) -> T {
-         do as_buf(self) |buf, len| {
-             // NB: len includes the trailing null.
-             assert!(len > 0);
-             if unsafe { *(ptr::offset(buf,len-1)) != 0 } {
-                 to_owned(self).as_c_str(|s| f(s))
-             } else {
-                 f(buf as *libc::c_char)
-             }
-         }
-     }
- }
- /**
-  * Deprecated. Use the `as_c_str` method on strings instead.
-  */
- #[inline]
- pub fn as_c_str<T>(s: &str, f: &fn(*libc::c_char) -> T) -> T {
-     s.as_c_str(f)
- }
- /**
-  * Work with the byte buffer and length of a slice.
-  *
-  * The given length is one byte longer than the 'official' indexable
-  * length of the string. This is to permit probing the byte past the
-  * indexable area for a null byte, as is the case in slices pointing
-  * to full strings, or suffixes of them.
-  */
- #[inline]
- pub fn as_buf<T>(s: &str, f: &fn(*u8, uint) -> T) -> T {
-     unsafe {
-         let v : *(*u8,uint) = transmute(&s);
-         let (buf,len) = *v;
-         f(buf, len)
-     }
- }
  /// Unsafe operations
  pub mod raw {
      use cast;
      use libc;
      use ptr;
      use str::raw;
-     use str::{as_buf, is_utf8};
+     use str::{is_utf8};
      use vec;
      use vec::MutableVector;
  
          ::cast::transmute(v)
      }
  
-     /**
-      * Takes a bytewise (not UTF-8) slice from a string.
-      *
-      * Returns the substring from [`begin`..`end`).
-      *
-      * # Failure
-      *
-      * If begin is greater than end.
-      * If end is greater than the length of the string.
-      */
-     pub unsafe fn slice_bytes_owned(s: &str, begin: uint, end: uint) -> ~str {
-         do as_buf(s) |sbuf, n| {
-             assert!((begin <= end));
-             assert!((end <= n));
-             let mut v = vec::with_capacity(end - begin + 1u);
-             do v.as_imm_buf |vbuf, _vlen| {
-                 let vbuf = ::cast::transmute_mut_unsafe(vbuf);
-                 let src = ptr::offset(sbuf, begin);
-                 ptr::copy_memory(vbuf, src, end - begin);
-             }
-             vec::raw::set_len(&mut v, end - begin);
-             v.push(0u8);
-             ::cast::transmute(v)
-         }
-     }
      /**
       * Takes a bytewise (not UTF-8) slice from a string.
       *
       */
      #[inline]
      pub unsafe fn slice_bytes(s: &str, begin: uint, end: uint) -> &str {
-         do as_buf(s) |sbuf, n| {
+         do s.as_imm_buf |sbuf, n| {
               assert!((begin <= end));
               assert!((end <= n));
  
      pub unsafe fn push_byte(s: &mut ~str, b: u8) {
          let new_len = s.len() + 1;
          s.reserve_at_least(new_len);
-         do as_buf(*s) |buf, len| {
-             let buf: *mut u8 = ::cast::transmute(buf);
+         do s.as_mut_buf |buf, len| {
              *ptr::mut_offset(buf, len) = b;
          }
          set_len(&mut *s, new_len);
          let len = s.len();
          assert!((len > 0u));
          let b = s[0];
-         *s = raw::slice_bytes_owned(*s, 1u, len);
+         *s = s.slice(1, len).to_owned();
          return b;
      }
  
@@@ -1193,7 -1095,7 +1095,7 @@@ impl<'self> Str for @str 
  impl<'self> Container for &'self str {
      #[inline]
      fn len(&self) -> uint {
-         do as_buf(*self) |_p, n| { n - 1u }
+         do self.as_imm_buf |_p, n| { n - 1u }
      }
      #[inline]
      fn is_empty(&self) -> bool {
@@@ -1287,6 -1189,9 +1189,9 @@@ pub trait StrSlice<'self> 
      fn lev_distance(&self, t: &str) -> uint;
  
      fn subslice_offset(&self, inner: &str) -> uint;
+     fn as_imm_buf<T>(&self, f: &fn(*u8, uint) -> T) -> T;
+     fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T;
  }
  
  /// Extension methods for strings
@@@ -1669,7 -1574,21 +1574,21 @@@ impl<'self> StrSlice<'self> for &'self 
  
      /// Copy a slice into a new unique str
      #[inline]
-     fn to_owned(&self) -> ~str { to_owned(*self) }
+     fn to_owned(&self) -> ~str {
+         do self.as_imm_buf |src, len| {
+             assert!(len > 0);
+             unsafe {
+                 let mut v = vec::with_capacity(len);
+                 do v.as_mut_buf |dst, _| {
+                     ptr::copy_memory(dst, src, len - 1);
+                 }
+                 vec::raw::set_len(&mut v, len - 1);
+                 v.push(0u8);
+                 ::cast::transmute(v)
+             }
+         }
+     }
  
      #[inline]
      fn to_managed(&self) -> @str {
       * let i = 0u;
       * while i < s.len() {
       *     let CharRange {ch, next} = s.char_range_at(i);
 -     *     std::io::println(fmt!("%u: %c",i,ch));
 +     *     printfln!("%u: %c", i, ch);
       *     i = next;
       * }
       * ~~~
  
      /// Given a string, make a new string with repeated copies of it.
      fn repeat(&self, nn: uint) -> ~str {
-         do as_buf(*self) |buf, len| {
-             let mut ret = ~"";
+         do self.as_imm_buf |buf, len| {
              // ignore the NULL terminator
              let len = len - 1;
-             ret.reserve(nn * len);
+             let mut ret = with_capacity(nn * len);
  
              unsafe {
-                 do as_buf(ret) |rbuf, _len| {
-                     let mut rbuf = ::cast::transmute_mut_unsafe(rbuf);
+                 do ret.as_mut_buf |rbuf, _len| {
+                     let mut rbuf = rbuf;
  
                      for nn.times {
                          ptr::copy_memory(rbuf, buf, len);
       */
      #[inline]
      fn subslice_offset(&self, inner: &str) -> uint {
-         do as_buf(*self) |a, a_len| {
-             do as_buf(inner) |b, b_len| {
+         do self.as_imm_buf |a, a_len| {
+             do inner.as_imm_buf |b, b_len| {
                  let a_start: uint;
                  let a_end: uint;
                  let b_start: uint;
          }
      }
  
+     /**
+      * Work with the byte buffer and length of a slice.
+      *
+      * The given length is one byte longer than the 'official' indexable
+      * length of the string. This is to permit probing the byte past the
+      * indexable area for a null byte, as is the case in slices pointing
+      * to full strings, or suffixes of them.
+      */
+     #[inline]
+     fn as_imm_buf<T>(&self, f: &fn(*u8, uint) -> T) -> T {
+         let v: &[u8] = unsafe { cast::transmute(*self) };
+         v.as_imm_buf(f)
+     }
+     /**
+      * Work with the byte buffer of a string as a null-terminated C string.
+      *
+      * Allows for unsafe manipulation of strings, which is useful for foreign
+      * interop. This is similar to `str::as_buf`, but guarantees null-termination.
+      * If the given slice is not already null-terminated, this function will
+      * allocate a temporary, copy the slice, null terminate it, and pass
+      * that instead.
+      *
+      * # Example
+      *
+      * ~~~ {.rust}
+      * let s = "PATH".as_c_str(|path| libc::getenv(path));
+      * ~~~
+      */
+     #[inline]
+     fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
+         do self.as_imm_buf |buf, len| {
+             // NB: len includes the trailing null.
+             assert!(len > 0);
+             if unsafe { *(ptr::offset(buf, len - 1)) != 0 } {
+                 self.to_owned().as_c_str(|s| f(s))
+             } else {
+                 f(buf as *libc::c_char)
+             }
+         }
+     }
  }
  
  #[allow(missing_doc)]
@@@ -2069,12 -2028,23 +2028,23 @@@ pub trait OwnedStr 
      fn pop_char(&mut self) -> char;
      fn shift_char(&mut self) -> char;
      fn unshift_char(&mut self, ch: char);
-     fn append(&self, rhs: &str) -> ~str; // FIXME #4850: this should consume self.
+     fn append(self, rhs: &str) -> ~str;
      fn reserve(&mut self, n: uint);
      fn reserve_at_least(&mut self, n: uint);
      fn capacity(&self) -> uint;
+     fn to_bytes_with_null(self) -> ~[u8];
  
-     fn as_bytes_with_null_consume(self) -> ~[u8];
+     /**
+      * Work with the mutable byte buffer and length of a slice.
+      *
+      * The given length is one byte longer than the 'official' indexable
+      * length of the string. This is to permit probing the byte past the
+      * indexable area for a null byte, as is the case in slices pointing
+      * to full strings, or suffixes of them.
+      *
+      * Make sure any mutations to this buffer keep this string valid UTF8.
+      */
+     fn as_mut_buf<T>(&mut self, f: &fn(*mut u8, uint) -> T) -> T;
  }
  
  impl OwnedStr for ~str {
              let llen = self.len();
              let rlen = rhs.len();
              self.reserve(llen + rlen);
-             do as_buf(*self) |lbuf, _llen| {
-                 do as_buf(rhs) |rbuf, _rlen| {
+             do self.as_imm_buf |lbuf, _llen| {
+                 do rhs.as_imm_buf |rbuf, _rlen| {
                      let dst = ptr::offset(lbuf, llen);
                      let dst = ::cast::transmute_mut_unsafe(dst);
                      ptr::copy_memory(dst, rbuf, rlen);
              let llen = self.len();
              let rlen = rhs.len();
              self.reserve_at_least(llen + rlen);
-             do as_buf(*self) |lbuf, _llen| {
-                 do as_buf(rhs) |rbuf, _rlen| {
+             do self.as_imm_buf |lbuf, _llen| {
+                 do rhs.as_imm_buf |rbuf, _rlen| {
                      let dst = ptr::offset(lbuf, llen);
                      let dst = ::cast::transmute_mut_unsafe(dst);
                      ptr::copy_memory(dst, rbuf, rlen);
              let new_len = len + nb;
              self.reserve_at_least(new_len);
              let off = len;
-             do as_buf(*self) |buf, _len| {
-                 let buf: *mut u8 = ::cast::transmute(buf);
+             do self.as_mut_buf |buf, _len| {
                  match nb {
                      1u => {
                          *ptr::mut_offset(buf, off) = code as u8;
       */
      fn shift_char(&mut self) -> char {
          let CharRange {ch, next} = self.char_range_at(0u);
-         *self = unsafe { raw::slice_bytes_owned(*self, next, self.len()) };
+         *self = self.slice(next, self.len()).to_owned();
          return ch;
      }
  
  
      /// Concatenate two strings together.
      #[inline]
-     fn append(&self, rhs: &str) -> ~str {
-         // FIXME #4850: this should consume self, but that causes segfaults
-         let mut v = self.clone();
-         v.push_str_no_overallocate(rhs);
-         v
+     fn append(self, rhs: &str) -> ~str {
+         let mut new_str = self;
+         new_str.push_str_no_overallocate(rhs);
+         new_str
      }
  
      /**
      /// Convert to a vector of bytes. This does not allocate a new
      /// string, and includes the null terminator.
      #[inline]
-     fn as_bytes_with_null_consume(self) -> ~[u8] {
+     fn to_bytes_with_null(self) -> ~[u8] {
          unsafe { ::cast::transmute(self) }
      }
+     #[inline]
+     fn as_mut_buf<T>(&mut self, f: &fn(*mut u8, uint) -> T) -> T {
+         let v: &mut ~[u8] = unsafe { cast::transmute(self) };
+         v.as_mut_buf(f)
+     }
  }
  
  impl Clone for ~str {
      #[inline]
      fn clone(&self) -> ~str {
-         to_owned(*self)
+         self.to_owned()
      }
  }
  
@@@ -3065,17 -3039,17 +3039,17 @@@ mod tests 
      }
  
      #[test]
-     fn test_as_bytes_with_null_consume() {
+     fn test_to_bytes_with_null() {
          let s = ~"ศไทย中华Việt Nam";
          let v = ~[
              224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
              184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
              109, 0
          ];
-         assert_eq!((~"").as_bytes_with_null_consume(), ~[0]);
-         assert_eq!((~"abc").as_bytes_with_null_consume(),
+         assert_eq!((~"").to_bytes_with_null(), ~[0]);
+         assert_eq!((~"abc").to_bytes_with_null(),
                     ~['a' as u8, 'b' as u8, 'c' as u8, 0]);
-         assert_eq!(s.as_bytes_with_null_consume(), v);
+         assert_eq!(s.to_bytes_with_null(), v);
      }
  
      #[test]
      }
  
      #[test]
-     fn test_as_buf() {
-         let a = "Abcdefg";
-         let b = as_buf(a, |buf, _l| {
-             assert_eq!(unsafe { *buf }, 65u8);
-             100
-         });
-         assert_eq!(b, 100);
-     }
+     fn test_as_imm_buf() {
+         do "".as_imm_buf |buf, len| {
+             assert_eq!(len, 1);
+             unsafe {
+                 assert_eq!(*ptr::offset(buf, 0), 0);
+             }
+         }
  
-     #[test]
-     fn test_as_buf_small() {
-         let a = "A";
-         let b = as_buf(a, |buf, _l| {
-             assert_eq!(unsafe { *buf }, 65u8);
-             100
-         });
-         assert_eq!(b, 100);
+         do "hello".as_imm_buf |buf, len| {
+             assert_eq!(len, 6);
+             unsafe {
+                 assert_eq!(*ptr::offset(buf, 0), 'h' as u8);
+                 assert_eq!(*ptr::offset(buf, 1), 'e' as u8);
+                 assert_eq!(*ptr::offset(buf, 2), 'l' as u8);
+                 assert_eq!(*ptr::offset(buf, 3), 'l' as u8);
+                 assert_eq!(*ptr::offset(buf, 4), 'o' as u8);
+                 assert_eq!(*ptr::offset(buf, 5), 0);
+             }
+         }
      }
  
      #[test]
-     fn test_as_buf2() {
-         unsafe {
-             let s = ~"hello";
-             let sb = as_buf(s, |b, _l| b);
-             let s_cstr = raw::from_buf(sb);
-             assert_eq!(s_cstr, s);
+     fn test_as_c_str() {
+         let a = ~"";
+         do a.as_c_str |buf| {
+             unsafe {
+                 assert_eq!(*ptr::offset(buf, 0), 0);
+             }
          }
-     }
  
-     #[test]
-     fn test_as_buf_3() {
          let a = ~"hello";
-         do as_buf(a) |buf, len| {
+         do a.as_c_str |buf| {
              unsafe {
-                 assert_eq!(a[0], 'h' as u8);
-                 assert_eq!(*buf, 'h' as u8);
-                 assert_eq!(len, 6u);
-                 assert_eq!(*ptr::offset(buf,4u), 'o' as u8);
-                 assert_eq!(*ptr::offset(buf,5u), 0u8);
+                 assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
+                 assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
+                 assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
+                 assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
+                 assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
+                 assert_eq!(*ptr::offset(buf, 5), 0);
              }
          }
      }
          assert_eq!(5, sum_len([s.as_slice()]));
      }
  }
 +
 +#[cfg(test)]
 +mod bench {
 +    use extra::test::BenchHarness;
 +    use str;
 +
 +    #[bench]
 +    fn is_utf8_100_ascii(bh: &mut BenchHarness) {
 +
 +        let s = bytes!("Hello there, the quick brown fox jumped over the lazy dog! \
 +                        Lorem ipsum dolor sit amet, consectetur. ");
 +
 +        assert_eq!(100, s.len());
 +        do bh.iter {
 +            str::is_utf8(s);
 +        }
 +    }
 +
 +    #[bench]
 +    fn is_utf8_100_multibyte(bh: &mut BenchHarness) {
 +        let s = bytes!("𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰");
 +        assert_eq!(100, s.len());
 +        do bh.iter {
 +            str::is_utf8(s);
 +        }
 +    }
 +
 +    #[bench]
 +    fn map_chars_100_ascii(bh: &mut BenchHarness) {
 +        let s = "HelloHelloHelloHelloHelloHelloHelloHelloHelloHello\
 +                 HelloHelloHelloHelloHelloHelloHelloHelloHelloHello";
 +        do bh.iter {
 +            s.map_chars(|c| ((c as uint) + 1) as char);
 +        }
 +    }
 +
 +    #[bench]
 +    fn map_chars_100_multibytes(bh: &mut BenchHarness) {
 +        let s = "𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑\
 +                 𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑\
 +                 𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑\
 +                 𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑";
 +        do bh.iter {
 +            s.map_chars(|c| ((c as uint) + 1) as char);
 +        }
 +    }
 +}
diff --combined src/libstd/vec.rs
index 8432f28a969863b624a9abb1e73dc95a38bd0149,cc41f0dbb941cfd07885a686a02e19b6a3c1a16d..5f8a2796248ec43c2606241c403cceb141bd4231
@@@ -87,6 -87,7 +87,7 @@@ pub fn from_elem<T:Clone>(n_elts: uint
  }
  
  /// Creates a new vector with a capacity of `capacity`
+ #[inline]
  pub fn with_capacity<T>(capacity: uint) -> ~[T] {
      unsafe {
          if contains_managed::<T>() {
@@@ -833,7 -834,7 +834,7 @@@ impl<'self,T> ImmutableVector<'self, T
       * ~~~ {.rust}
       * let v = &[1,2,3,4];
       * for v.window_iter().advance |win| {
 -     *     io::println(fmt!("%?", win));
 +     *     printfln!(win);
       * }
       * ~~~
       *
       * ~~~ {.rust}
       * let v = &[1,2,3,4,5];
       * for v.chunk_iter().advance |win| {
 -     *     io::println(fmt!("%?", win));
 +     *     printfln!(win);
       * }
       * ~~~
       *
@@@ -1691,7 -1692,7 +1692,7 @@@ pub trait MutableVector<'self, T> 
      unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T;
      unsafe fn unsafe_set(&self, index: uint, val: T);
  
-     fn as_mut_buf<U>(&self, f: &fn(*mut T, uint) -> U) -> U;
+     fn as_mut_buf<U>(self, f: &fn(*mut T, uint) -> U) -> U;
  }
  
  impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
  
      /// Similar to `as_imm_buf` but passing a `*mut T`
      #[inline]
-     fn as_mut_buf<U>(&self, f: &fn(*mut T, uint) -> U) -> U {
-         unsafe {
-             let v : *(*mut T,uint) = transmute(self);
-             let (buf,len) = *v;
-             f(buf, len / sys::nonzero_size_of::<T>())
-         }
+     fn as_mut_buf<U>(self, f: &fn(*mut T, uint) -> U) -> U {
+         let (buf, len): (*mut T, uint) = unsafe { transmute(self) };
+         f(buf, len / sys::nonzero_size_of::<T>())
      }
  
  }
@@@ -2116,7 -2114,8 +2114,7 @@@ macro_rules! iterator 
  
              #[inline]
              fn size_hint(&self) -> (uint, Option<uint>) {
 -                let diff = (self.end as uint) - (self.ptr as uint);
 -                let exact = diff / sys::nonzero_size_of::<$elem>();
 +                let exact = self.indexable();
                  (exact, Some(exact))
              }
          }
@@@ -2144,28 -2143,6 +2142,28 @@@ macro_rules! double_ended_iterator 
      }
  }
  
 +macro_rules! random_access_iterator {
 +    (impl $name:ident -> $elem:ty) => {
 +        impl<'self, T> RandomAccessIterator<$elem> for $name<'self, T> {
 +            #[inline]
 +            fn indexable(&self) -> uint {
 +                let diff = (self.end as uint) - (self.ptr as uint);
 +                diff / sys::nonzero_size_of::<T>()
 +            }
 +
 +            fn idx(&self, index: uint) -> Option<$elem> {
 +                unsafe {
 +                    if index < self.indexable() {
 +                        cast::transmute(self.ptr.offset(index))
 +                    } else {
 +                        None
 +                    }
 +                }
 +            }
 +        }
 +    }
 +}
 +
  //iterator!{struct VecIterator -> *T, &'self T}
  /// An iterator for iterating over a vector.
  pub struct VecIterator<'self, T> {
  }
  iterator!{impl VecIterator -> &'self T}
  double_ended_iterator!{impl VecIterator -> &'self T}
 +random_access_iterator!{impl VecIterator -> &'self T}
  pub type VecRevIterator<'self, T> = InvertIterator<&'self T, VecIterator<'self, T>>;
  
  impl<'self, T> Clone for VecIterator<'self, T> {
@@@ -2191,7 -2167,6 +2189,7 @@@ pub struct VecMutIterator<'self, T> 
  }
  iterator!{impl VecMutIterator -> &'self mut T}
  double_ended_iterator!{impl VecMutIterator -> &'self mut T}
 +random_access_iterator!{impl VecMutIterator -> &'self mut T}
  pub type VecMutRevIterator<'self, T> = InvertIterator<&'self mut T, VecMutIterator<'self, T>>;
  
  /// An iterator that moves out of a vector.
@@@ -3131,45 -3106,6 +3129,45 @@@ mod tests 
          assert!(it.next().is_none());
      }
  
 +    #[test]
 +    fn test_random_access_iterator() {
 +        use iterator::*;
 +        let xs = [1, 2, 5, 10, 11];
 +        let mut it = xs.iter();
 +
 +        assert_eq!(it.indexable(), 5);
 +        assert_eq!(it.idx(0).unwrap(), &1);
 +        assert_eq!(it.idx(2).unwrap(), &5);
 +        assert_eq!(it.idx(4).unwrap(), &11);
 +        assert!(it.idx(5).is_none());
 +
 +        assert_eq!(it.next().unwrap(), &1);
 +        assert_eq!(it.indexable(), 4);
 +        assert_eq!(it.idx(0).unwrap(), &2);
 +        assert_eq!(it.idx(3).unwrap(), &11);
 +        assert!(it.idx(4).is_none());
 +
 +        assert_eq!(it.next().unwrap(), &2);
 +        assert_eq!(it.indexable(), 3);
 +        assert_eq!(it.idx(1).unwrap(), &10);
 +        assert!(it.idx(3).is_none());
 +
 +        assert_eq!(it.next().unwrap(), &5);
 +        assert_eq!(it.indexable(), 2);
 +        assert_eq!(it.idx(1).unwrap(), &11);
 +
 +        assert_eq!(it.next().unwrap(), &10);
 +        assert_eq!(it.indexable(), 1);
 +        assert_eq!(it.idx(0).unwrap(), &11);
 +        assert!(it.idx(1).is_none());
 +
 +        assert_eq!(it.next().unwrap(), &11);
 +        assert_eq!(it.indexable(), 0);
 +        assert!(it.idx(0).is_none());
 +
 +        assert!(it.next().is_none());
 +    }
 +
      #[test]
      fn test_iter_size_hints() {
          use iterator::*;