about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2013-06-10 17:42:24 +1000
committerHuon Wilson <dbau.pp+github@gmail.com>2013-06-10 23:02:55 +1000
commit1553874149c3c37b94d75e9122092b131ba74c77 (patch)
treeea25b52a29e038180659148f319410843b13fa02 /src
parenta64e886e3c1dd38473fd7711933557f1b97a9036 (diff)
downloadrust-1553874149c3c37b94d75e9122092b131ba74c77.tar.gz
rust-1553874149c3c37b94d75e9122092b131ba74c77.zip
std: convert str::reserve* to methods, and methodise str::push_*.
Diffstat (limited to 'src')
-rw-r--r--src/libextra/base64.rs26
-rw-r--r--src/libextra/json.rs22
-rw-r--r--src/libextra/net_url.rs26
-rw-r--r--src/libextra/rope.rs4
-rw-r--r--src/libextra/semver.rs2
-rw-r--r--src/libextra/time.rs2
-rw-r--r--src/librustc/middle/astencode.rs2
-rw-r--r--src/librustc/middle/borrowck/mod.rs18
-rw-r--r--src/librustc/middle/dataflow.rs6
-rw-r--r--src/libstd/str.rs332
-rw-r--r--src/libstd/unstable/lang.rs6
-rw-r--r--src/libsyntax/ext/fmt.rs3
-rw-r--r--src/libsyntax/parse/comments.rs6
-rw-r--r--src/libsyntax/parse/lexer.rs29
-rw-r--r--src/test/bench/shootout-fasta.rs2
-rw-r--r--src/test/run-pass/issue-4241.rs6
-rw-r--r--src/test/run-pass/move-out-of-field.rs2
-rw-r--r--src/test/run-pass/utf8_chars.rs2
18 files changed, 248 insertions, 248 deletions
diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs
index b8f3a267d2d..62d4a32b8e2 100644
--- a/src/libextra/base64.rs
+++ b/src/libextra/base64.rs
@@ -49,7 +49,7 @@ impl<'self> ToBase64 for &'self [u8] {
     fn to_base64(&self) -> ~str {
         let mut s = ~"";
         let len = self.len();
-        str::reserve(&mut s, ((len + 3u) / 4u) * 3u);
+        s.reserve(((len + 3u) / 4u) * 3u);
 
         let mut i = 0u;
 
@@ -59,10 +59,10 @@ impl<'self> ToBase64 for &'self [u8] {
                     (self[i + 2u] as uint);
 
             // This 24-bit number gets separated into four 6-bit numbers.
-            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
-            str::push_char(&mut s, CHARS[n & 63u]);
+            s.push_char(CHARS[(n >> 18u) & 63u]);
+            s.push_char(CHARS[(n >> 12u) & 63u]);
+            s.push_char(CHARS[(n >> 6u) & 63u]);
+            s.push_char(CHARS[n & 63u]);
 
             i += 3u;
         }
@@ -73,18 +73,18 @@ impl<'self> ToBase64 for &'self [u8] {
           0 => (),
           1 => {
             let n = (self[i] as uint) << 16u;
-            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
-            str::push_char(&mut s, '=');
-            str::push_char(&mut s, '=');
+            s.push_char(CHARS[(n >> 18u) & 63u]);
+            s.push_char(CHARS[(n >> 12u) & 63u]);
+            s.push_char('=');
+            s.push_char('=');
           }
           2 => {
             let n = (self[i] as uint) << 16u |
                 (self[i + 1u] as uint) << 8u;
-            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
-            str::push_char(&mut s, '=');
+            s.push_char(CHARS[(n >> 18u) & 63u]);
+            s.push_char(CHARS[(n >> 12u) & 63u]);
+            s.push_char(CHARS[(n >> 6u) & 63u]);
+            s.push_char('=');
           }
           _ => fail!("Algebra is broken, please alert the math police")
         }
diff --git a/src/libextra/json.rs b/src/libextra/json.rs
index 30a2b5f8627..1e9ec48aff3 100644
--- a/src/libextra/json.rs
+++ b/src/libextra/json.rs
@@ -79,7 +79,7 @@ fn escape_str(s: &str) -> ~str {
 
 fn spaces(n: uint) -> ~str {
     let mut ss = ~"";
-    for n.times { str::push_str(&mut ss, " "); }
+    for n.times { ss.push_str(" "); }
     return ss;
 }
 
@@ -712,14 +712,14 @@ impl Parser {
 
             if (escape) {
                 match self.ch {
-                  '"' => str::push_char(&mut res, '"'),
-                  '\\' => str::push_char(&mut res, '\\'),
-                  '/' => str::push_char(&mut res, '/'),
-                  'b' => str::push_char(&mut res, '\x08'),
-                  'f' => str::push_char(&mut res, '\x0c'),
-                  'n' => str::push_char(&mut res, '\n'),
-                  'r' => str::push_char(&mut res, '\r'),
-                  't' => str::push_char(&mut res, '\t'),
+                  '"' => res.push_char('"'),
+                  '\\' => res.push_char('\\'),
+                  '/' => res.push_char('/'),
+                  'b' => res.push_char('\x08'),
+                  'f' => res.push_char('\x0c'),
+                  'n' => res.push_char('\n'),
+                  'r' => res.push_char('\r'),
+                  't' => res.push_char('\t'),
                   'u' => {
                       // Parse \u1234.
                       let mut i = 0u;
@@ -748,7 +748,7 @@ impl Parser {
                             ~"invalid \\u escape (not four digits)");
                       }
 
-                      str::push_char(&mut res, n as char);
+                      res.push_char(n as char);
                   }
                   _ => return self.error(~"invalid escape")
                 }
@@ -760,7 +760,7 @@ impl Parser {
                     self.bump();
                     return Ok(res);
                 }
-                str::push_char(&mut res, self.ch);
+                res.push_char(self.ch);
             }
         }
 
diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs
index 6fd6fa3acd9..30d55721efb 100644
--- a/src/libextra/net_url.rs
+++ b/src/libextra/net_url.rs
@@ -81,7 +81,7 @@ fn encode_inner(s: &str, full_url: bool) -> ~str {
               'a' .. 'z' |
               '0' .. '9' |
               '-' | '.' | '_' | '~' => {
-                str::push_char(&mut out, ch);
+                out.push_char(ch);
               }
               _ => {
                   if full_url {
@@ -92,7 +92,7 @@ fn encode_inner(s: &str, full_url: bool) -> ~str {
                       // sub-delims:
                       '!' | '$' | '&' | '"' | '(' | ')' | '*' |
                       '+' | ',' | ';' | '=' => {
-                        str::push_char(&mut out, ch);
+                        out.push_char(ch);
                       }
 
                       _ => out += fmt!("%%%X", ch as uint)
@@ -148,18 +148,18 @@ fn decode_inner(s: &str, full_url: bool) -> ~str {
                       // sub-delims:
                       '!' | '$' | '&' | '"' | '(' | ')' | '*' |
                       '+' | ',' | ';' | '=' => {
-                        str::push_char(&mut out, '%');
-                        str::push_char(&mut out, bytes[0u] as char);
-                        str::push_char(&mut out, bytes[1u] as char);
+                        out.push_char('%');
+                        out.push_char(bytes[0u] as char);
+                        out.push_char(bytes[1u] as char);
                       }
 
-                      ch => str::push_char(&mut out, ch)
+                      ch => out.push_char(ch)
                     }
                 } else {
-                      str::push_char(&mut out, ch);
+                      out.push_char(ch);
                 }
               }
-              ch => str::push_char(&mut out, ch)
+              ch => out.push_char(ch)
             }
         }
 
@@ -191,9 +191,9 @@ fn encode_plus(s: &str) -> ~str {
             let ch = rdr.read_byte() as char;
             match ch {
               'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '.' | '-' => {
-                str::push_char(&mut out, ch);
+                out.push_char(ch);
               }
-              ' ' => str::push_char(&mut out, '+'),
+              ' ' => out.push_char('+'),
               _ => out += fmt!("%%%X", ch as uint)
             }
         }
@@ -216,7 +216,7 @@ pub fn encode_form_urlencoded(m: &HashMap<~str, ~[~str]>) -> ~str {
             if first {
                 first = false;
             } else {
-                str::push_char(&mut out, '&');
+                out.push_char('&');
                 first = false;
             }
 
@@ -267,9 +267,9 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
                     };
 
                     if parsing_key {
-                        str::push_char(&mut key, ch)
+                        key.push_char(ch)
                     } else {
-                        str::push_char(&mut value, ch)
+                        value.push_char(ch)
                     }
                 }
             }
diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs
index 9ae8c47ae3c..de78e0a6eeb 100644
--- a/src/libextra/rope.rs
+++ b/src/libextra/rope.rs
@@ -1289,9 +1289,7 @@ mod tests {
             fn aux(str: &mut ~str, node: @node::Node) {
                 match (*node) {
                     node::Leaf(x) => {
-                        str::push_str(
-                            str,
-                            x.content.slice(x.byte_offset, x.byte_offset + x.byte_len));
+                        str.push_str(x.content.slice(x.byte_offset, x.byte_offset + x.byte_len));
                     }
                     node::Concat(ref x) => {
                         aux(str, x.left);
diff --git a/src/libextra/semver.rs b/src/libextra/semver.rs
index 36ebd10ae17..dad08075238 100644
--- a/src/libextra/semver.rs
+++ b/src/libextra/semver.rs
@@ -149,7 +149,7 @@ fn take_nonempty_prefix(rdr: @io::Reader,
     let mut buf = ~"";
     let mut ch = ch;
     while pred(ch) {
-        str::push_char(&mut buf, ch);
+        buf.push_char(ch);
         ch = rdr.read_char();
     }
     if buf.is_empty() {
diff --git a/src/libextra/time.rs b/src/libextra/time.rs
index f545b28c507..fea5cb560ac 100644
--- a/src/libextra/time.rs
+++ b/src/libextra/time.rs
@@ -851,7 +851,7 @@ priv fn do_strftime(format: &str, tm: &Tm) -> ~str {
         while !rdr.eof() {
             match rdr.read_char() {
                 '%' => buf += parse_type(rdr.read_char(), tm),
-                ch => str::push_char(&mut buf, ch)
+                ch => buf.push_char(ch)
             }
         }
     }
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 32a2bf22f27..18946ee2d79 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -980,7 +980,7 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
         fn type_string(doc: ebml::Doc) -> ~str {
             let mut str = ~"";
             for uint::range(doc.start, doc.end) |i| {
-                str::push_char(&mut str, doc.data[i] as char);
+                str.push_char(doc.data[i] as char);
             }
             str
         }
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index fa3bae3f5ac..b0b9c9f7efb 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -694,9 +694,9 @@ impl BorrowckCtxt {
                                                  out: &mut ~str) {
         match *loan_path {
             LpExtend(_, _, LpDeref) => {
-                str::push_char(out, '(');
+                out.push_char('(');
                 self.append_loan_path_to_str(loan_path, out);
-                str::push_char(out, ')');
+                out.push_char(')');
             }
             LpExtend(_, _, LpInterior(_)) |
             LpVar(_) => {
@@ -712,7 +712,7 @@ impl BorrowckCtxt {
             LpVar(id) => {
                 match self.tcx.items.find(&id) {
                     Some(&ast_map::node_local(ref ident)) => {
-                        str::push_str(out, *token::ident_to_str(ident));
+                        out.push_str(*token::ident_to_str(ident));
                     }
                     r => {
                         self.tcx.sess.bug(
@@ -726,23 +726,23 @@ impl BorrowckCtxt {
                 self.append_loan_path_to_str_from_interior(lp_base, out);
                 match fname {
                     mc::NamedField(ref fname) => {
-                        str::push_char(out, '.');
-                        str::push_str(out, *token::ident_to_str(fname));
+                        out.push_char('.');
+                        out.push_str(*token::ident_to_str(fname));
                     }
                     mc::PositionalField(idx) => {
-                        str::push_char(out, '#'); // invent a notation here
-                        str::push_str(out, idx.to_str());
+                        out.push_char('#'); // invent a notation here
+                        out.push_str(idx.to_str());
                     }
                 }
             }
 
             LpExtend(lp_base, _, LpInterior(mc::InteriorElement(_))) => {
                 self.append_loan_path_to_str_from_interior(lp_base, out);
-                str::push_str(out, "[]");
+                out.push_str("[]");
             }
 
             LpExtend(lp_base, _, LpDeref) => {
-                str::push_char(out, '*');
+                out.push_char('*');
                 self.append_loan_path_to_str(lp_base, out);
             }
         }
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 1f9fff14ba2..e2d88e3c768 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -947,13 +947,13 @@ fn bits_to_str(words: &[uint]) -> ~str {
     for words.each |&word| {
         let mut v = word;
         for uint::range(0, uint::bytes) |_| {
-            str::push_char(&mut result, sep);
-            str::push_str(&mut result, fmt!("%02x", v & 0xFF));
+            result.push_char(sep);
+            result.push_str(fmt!("%02x", v & 0xFF));
             v >>= 8;
             sep = '-';
         }
     }
-    str::push_char(&mut result, ']');
+    result.push_char(']');
     return result;
 }
 
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index 7ae59e524a0..5455edc2586 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -139,121 +139,35 @@ pub fn from_byte(b: u8) -> ~str {
     unsafe { ::cast::transmute(~[b, 0u8]) }
 }
 
-/// Appends a character at the end of a string
-pub fn push_char(s: &mut ~str, ch: char) {
-    unsafe {
-        let code = ch as uint;
-        let nb = if code < max_one_b { 1u }
-        else if code < max_two_b { 2u }
-        else if code < max_three_b { 3u }
-        else if code < max_four_b { 4u }
-        else if code < max_five_b { 5u }
-        else { 6u };
-        let len = s.len();
-        let new_len = len + nb;
-        reserve_at_least(&mut *s, new_len);
-        let off = len;
-        do as_buf(*s) |buf, _len| {
-            let buf: *mut u8 = ::cast::transmute(buf);
-            match nb {
-                1u => {
-                    *ptr::mut_offset(buf, off) = code as u8;
-                }
-                2u => {
-                    *ptr::mut_offset(buf, off) = (code >> 6u & 31u | tag_two_b) as u8;
-                    *ptr::mut_offset(buf, off + 1u) = (code & 63u | tag_cont) as u8;
-                }
-                3u => {
-                    *ptr::mut_offset(buf, off) = (code >> 12u & 15u | tag_three_b) as u8;
-                    *ptr::mut_offset(buf, off + 1u) = (code >> 6u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 2u) = (code & 63u | tag_cont) as u8;
-                }
-                4u => {
-                    *ptr::mut_offset(buf, off) = (code >> 18u & 7u | tag_four_b) as u8;
-                    *ptr::mut_offset(buf, off + 1u) = (code >> 12u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 2u) = (code >> 6u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 3u) = (code & 63u | tag_cont) as u8;
-                }
-                5u => {
-                    *ptr::mut_offset(buf, off) = (code >> 24u & 3u | tag_five_b) as u8;
-                    *ptr::mut_offset(buf, off + 1u) = (code >> 18u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 2u) = (code >> 12u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 3u) = (code >> 6u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 4u) = (code & 63u | tag_cont) as u8;
-                }
-                6u => {
-                    *ptr::mut_offset(buf, off) = (code >> 30u & 1u | tag_six_b) as u8;
-                    *ptr::mut_offset(buf, off + 1u) = (code >> 24u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 2u) = (code >> 18u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 3u) = (code >> 12u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 4u) = (code >> 6u & 63u | tag_cont) as u8;
-                    *ptr::mut_offset(buf, off + 5u) = (code & 63u | tag_cont) as u8;
-                }
-                _ => {}
-            }
-        }
-        raw::set_len(s, new_len);
-    }
-}
-
 /// Convert a char to a string
 pub fn from_char(ch: char) -> ~str {
     let mut buf = ~"";
-    push_char(&mut buf, ch);
+    buf.push_char(ch);
     buf
 }
 
 /// Convert a vector of chars to a string
 pub fn from_chars(chs: &[char]) -> ~str {
     let mut buf = ~"";
-    reserve(&mut buf, chs.len());
+    buf.reserve(chs.len());
     for chs.each |ch| {
-        push_char(&mut buf, *ch);
+        buf.push_char(*ch)
     }
     buf
 }
 
-/// Appends a string slice to the back of a string, without overallocating
-#[inline(always)]
-pub fn push_str_no_overallocate(lhs: &mut ~str, rhs: &str) {
-    unsafe {
-        let llen = lhs.len();
-        let rlen = rhs.len();
-        reserve(&mut *lhs, llen + rlen);
-        do as_buf(*lhs) |lbuf, _llen| {
-            do as_buf(rhs) |rbuf, _rlen| {
-                let dst = ptr::offset(lbuf, llen);
-                let dst = ::cast::transmute_mut_unsafe(dst);
-                ptr::copy_memory(dst, rbuf, rlen);
-            }
-        }
-        raw::set_len(lhs, llen + rlen);
-    }
-}
-
-/// Appends a string slice to the back of a string
-#[inline(always)]
+/// A function version of the `.push_str`, required for `fmt!` during
+/// the bootstrap. Use `lhs.push_str(rhs)` instead of this.
+#[doc="hidden"]
 pub fn push_str(lhs: &mut ~str, rhs: &str) {
-    unsafe {
-        let llen = lhs.len();
-        let rlen = rhs.len();
-        reserve_at_least(&mut *lhs, llen + rlen);
-        do as_buf(*lhs) |lbuf, _llen| {
-            do as_buf(rhs) |rbuf, _rlen| {
-                let dst = ptr::offset(lbuf, llen);
-                let dst = ::cast::transmute_mut_unsafe(dst);
-                ptr::copy_memory(dst, rbuf, rlen);
-            }
-        }
-        raw::set_len(lhs, llen + rlen);
-    }
+    lhs.push_str(rhs)
 }
 
 /// Concatenate two strings together
 #[inline(always)]
 pub fn append(lhs: ~str, rhs: &str) -> ~str {
     let mut v = lhs;
-    push_str_no_overallocate(&mut v, rhs);
+    v.push_str_no_overallocate(rhs);
     v
 }
 
@@ -286,7 +200,7 @@ impl<'self> StrVector for &'self [~str] {
         }
         let mut s = ~"";
 
-        reserve(&mut s, len);
+        s.reserve(len);
 
         unsafe {
             do as_buf(s) |buf, _| {
@@ -319,7 +233,7 @@ impl<'self> StrVector for &'self [~str] {
         let mut s = ~"";
         let mut first = true;
 
-        reserve(&mut s, len);
+        s.reserve(len);
 
         unsafe {
             do as_buf(s) |buf, _| {
@@ -358,7 +272,7 @@ impl<'self> StrVector for &'self [&'self str] {
         }
         let mut s = ~"";
 
-        reserve(&mut s, len);
+        s.reserve(len);
 
         unsafe {
             do as_buf(s) |buf, _| {
@@ -391,7 +305,7 @@ impl<'self> StrVector for &'self [&'self str] {
         let mut s = ~"";
         let mut first = true;
 
-        reserve(&mut s, len);
+        s.reserve(len);
 
         unsafe {
             do as_buf(s) |buf, _| {
@@ -425,7 +339,7 @@ pub fn repeat(ss: &str, nn: uint) -> ~str {
         let mut ret = ~"";
         // ignore the NULL terminator
         let len = len - 1;
-        reserve(&mut ret, nn * len);
+        ret.reserve(nn * len);
 
         unsafe {
             do as_buf(ret) |rbuf, _len| {
@@ -1148,9 +1062,9 @@ Section: Iterating through strings
 /// Apply a function to each character
 pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str {
     let mut result = ~"";
-    reserve(&mut result, ss.len());
+    result.reserve(ss.len());
     for ss.iter().advance |cc| {
-        str::push_char(&mut result, ff(cc));
+        result.push_char(ff(cc));
     }
     result
 }
@@ -1325,8 +1239,8 @@ pub fn utf16_chars(v: &[u16], f: &fn(char)) {
  */
 pub fn from_utf16(v: &[u16]) -> ~str {
     let mut buf = ~"";
-    reserve(&mut buf, v.len());
-    utf16_chars(v, |ch| push_char(&mut buf, ch));
+    buf.reserve(v.len());
+    utf16_chars(v, |ch| buf.push_char(ch));
     buf
 }
 
@@ -1336,7 +1250,7 @@ pub fn from_utf16(v: &[u16]) -> ~str {
  */
 pub fn with_capacity(capacity: uint) -> ~str {
     let mut buf = ~"";
-    reserve(&mut buf, capacity);
+    buf.reserve(capacity);
     buf
 }
 
@@ -1660,54 +1574,6 @@ pub fn subslice_offset(outer: &str, inner: &str) -> uint {
     }
 }
 
-/**
- * Reserves capacity for exactly `n` bytes in the given string, not including
- * the null terminator.
- *
- * Assuming single-byte characters, the resulting string will be large
- * enough to hold a string of length `n`. To account for the null terminator,
- * the underlying buffer will have the size `n` + 1.
- *
- * If the capacity for `s` is already equal to or greater than the requested
- * capacity, then no action is taken.
- *
- * # Arguments
- *
- * * s - A string
- * * n - The number of bytes to reserve space for
- */
-#[inline(always)]
-pub fn reserve(s: &mut ~str, n: uint) {
-    unsafe {
-        let v: *mut ~[u8] = cast::transmute(s);
-        vec::reserve(&mut *v, n + 1);
-    }
-}
-
-/**
- * Reserves capacity for at least `n` bytes in the given string, not including
- * the null terminator.
- *
- * Assuming single-byte characters, the resulting string will be large
- * enough to hold a string of length `n`. To account for the null terminator,
- * the underlying buffer will have the size `n` + 1.
- *
- * This function will over-allocate in order to amortize the allocation costs
- * in scenarios where the caller may need to repeatedly reserve additional
- * space.
- *
- * If the capacity for `s` is already equal to or greater than the requested
- * capacity, then no action is taken.
- *
- * # Arguments
- *
- * * s - A string
- * * n - The number of bytes to reserve space for
- */
-#[inline(always)]
-pub fn reserve_at_least(s: &mut ~str, n: uint) {
-    reserve(s, uint::next_power_of_two(n + 1u) - 1u)
-}
 
 /**
  * Returns the number of single-byte characters the string can hold without
@@ -1724,9 +1590,9 @@ pub fn capacity(s: &const ~str) -> uint {
 /// Escape each char in `s` with char::escape_default.
 pub fn escape_default(s: &str) -> ~str {
     let mut out: ~str = ~"";
-    reserve_at_least(&mut out, s.len());
+    out.reserve_at_least(s.len());
     for s.iter().advance |c| {
-        push_str(&mut out, char::escape_default(c));
+        out.push_str(char::escape_default(c));
     }
     out
 }
@@ -1734,9 +1600,9 @@ pub fn escape_default(s: &str) -> ~str {
 /// Escape each char in `s` with char::escape_unicode.
 pub fn escape_unicode(s: &str) -> ~str {
     let mut out: ~str = ~"";
-    reserve_at_least(&mut out, s.len());
+    out.reserve_at_least(s.len());
     for s.iter().advance |c| {
-        push_str(&mut out, char::escape_unicode(c));
+        out.push_str(char::escape_unicode(c));
     }
     out
 }
@@ -1747,7 +1613,7 @@ pub mod raw {
     use libc;
     use ptr;
     use str::raw;
-    use str::{as_buf, is_utf8, reserve_at_least};
+    use str::{as_buf, is_utf8};
     use vec;
 
     /// Create a Rust string from a null-terminated *u8 buffer
@@ -1859,7 +1725,7 @@ pub mod raw {
     /// Appends a byte to a string. (Not UTF-8 safe).
     pub unsafe fn push_byte(s: &mut ~str, b: u8) {
         let new_len = s.len() + 1;
-        reserve_at_least(&mut *s, new_len);
+        s.reserve_at_least(new_len);
         do as_buf(*s) |buf, len| {
             let buf: *mut u8 = ::cast::transmute(buf);
             *ptr::mut_offset(buf, len) = b;
@@ -1870,7 +1736,7 @@ pub mod raw {
     /// Appends a vector of bytes to a string. (Not UTF-8 safe).
     unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) {
         let new_len = s.len() + bytes.len();
-        reserve_at_least(&mut *s, new_len);
+        s.reserve_at_least(new_len);
         for bytes.each |byte| { push_byte(&mut *s, *byte); }
     }
 
@@ -2274,18 +2140,154 @@ impl<'self> StrSlice<'self> for &'self str {
 
 #[allow(missing_doc)]
 pub trait OwnedStr {
-    fn push_str(&mut self, v: &str);
+    fn push_str_no_overallocate(&mut self, rhs: &str);
+    fn push_str(&mut self, rhs: &str);
     fn push_char(&mut self, c: char);
+    fn reserve(&mut self, n: uint);
+    fn reserve_at_least(&mut self, n: uint);
 }
 
 impl OwnedStr for ~str {
+    /// Appends a string slice to the back of a string, without overallocating
+    #[inline(always)]
+    fn push_str_no_overallocate(&mut self, rhs: &str) {
+        unsafe {
+            let llen = self.len();
+            let rlen = rhs.len();
+            self.reserve(llen + rlen);
+            do as_buf(*self) |lbuf, _llen| {
+                do as_buf(rhs) |rbuf, _rlen| {
+                    let dst = ptr::offset(lbuf, llen);
+                    let dst = ::cast::transmute_mut_unsafe(dst);
+                    ptr::copy_memory(dst, rbuf, rlen);
+                }
+            }
+            raw::set_len(self, llen + rlen);
+        }
+    }
+
+    /// Appends a string slice to the back of a string
     #[inline]
-    fn push_str(&mut self, v: &str) {
-        push_str(self, v);
+    fn push_str(&mut self, rhs: &str) {
+        unsafe {
+            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| {
+                    let dst = ptr::offset(lbuf, llen);
+                    let dst = ::cast::transmute_mut_unsafe(dst);
+                    ptr::copy_memory(dst, rbuf, rlen);
+                }
+            }
+            raw::set_len(self, llen + rlen);
+        }
     }
+    /// Appends a character to the back of a string
     #[inline]
     fn push_char(&mut self, c: char) {
-        push_char(self, c);
+        unsafe {
+            let code = c as uint;
+            let nb = if code < max_one_b { 1u }
+            else if code < max_two_b { 2u }
+            else if code < max_three_b { 3u }
+            else if code < max_four_b { 4u }
+            else if code < max_five_b { 5u }
+            else { 6u };
+            let len = self.len();
+            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);
+                match nb {
+                    1u => {
+                        *ptr::mut_offset(buf, off) = code as u8;
+                    }
+                    2u => {
+                        *ptr::mut_offset(buf, off) = (code >> 6u & 31u | tag_two_b) as u8;
+                        *ptr::mut_offset(buf, off + 1u) = (code & 63u | tag_cont) as u8;
+                    }
+                    3u => {
+                        *ptr::mut_offset(buf, off) = (code >> 12u & 15u | tag_three_b) as u8;
+                        *ptr::mut_offset(buf, off + 1u) = (code >> 6u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 2u) = (code & 63u | tag_cont) as u8;
+                    }
+                    4u => {
+                        *ptr::mut_offset(buf, off) = (code >> 18u & 7u | tag_four_b) as u8;
+                        *ptr::mut_offset(buf, off + 1u) = (code >> 12u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 2u) = (code >> 6u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 3u) = (code & 63u | tag_cont) as u8;
+                    }
+                    5u => {
+                        *ptr::mut_offset(buf, off) = (code >> 24u & 3u | tag_five_b) as u8;
+                        *ptr::mut_offset(buf, off + 1u) = (code >> 18u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 2u) = (code >> 12u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 3u) = (code >> 6u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 4u) = (code & 63u | tag_cont) as u8;
+                    }
+                    6u => {
+                        *ptr::mut_offset(buf, off) = (code >> 30u & 1u | tag_six_b) as u8;
+                        *ptr::mut_offset(buf, off + 1u) = (code >> 24u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 2u) = (code >> 18u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 3u) = (code >> 12u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 4u) = (code >> 6u & 63u | tag_cont) as u8;
+                        *ptr::mut_offset(buf, off + 5u) = (code & 63u | tag_cont) as u8;
+                    }
+                    _ => {}
+                }
+            }
+            raw::set_len(self, new_len);
+        }
+    }
+
+    /**
+     * Reserves capacity for exactly `n` bytes in the given string, not including
+     * the null terminator.
+     *
+     * Assuming single-byte characters, the resulting string will be large
+     * enough to hold a string of length `n`. To account for the null terminator,
+     * the underlying buffer will have the size `n` + 1.
+     *
+     * If the capacity for `s` is already equal to or greater than the requested
+     * capacity, then no action is taken.
+     *
+     * # Arguments
+     *
+     * * s - A string
+     * * n - The number of bytes to reserve space for
+     */
+    #[inline(always)]
+    pub fn reserve(&mut self, n: uint) {
+        unsafe {
+            let v: *mut ~[u8] = cast::transmute(self);
+            vec::reserve(&mut *v, n + 1);
+        }
+    }
+
+    /**
+     * Reserves capacity for at least `n` bytes in the given string, not including
+     * the null terminator.
+     *
+     * Assuming single-byte characters, the resulting string will be large
+     * enough to hold a string of length `n`. To account for the null terminator,
+     * the underlying buffer will have the size `n` + 1.
+     *
+     * This function will over-allocate in order to amortize the allocation costs
+     * in scenarios where the caller may need to repeatedly reserve additional
+     * space.
+     *
+     * If the capacity for `s` is already equal to or greater than the requested
+     * capacity, then no action is taken.
+     *
+     * # Arguments
+     *
+     * * s - A string
+     * * n - The number of bytes to reserve space for
+     */
+    #[inline(always)]
+    fn reserve_at_least(&mut self, n: uint) {
+        self.reserve(uint::next_power_of_two(n + 1u) - 1u)
     }
 }
 
@@ -2582,13 +2584,13 @@ mod tests {
         fn a_million_letter_a() -> ~str {
             let mut i = 0;
             let mut rs = ~"";
-            while i < 100000 { push_str(&mut rs, "aaaaaaaaaa"); i += 1; }
+            while i < 100000 { rs.push_str("aaaaaaaaaa"); i += 1; }
             rs
         }
         fn half_a_million_letter_a() -> ~str {
             let mut i = 0;
             let mut rs = ~"";
-            while i < 100000 { push_str(&mut rs, "aaaaa"); i += 1; }
+            while i < 100000 { rs.push_str("aaaaa"); i += 1; }
             rs
         }
         let letters = a_million_letter_a();
diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs
index cd3e0cf303e..e75cf2c01c6 100644
--- a/src/libstd/unstable/lang.rs
+++ b/src/libstd/unstable/lang.rs
@@ -136,10 +136,10 @@ unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) {
             let mut sep = " at ";
             for borrow_list.rev_iter().advance |entry| {
                 if entry.box == box {
-                    str::push_str(&mut msg, sep);
+                    msg.push_str(sep);
                     let filename = str::raw::from_c_str(entry.file);
-                    str::push_str(&mut msg, filename);
-                    str::push_str(&mut msg, fmt!(":%u", entry.line as uint));
+                    msg.push_str(filename);
+                    msg.push_str(fmt!(":%u", entry.line as uint));
                     sep = " and at ";
                 }
             }
diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs
index 6d0c499f2c8..b2ec3684b70 100644
--- a/src/libsyntax/ext/fmt.rs
+++ b/src/libsyntax/ext/fmt.rs
@@ -276,6 +276,9 @@ fn pieces_to_expr(cx: @ExtCtxt, sp: span,
                     stms.push(cx.stmt_let(fmt_sp, npieces > 1,
                                           ident, cx.expr_str_uniq(fmt_sp, s)));
                 } else {
+                    // we call the push_str function because the
+                    // bootstrap doesnt't seem to work if we call the
+                    // method.
                     let args = ~[cx.expr_mut_addr_of(fmt_sp, buf()), cx.expr_str(fmt_sp, s)];
                     let call = cx.expr_call_global(fmt_sp,
                                                    ~[core_ident,
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index a715ede7664..89fd5c3762a 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -125,7 +125,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str {
 fn read_to_eol(rdr: @mut StringReader) -> ~str {
     let mut val = ~"";
     while rdr.curr != '\n' && !is_eof(rdr) {
-        str::push_char(&mut val, rdr.curr);
+        val.push_char(rdr.curr);
         bump(rdr);
     }
     if rdr.curr == '\n' { bump(rdr); }
@@ -237,7 +237,7 @@ fn read_block_comment(rdr: @mut StringReader,
     // doc-comments are not really comments, they are attributes
     if rdr.curr == '*' || rdr.curr == '!' {
         while !(rdr.curr == '*' && nextch(rdr) == '/') && !is_eof(rdr) {
-            str::push_char(&mut curr_line, rdr.curr);
+            curr_line.push_char(rdr.curr);
             bump(rdr);
         }
         if !is_eof(rdr) {
@@ -261,7 +261,7 @@ fn read_block_comment(rdr: @mut StringReader,
                 curr_line = ~"";
                 bump(rdr);
             } else {
-                str::push_char(&mut curr_line, rdr.curr);
+                curr_line.push_char(rdr.curr);
                 if rdr.curr == '/' && nextch(rdr) == '*' {
                     bump(rdr);
                     bump(rdr);
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 2dc8008f8ec..809a222352f 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -358,11 +358,11 @@ fn scan_exponent(rdr: @mut StringReader) -> Option<~str> {
     let mut c = rdr.curr;
     let mut rslt = ~"";
     if c == 'e' || c == 'E' {
-        str::push_char(&mut rslt, c);
+        rslt.push_char(c);
         bump(rdr);
         c = rdr.curr;
         if c == '-' || c == '+' {
-            str::push_char(&mut rslt, c);
+            rslt.push_char(c);
             bump(rdr);
         }
         let exponent = scan_digits(rdr, 10u);
@@ -379,7 +379,7 @@ fn scan_digits(rdr: @mut StringReader, radix: uint) -> ~str {
         if c == '_' { bump(rdr); loop; }
         match char::to_digit(c, radix) {
           Some(_) => {
-            str::push_char(&mut rslt, c);
+            rslt.push_char(c);
             bump(rdr);
           }
           _ => return rslt
@@ -721,31 +721,28 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
                 let escaped = rdr.curr;
                 bump(rdr);
                 match escaped {
-                  'n' => str::push_char(&mut accum_str, '\n'),
-                  'r' => str::push_char(&mut accum_str, '\r'),
-                  't' => str::push_char(&mut accum_str, '\t'),
-                  '\\' => str::push_char(&mut accum_str, '\\'),
-                  '\'' => str::push_char(&mut accum_str, '\''),
-                  '"' => str::push_char(&mut accum_str, '"'),
+                  'n' => accum_str.push_char('\n'),
+                  'r' => accum_str.push_char('\r'),
+                  't' => accum_str.push_char('\t'),
+                  '\\' => accum_str.push_char('\\'),
+                  '\'' => accum_str.push_char('\''),
+                  '"' => accum_str.push_char('"'),
                   '\n' => consume_whitespace(rdr),
                   'x' => {
-                    str::push_char(&mut accum_str,
-                                   scan_numeric_escape(rdr, 2u));
+                    accum_str.push_char(scan_numeric_escape(rdr, 2u));
                   }
                   'u' => {
-                    str::push_char(&mut accum_str,
-                                   scan_numeric_escape(rdr, 4u));
+                    accum_str.push_char(scan_numeric_escape(rdr, 4u));
                   }
                   'U' => {
-                    str::push_char(&mut accum_str,
-                                   scan_numeric_escape(rdr, 8u));
+                    accum_str.push_char(scan_numeric_escape(rdr, 8u));
                   }
                   c2 => {
                     rdr.fatal(fmt!("unknown string escape: %d", c2 as int));
                   }
                 }
               }
-              _ => str::push_char(&mut accum_str, ch)
+              _ => accum_str.push_char(ch)
             }
         }
         bump(rdr);
diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs
index c497a30ec5f..5c77e698bec 100644
--- a/src/test/bench/shootout-fasta.rs
+++ b/src/test/bench/shootout-fasta.rs
@@ -79,7 +79,7 @@ fn make_random_fasta(wr: @io::Writer,
     };
     let mut op: ~str = ~"";
     for uint::range(0u, n as uint) |_i| {
-        str::push_char(&mut op, select_random(myrandom_next(rng, 100u32),
+        op.push_char(select_random(myrandom_next(rng, 100u32),
                                               copy genelist));
         if op.len() >= LINE_LENGTH() {
             wr.write_line(op);
diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs
index 4aa604160d9..972b9c7a525 100644
--- a/src/test/run-pass/issue-4241.rs
+++ b/src/test/run-pass/issue-4241.rs
@@ -95,10 +95,10 @@ priv fn parse_response(io: @io::Reader) -> Result {
 
 priv fn cmd_to_str(cmd: ~[~str]) -> ~str {
   let mut res = ~"*";
-  str::push_str(&mut res, cmd.len().to_str());
-  str::push_str(&mut res, "\r\n");
+  res.push_str(cmd.len().to_str());
+  res.push_str("\r\n");
     for cmd.each |s| {
-    str::push_str(&mut res, str::concat(~[~"$", s.len().to_str(), ~"\r\n",
+    res.push_str(str::concat(~[~"$", s.len().to_str(), ~"\r\n",
                                           copy *s, ~"\r\n"]));
     }
   res
diff --git a/src/test/run-pass/move-out-of-field.rs b/src/test/run-pass/move-out-of-field.rs
index b6485348a51..a3c2872803a 100644
--- a/src/test/run-pass/move-out-of-field.rs
+++ b/src/test/run-pass/move-out-of-field.rs
@@ -6,7 +6,7 @@ struct StringBuffer {
 
 impl StringBuffer {
     pub fn append(&mut self, v: &str) {
-        str::push_str(&mut self.s, v);
+        self.s.push_str(v);
     }
 }
 
diff --git a/src/test/run-pass/utf8_chars.rs b/src/test/run-pass/utf8_chars.rs
index 011fb4435c3..94990d649d8 100644
--- a/src/test/run-pass/utf8_chars.rs
+++ b/src/test/run-pass/utf8_chars.rs
@@ -33,7 +33,7 @@ pub fn main() {
     let mut stack = ~"a×c€";
     assert_eq!(str::pop_char(&mut stack), '€');
     assert_eq!(str::pop_char(&mut stack), 'c');
-    str::push_char(&mut stack, 'u');
+    stack.push_char('u');
     assert!(stack == ~"a×u");
     assert_eq!(str::shift_char(&mut stack), 'a');
     assert_eq!(str::shift_char(&mut stack), '×');