diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index 858e7334cff..cea440afd90 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -997,7 +997,7 @@ fn make_lib_name(config: &config, auxfile: &Path, testfile: &Path) -> Path {
 fn make_exe_name(config: &config, testfile: &Path) -> Path {
     let mut f = output_base_name(config, testfile);
     if !os::consts::EXE_SUFFIX.is_empty() {
-        match f.filename().map(|s| s + os::consts::EXE_SUFFIX.as_bytes()) {
+        match f.filename().map(|s| Vec::from_slice(s).append(os::consts::EXE_SUFFIX.as_bytes())) {
             Some(v) => f.set_filename(v),
             None => ()
         }
@@ -1091,7 +1091,7 @@ fn make_out_name(config: &config, testfile: &Path, extension: &str) -> Path {
 
 fn aux_output_dir_name(config: &config, testfile: &Path) -> Path {
     let mut f = output_base_name(config, testfile);
-    match f.filename().map(|s| s + bytes!(".libaux")) {
+    match f.filename().map(|s| Vec::from_slice(s).append(bytes!(".libaux"))) {
         Some(v) => f.set_filename(v),
         None => ()
     }
@@ -1273,7 +1273,7 @@ fn append_suffix_to_stem(p: &Path, suffix: &str) -> Path {
         (*p).clone()
     } else {
         let stem = p.filestem().unwrap();
-        p.with_filename(stem + bytes!("-") + suffix.as_bytes())
+        p.with_filename(Vec::from_slice(stem).append(bytes!("-")).append(suffix.as_bytes()))
     }
 }
 
diff --git a/src/doc/rust.md b/src/doc/rust.md
index 1158044ae19..e4c95538d30 100644
--- a/src/doc/rust.md
+++ b/src/doc/rust.md
@@ -3604,7 +3604,7 @@ fn map<A: Clone, B: Clone>(f: |A| -> B, xs: &[A]) -> Vec<B> {
     }
     let first: B = f(xs[0].clone());
     let rest: Vec<B> = map(f, xs.slice(1, xs.len()));
-    return [first] + rest;
+    return vec![first].append(rest.as_slice());
 }
 ~~~~
 
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 53de765b89c..a771f30dfd1 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -111,4 +111,6 @@ mod std {
     #[cfg(test)] pub use realstd::rt;     // needed for fail!()
     #[cfg(test)] pub use realstd::option; // needed for assert!()
     #[cfg(test)] pub use realstd::os;     // needed for tests
+    #[cfg(test)] pub use realstd::slice;  // needed for tests
+    #[cfg(test)] pub use realstd::vec;    // needed for vec![]
 }
diff --git a/src/libcore/should_not_exist.rs b/src/libcore/should_not_exist.rs
index 78d5afec7b4..0e6baaa518a 100644
--- a/src/libcore/should_not_exist.rs
+++ b/src/libcore/should_not_exist.rs
@@ -13,8 +13,9 @@ use char::Char;
 use clone::Clone;
 use container::Container;
 use default::Default;
+use finally::try_finally;
 use intrinsics;
-use iter::{Iterator, FromIterator};
+use iter::{range, Iterator, FromIterator};
 use mem;
 use num::{CheckedMul, CheckedAdd};
 use option::{Some, None};
@@ -25,7 +26,6 @@ use slice::ImmutableVector;
 use str::StrSlice;
 
 #[cfg(not(test))] use ops::Add;
-#[cfg(not(test))] use slice::Vector;
 
 #[allow(ctypes)]
 extern {
@@ -147,6 +147,34 @@ impl<'a> Add<&'a str,~str> for &'a str {
 impl<A: Clone> Clone for ~[A] {
     #[inline]
     fn clone(&self) -> ~[A] {
-        self.iter().map(|a| a.clone()).collect()
+        let len = self.len();
+        let data_size = len.checked_mul(&mem::size_of::<A>()).unwrap();
+        let size = mem::size_of::<Vec<()>>().checked_add(&data_size).unwrap();
+
+        unsafe {
+            let ret = alloc(size) as *mut Vec<A>;
+
+            (*ret).fill = len * mem::nonzero_size_of::<A>();
+            (*ret).alloc = len * mem::nonzero_size_of::<A>();
+
+            let mut i = 0;
+            let p = &mut (*ret).data as *mut _ as *mut A;
+            try_finally(
+                &mut i, (),
+                |i, ()| while *i < len {
+                    mem::move_val_init(
+                        &mut(*p.offset(*i as int)),
+                        self.unsafe_ref(*i).clone());
+                    *i += 1;
+                },
+                |i| if *i < len {
+                    // we must be failing, clean up after ourselves
+                    for j in range(0, *i as int) {
+                        ptr::read(&*p.offset(j));
+                    }
+                    free(ret as *u8);
+                });
+            cast::transmute(ret)
+        }
     }
 }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 8047de5e8f9..400aa83a615 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -2110,11 +2110,11 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
 
     let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
     let metadata = encoder::encode_metadata(encode_parms, krate);
-    let compressed = encoder::metadata_encoding_version +
-                        match flate::deflate_bytes(metadata.as_slice()) {
-                            Some(compressed) => compressed,
-                            None => cx.sess().fatal(format!("failed to compress metadata", ))
-                        }.as_slice();
+    let compressed = Vec::from_slice(encoder::metadata_encoding_version)
+                     .append(match flate::deflate_bytes(metadata.as_slice()) {
+                         Some(compressed) => compressed,
+                         None => cx.sess().fatal(format!("failed to compress metadata"))
+                     }.as_slice());
     let llmeta = C_bytes(cx, compressed.as_slice());
     let llconst = C_struct(cx, [llmeta], false);
     let name = format!("rust_metadata_{}_{}_{}", cx.link_meta.crateid.name,
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 9822cc388bb..4fd4f2f9d6e 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -157,8 +157,9 @@ pub fn monomorphic_fn(ccx: &CrateContext,
             // This is a bit unfortunate.
 
             let idx = real_substs.tps.len() - num_method_ty_params;
-            let substs = real_substs.tps.slice(0, idx) +
-            &[real_substs.self_ty.unwrap()] + real_substs.tps.tailn(idx);
+            let substs = Vec::from_slice(real_substs.tps.slice(0, idx))
+                         .append([real_substs.self_ty.unwrap()])
+                         .append(real_substs.tps.tailn(idx));
             debug!("static default: changed substitution to {}",
                    substs.repr(ccx.tcx()));
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index fe80d26d109..0bdf0818c8e 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -549,7 +549,8 @@ impl<'a> SourceCollector<'a> {
             root_path.push_str("../");
         });
 
-        cur.push(p.filename().expect("source has no filename") + bytes!(".html"));
+        cur.push(Vec::from_slice(p.filename().expect("source has no filename"))
+                 .append(bytes!(".html")));
         let mut w = BufferedWriter::new(try!(File::create(&cur)));
 
         let title = format!("{} -- source", cur.filename_display());
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 32f78c23aa7..f45ec8a6742 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -13,7 +13,7 @@
 use to_str::{IntoStr};
 use str;
 use str::Str;
-use str::StrSlice;
+use str::{StrAllocating, StrSlice};
 use str::OwnedStr;
 use container::Container;
 use cast;
diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs
index 4bd2ba07634..d8f1c108b74 100644
--- a/src/libstd/num/i16.rs
+++ b/src/libstd/num/i16.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for signed 16-bits integers (`i16` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::i16::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs
index 3c3acfae3c0..9cc8981fc13 100644
--- a/src/libstd/num/i32.rs
+++ b/src/libstd/num/i32.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for signed 32-bits integers (`i32` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::i32::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs
index ad0fe1c08ef..4f7fe32cc70 100644
--- a/src/libstd/num/i64.rs
+++ b/src/libstd/num/i64.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for signed 64-bits integers (`i64` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::i64::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs
index bd40a2c53b6..bea315d8683 100644
--- a/src/libstd/num/i8.rs
+++ b/src/libstd/num/i8.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for signed 8-bits integers (`i8` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::i8::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs
index d9552ee3340..d6a7fd1660b 100644
--- a/src/libstd/num/int.rs
+++ b/src/libstd/num/int.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for architecture-sized signed integers (`int` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::int::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs
index f7813c31d4d..fcdb63f5ad5 100644
--- a/src/libstd/num/int_macros.rs
+++ b/src/libstd/num/int_macros.rs
@@ -77,6 +77,9 @@ impl ToStrRadix for $T {
     /// Convert to a string in a given base.
     #[inline]
     fn to_str_radix(&self, radix: uint) -> ~str {
+        use slice::Vector;
+        use str::StrAllocating;
+
         let mut buf = ::vec::Vec::new();
         strconv::int_to_str_bytes_common(*self, radix, strconv::SignNeg, |i| {
             buf.push(i);
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
index ebcef6ddc5f..4769b17fb2b 100644
--- a/src/libstd/num/strconv.rs
+++ b/src/libstd/num/strconv.rs
@@ -21,7 +21,7 @@ use ops::{Add, Sub, Mul, Div, Rem, Neg};
 use option::{None, Option, Some};
 use slice::{CloneableVector, ImmutableVector, MutableVector};
 use std::cmp::{Ord, Eq};
-use str::{Str, StrSlice};
+use str::{StrAllocating, StrSlice};
 use strbuf::StrBuf;
 use vec::Vec;
 
diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs
index dd6a838df9b..5c93ca6c36b 100644
--- a/src/libstd/num/u16.rs
+++ b/src/libstd/num/u16.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for unsigned 16-bits integers (`u16` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::u16::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs
index bb05938969d..436eae7cd14 100644
--- a/src/libstd/num/u32.rs
+++ b/src/libstd/num/u32.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for unsigned 32-bits integers (`u32` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::u32::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs
index f38806e1527..c654d6fbe31 100644
--- a/src/libstd/num/u64.rs
+++ b/src/libstd/num/u64.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for unsigned 64-bits integer (`u64` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::u64::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs
index 87fed563a15..7051b9191be 100644
--- a/src/libstd/num/u8.rs
+++ b/src/libstd/num/u8.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for unsigned 8-bits integers (`u8` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::u8::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs
index 61ab97e86b8..d1c3e96b2c9 100644
--- a/src/libstd/num/uint.rs
+++ b/src/libstd/num/uint.rs
@@ -11,11 +11,10 @@
 //! Operations and constants for architecture-sized unsigned integers (`uint` type)
 
 use from_str::FromStr;
-use iter::Iterator;
 use num::{ToStrRadix, FromStrRadix};
 use num::strconv;
 use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
 use str;
 
 pub use core::uint::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs
index 814ea0e4274..0795238a49c 100644
--- a/src/libstd/num/uint_macros.rs
+++ b/src/libstd/num/uint_macros.rs
@@ -78,6 +78,9 @@ impl ToStrRadix for $T {
     /// Convert to a string in a given base.
     #[inline]
     fn to_str_radix(&self, radix: uint) -> ~str {
+        use slice::Vector;
+        use str::StrAllocating;
+
         let mut buf = ::vec::Vec::new();
         strconv::int_to_str_bytes_common(*self, radix, strconv::SignNone, |i| {
             buf.push(i);
diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs
index f769ce5b319..2650c39bdb8 100644
--- a/src/libstd/slice.rs
+++ b/src/libstd/slice.rs
@@ -279,26 +279,6 @@ impl<T: Clone> Iterator<~[T]> for Permutations<T> {
     }
 }
 
-#[cfg(not(test))]
-impl<'a,T:Clone, V: Vector<T>> Add<V, Vec<T>> for &'a [T] {
-    #[inline]
-    fn add(&self, rhs: &V) -> Vec<T> {
-        let rhs = rhs.as_slice();
-        let mut res = Vec::with_capacity(self.len() + rhs.len());
-        res.push_all(*self);
-        res.push_all(rhs);
-        res
-    }
-}
-
-#[cfg(not(test))]
-impl<T:Clone, V: Vector<T>> Add<V, Vec<T>> for ~[T] {
-    #[inline]
-    fn add(&self, rhs: &V) -> Vec<T> {
-        self.as_slice() + rhs.as_slice()
-    }
-}
-
 /// Extension methods for vector slices with cloneable elements
 pub trait CloneableVector<T> {
     /// Copy `self` into a new owned vector
@@ -313,6 +293,11 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
     /// Returns a copy of `v`.
     #[inline]
     fn to_owned(&self) -> ~[T] {
+        use RawVec = core::raw::Vec;
+        use rt::global_heap::{malloc_raw, exchange_free};
+        use num::{CheckedAdd, CheckedMul};
+        use option::Expect;
+
         let len = self.len();
         let data_size = len.checked_mul(&mem::size_of::<T>());
         let data_size = data_size.expect("overflow in to_owned()");
@@ -2142,15 +2127,6 @@ mod bench {
         })
     }
 
-    #[bench]
-    fn add(b: &mut Bencher) {
-        let xs: &[int] = [5, ..10];
-        let ys: &[int] = [5, ..10];
-        b.iter(|| {
-            xs + ys;
-        });
-    }
-
     #[bench]
     fn concat(b: &mut Bencher) {
         let xss: Vec<Vec<uint>> = Vec::from_fn(100, |i| range(0, i).collect());
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index fb2d85657e8..fb3dcc97287 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -667,12 +667,11 @@ impl<'a> fmt::Show for MaybeOwned<'a> {
 /// Unsafe operations
 pub mod raw {
     use cast;
-    use iter::Iterator;
     use libc;
     use ptr::RawPtr;
     use raw::Slice;
-    use slice::ImmutableVector;
-    use str::is_utf8;
+    use slice::CloneableVector;
+    use str::{is_utf8, StrAllocating};
 
     pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes};
     pub use core::str::raw::{slice_unchecked};
@@ -821,8 +820,10 @@ pub trait StrAllocating: Str {
     /// Copy a slice into a new owned str.
     #[inline]
     fn to_owned(&self) -> ~str {
+        use slice::Vector;
+
         unsafe {
-            ::cast::transmute(self.as_bytes().to_owned())
+            ::cast::transmute(self.as_slice().as_bytes().to_owned())
         }
     }