From 3136fba5aeca9184c944829596b93e45886fecf2 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Sun, 24 Mar 2013 12:41:19 -0400
Subject: [PATCH 1/2] Removing some mutable fields in libstd

---
 src/libstd/arc.rs         |  2 +-
 src/libstd/json.rs        | 36 +++++++++----------
 src/libstd/num/complex.rs |  1 -
 src/libstd/rope.rs        | 73 +++++++++++++++++++--------------------
 src/libstd/sync.rs        |  3 +-
 src/libstd/task_pool.rs   |  7 ++--
 src/libstd/test.rs        | 61 ++++++++++++++++----------------
 7 files changed, 91 insertions(+), 92 deletions(-)

diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs
index ac8dd1a5d65..585ce2dc815 100644
--- a/src/libstd/arc.rs
+++ b/src/libstd/arc.rs
@@ -259,7 +259,7 @@ struct RWARCInner<T> { lock: RWlock, failed: bool, data: T }
  */
 struct RWARC<T> {
     x: SharedMutableState<RWARCInner<T>>,
-    mut cant_nest: ()
+    cant_nest: ()
 }
 
 /// Create a reader/writer ARC with the supplied data.
diff --git a/src/libstd/json.rs b/src/libstd/json.rs
index f426b74736a..5a2bfd2113b 100644
--- a/src/libstd/json.rs
+++ b/src/libstd/json.rs
@@ -360,9 +360,9 @@ pub fn to_pretty_str(json: &Json) -> ~str {
 
 pub struct Parser {
     priv rdr: @io::Reader,
-    priv mut ch: char,
-    priv mut line: uint,
-    priv mut col: uint,
+    priv ch: char,
+    priv line: uint,
+    priv col: uint,
 }
 
 /// Decode a json value from an io::reader
@@ -376,7 +376,7 @@ pub fn Parser(rdr: @io::Reader) -> Parser {
 }
 
 pub impl Parser {
-    fn parse(&self) -> Result<Json, Error> {
+    fn parse(&mut self) -> Result<Json, Error> {
         match self.parse_value() {
           Ok(value) => {
             // Skip trailing whitespaces.
@@ -396,7 +396,7 @@ pub impl Parser {
 priv impl Parser {
     fn eof(&self) -> bool { self.ch == -1 as char }
 
-    fn bump(&self) {
+    fn bump(&mut self) {
         self.ch = self.rdr.read_char();
 
         if self.ch == '\n' {
@@ -407,7 +407,7 @@ priv impl Parser {
         }
     }
 
-    fn next_char(&self) -> char {
+    fn next_char(&mut self) -> char {
         self.bump();
         self.ch
     }
@@ -416,7 +416,7 @@ priv impl Parser {
         Err(Error { line: self.line, col: self.col, msg: @msg })
     }
 
-    fn parse_value(&self) -> Result<Json, Error> {
+    fn parse_value(&mut self) -> Result<Json, Error> {
         self.parse_whitespace();
 
         if self.eof() { return self.error(~"EOF while parsing value"); }
@@ -437,11 +437,11 @@ priv impl Parser {
         }
     }
 
-    fn parse_whitespace(&self) {
+    fn parse_whitespace(&mut self) {
         while char::is_whitespace(self.ch) { self.bump(); }
     }
 
-    fn parse_ident(&self, ident: &str, value: Json) -> Result<Json, Error> {
+    fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
         if str::all(ident, |c| c == self.next_char()) {
             self.bump();
             Ok(value)
@@ -450,7 +450,7 @@ priv impl Parser {
         }
     }
 
-    fn parse_number(&self) -> Result<Json, Error> {
+    fn parse_number(&mut self) -> Result<Json, Error> {
         let mut neg = 1f;
 
         if self.ch == '-' {
@@ -480,7 +480,7 @@ priv impl Parser {
         Ok(Number(neg * res))
     }
 
-    fn parse_integer(&self) -> Result<float, Error> {
+    fn parse_integer(&mut self) -> Result<float, Error> {
         let mut res = 0f;
 
         match self.ch {
@@ -512,7 +512,7 @@ priv impl Parser {
         Ok(res)
     }
 
-    fn parse_decimal(&self, res: float) -> Result<float, Error> {
+    fn parse_decimal(&mut self, res: float) -> Result<float, Error> {
         self.bump();
 
         // Make sure a digit follows the decimal place.
@@ -538,10 +538,9 @@ priv impl Parser {
         Ok(res)
     }
 
-    fn parse_exponent(&self, res: float) -> Result<float, Error> {
+    fn parse_exponent(&mut self, mut res: float) -> Result<float, Error> {
         self.bump();
 
-        let mut res = res;
         let mut exp = 0u;
         let mut neg_exp = false;
 
@@ -579,7 +578,7 @@ priv impl Parser {
         Ok(res)
     }
 
-    fn parse_str(&self) -> Result<~str, Error> {
+    fn parse_str(&mut self) -> Result<~str, Error> {
         let mut escape = false;
         let mut res = ~"";
 
@@ -643,7 +642,7 @@ priv impl Parser {
         self.error(~"EOF while parsing string")
     }
 
-    fn parse_list(&self) -> Result<Json, Error> {
+    fn parse_list(&mut self) -> Result<Json, Error> {
         self.bump();
         self.parse_whitespace();
 
@@ -673,7 +672,7 @@ priv impl Parser {
         };
     }
 
-    fn parse_object(&self) -> Result<Json, Error> {
+    fn parse_object(&mut self) -> Result<Json, Error> {
         self.bump();
         self.parse_whitespace();
 
@@ -726,7 +725,8 @@ priv impl Parser {
 
 /// Decodes a json value from an @io::Reader
 pub fn from_reader(rdr: @io::Reader) -> Result<Json, Error> {
-    Parser(rdr).parse()
+    let mut parser = Parser(rdr);
+    parser.parse()
 }
 
 /// Decodes a json value from a string
diff --git a/src/libstd/num/complex.rs b/src/libstd/num/complex.rs
index 1e8fc0e6c2b..949850f3ca6 100644
--- a/src/libstd/num/complex.rs
+++ b/src/libstd/num/complex.rs
@@ -239,7 +239,6 @@ mod test {
 
     mod arith {
         use super::*;
-        use super::super::*;
         use core::num::Zero;
 
         #[test]
diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs
index 61f50069d89..232f46b6676 100644
--- a/src/libstd/rope.rs
+++ b/src/libstd/rope.rs
@@ -455,7 +455,7 @@ pub mod iterator {
               node::Content(x) => return node::leaf_iterator::start(x)
             }
         }
-        pub fn next(it: &node::leaf_iterator::T) -> Option<node::Leaf> {
+        pub fn next(it: &mut node::leaf_iterator::T) -> Option<node::Leaf> {
             return node::leaf_iterator::next(it);
         }
     }
@@ -470,7 +470,7 @@ pub mod iterator {
               node::Content(x) => return node::char_iterator::start(x)
             }
         }
-        pub fn next(it: &node::char_iterator::T) -> Option<char> {
+        pub fn next(it: &mut node::char_iterator::T) -> Option<char> {
             return node::char_iterator::next(it)
         }
     }
@@ -832,9 +832,9 @@ pub mod node {
         unsafe {
             let mut buf = vec::from_elem(byte_len(node), 0);
             let mut offset = 0u;//Current position in the buffer
-            let it = leaf_iterator::start(node);
+            let mut it = leaf_iterator::start(node);
             loop {
-                match (leaf_iterator::next(&it)) {
+                match leaf_iterator::next(&mut it) {
                   option::None => break,
                   option::Some(x) => {
                     //FIXME (#2744): Replace with memcpy or something similar
@@ -896,9 +896,9 @@ pub mod node {
         if height(node) < hint_max_node_height { return option::None; }
         //1. Gather all leaves as a forest
         let mut forest = ~[];
-        let it = leaf_iterator::start(node);
+        let mut it = leaf_iterator::start(node);
         loop {
-            match (leaf_iterator::next(&it)) {
+            match leaf_iterator::next(&mut it) {
               option::None    => break,
               option::Some(x) => forest.push(@Leaf(x))
             }
@@ -1058,11 +1058,12 @@ pub mod node {
     }
 
     pub fn cmp(a: @Node, b: @Node) -> int {
-        let ita = char_iterator::start(a);
-        let itb = char_iterator::start(b);
+        let mut ita = char_iterator::start(a);
+        let mut itb = char_iterator::start(b);
         let mut result = 0;
         while result == 0 {
-            match ((char_iterator::next(&ita), char_iterator::next(&itb))) {
+            match (char_iterator::next(&mut ita), char_iterator::next(&mut itb))
+            {
               (option::None, option::None) => break,
               (option::Some(chara), option::Some(charb)) => {
                 result = char::cmp(chara, charb);
@@ -1131,9 +1132,7 @@ pub mod node {
      * proportional to the height of the rope + the (bounded)
      * length of the largest leaf.
      */
-    pub fn char_at(node: @Node, pos: uint) -> char {
-        let mut node    = node;
-        let mut pos     = pos;
+    pub fn char_at(mut node: @Node, mut pos: uint) -> char {
         loop {
             match *node {
               Leaf(x) => return str::char_at(*x.content, pos),
@@ -1154,8 +1153,8 @@ pub mod node {
         use core::vec;
 
         pub struct T {
-            mut stack: ~[@Node],
-            mut stackpos: int,
+            stack: ~[@Node],
+            stackpos: int,
         }
 
         pub fn empty() -> T {
@@ -1171,7 +1170,7 @@ pub mod node {
             }
         }
 
-        pub fn next(it: &T) -> Option<Leaf> {
+        pub fn next(it: &mut T) -> Option<Leaf> {
             if it.stackpos < 0 { return option::None; }
             loop {
                 let current = it.stack[it.stackpos];
@@ -1199,8 +1198,8 @@ pub mod node {
 
         pub struct T {
             leaf_iterator: leaf_iterator::T,
-            mut leaf:  Option<Leaf>,
-            mut leaf_byte_pos: uint,
+            leaf:  Option<Leaf>,
+            leaf_byte_pos: uint,
         }
 
         pub fn start(node: @Node) -> T {
@@ -1219,13 +1218,13 @@ pub mod node {
             }
         }
 
-        pub fn next(it: &T) -> Option<char> {
+        pub fn next(it: &mut T) -> Option<char> {
             loop {
-                match (get_current_or_next_leaf(it)) {
+                match get_current_or_next_leaf(it) {
                   option::None => return option::None,
                   option::Some(_) => {
                     let next_char = get_next_char_in_leaf(it);
-                    match (next_char) {
+                    match next_char {
                       option::None => loop,
                       option::Some(_) => return next_char
                     }
@@ -1234,16 +1233,16 @@ pub mod node {
             };
         }
 
-        pub fn get_current_or_next_leaf(it: &T) -> Option<Leaf> {
-            match ((*it).leaf) {
-              option::Some(_) => return (*it).leaf,
+        pub fn get_current_or_next_leaf(it: &mut T) -> Option<Leaf> {
+            match it.leaf {
+              option::Some(_) => return it.leaf,
               option::None => {
-                let next = leaf_iterator::next(&((*it).leaf_iterator));
-                match (next) {
+                let next = leaf_iterator::next(&mut it.leaf_iterator);
+                match next {
                   option::None => return option::None,
                   option::Some(_) => {
-                    (*it).leaf          = next;
-                    (*it).leaf_byte_pos = 0u;
+                    it.leaf          = next;
+                    it.leaf_byte_pos = 0u;
                     return next;
                   }
                 }
@@ -1251,13 +1250,13 @@ pub mod node {
             }
         }
 
-        pub fn get_next_char_in_leaf(it: &T) -> Option<char> {
-            match copy (*it).leaf {
+        pub fn get_next_char_in_leaf(it: &mut T) -> Option<char> {
+            match copy it.leaf {
               option::None => return option::None,
               option::Some(aleaf) => {
-                if (*it).leaf_byte_pos >= aleaf.byte_len {
+                if it.leaf_byte_pos >= aleaf.byte_len {
                     //We are actually past the end of the leaf
-                    (*it).leaf = option::None;
+                    it.leaf = option::None;
                     return option::None
                 } else {
                     let range =
@@ -1342,11 +1341,11 @@ mod tests {
         assert!(rope_to_string(r) == *sample);
 
         let mut string_iter = 0u;
-        let string_len  = str::len(*sample);
-        let rope_iter   = iterator::char::start(r);
-        let mut equal   = true;
+        let string_len = str::len(*sample);
+        let mut rope_iter = iterator::char::start(r);
+        let mut equal = true;
         while equal {
-            match (node::char_iterator::next(&rope_iter)) {
+            match (node::char_iterator::next(&mut rope_iter)) {
               option::None => {
                 if string_iter < string_len {
                     equal = false;
@@ -1376,9 +1375,9 @@ mod tests {
         let r      = of_str(sample);
 
         let mut len = 0u;
-        let it  = iterator::char::start(r);
+        let mut it  = iterator::char::start(r);
         loop {
-            match (node::char_iterator::next(&it)) {
+            match (node::char_iterator::next(&mut it)) {
               option::None => break,
               option::Some(_) => len += 1u
             }
diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs
index 99b3a122d9f..1bfdd7f99d5 100644
--- a/src/libstd/sync.rs
+++ b/src/libstd/sync.rs
@@ -72,7 +72,7 @@ fn broadcast_waitqueue(q: &Waitqueue) -> uint {
 // The building-block used to make semaphores, mutexes, and rwlocks.
 #[doc(hidden)]
 struct SemInner<Q> {
-    mut count: int,
+    count: int,
     waiters:   Waitqueue,
     // Can be either unit or another waitqueue. Some sems shouldn't come with
     // a condition variable attached, others should.
@@ -729,7 +729,6 @@ mod tests {
 
     use core::cast;
     use core::cell::Cell;
-    use core::option;
     use core::ptr;
     use core::result;
     use core::task;
diff --git a/src/libstd/task_pool.rs b/src/libstd/task_pool.rs
index aed6721b78e..3f2772942a5 100644
--- a/src/libstd/task_pool.rs
+++ b/src/libstd/task_pool.rs
@@ -26,8 +26,7 @@ enum Msg<T> {
 
 pub struct TaskPool<T> {
     channels: ~[Chan<Msg<T>>],
-    mut next_index: uint,
-
+    next_index: uint,
 }
 
 #[unsafe_destructor]
@@ -84,7 +83,7 @@ pub impl<T> TaskPool<T> {
 
     /// Executes the function `f` on a task in the pool. The function
     /// receives a reference to the local data returned by the `init_fn`.
-    fn execute(&self, f: ~fn(&T)) {
+    fn execute(&mut self, f: ~fn(&T)) {
         self.channels[self.next_index].send(Execute(f));
         self.next_index += 1;
         if self.next_index == self.channels.len() { self.next_index = 0; }
@@ -97,7 +96,7 @@ fn test_task_pool() {
         let g: ~fn(uint) -> uint = |i| i;
         g
     };
-    let pool = TaskPool::new(4, Some(SingleThreaded), f);
+    let mut pool = TaskPool::new(4, Some(SingleThreaded), f);
     for 8.times {
         pool.execute(|i| io::println(fmt!("Hello from thread %u!", *i)));
     }
diff --git a/src/libstd/test.rs b/src/libstd/test.rs
index 7c5591d839e..04fa319b255 100644
--- a/src/libstd/test.rs
+++ b/src/libstd/test.rs
@@ -201,19 +201,19 @@ struct ConsoleTestState {
     out: @io::Writer,
     log_out: Option<@io::Writer>,
     use_color: bool,
-    mut total: uint,
-    mut passed: uint,
-    mut failed: uint,
-    mut ignored: uint,
-    mut benchmarked: uint,
-    mut failures: ~[TestDesc]
+    total: uint,
+    passed: uint,
+    failed: uint,
+    ignored: uint,
+    benchmarked: uint,
+    failures: ~[TestDesc]
 }
 
 // A simple console test runner
 pub fn run_tests_console(opts: &TestOpts,
                          tests: ~[TestDescAndFn]) -> bool {
 
-    fn callback(event: &TestEvent, st: @ConsoleTestState) {
+    fn callback(event: &TestEvent, st: &mut ConsoleTestState) {
         debug!("callback(event=%?)", event);
         match *event {
           TeFiltered(ref filtered_tests) => {
@@ -268,16 +268,16 @@ pub fn run_tests_console(opts: &TestOpts,
         None => None
     };
 
-    let st = @ConsoleTestState {
+    let st = @mut ConsoleTestState {
         out: io::stdout(),
         log_out: log_out,
         use_color: use_color(),
-        mut total: 0u,
-        mut passed: 0u,
-        mut failed: 0u,
-        mut ignored: 0u,
-        mut benchmarked: 0u,
-        mut failures: ~[]
+        total: 0u,
+        passed: 0u,
+        failed: 0u,
+        ignored: 0u,
+        benchmarked: 0u,
+        failures: ~[]
     };
 
     run_tests(opts, tests, |x| callback(&x, st));
@@ -290,15 +290,18 @@ pub fn run_tests_console(opts: &TestOpts,
         print_failures(st);
     }
 
-    st.out.write_str(fmt!("\nresult: "));
-    if success {
-        // There's no parallelism at this point so it's safe to use color
-        write_ok(st.out, true);
-    } else {
-        write_failed(st.out, true);
+    {
+      let st: &mut ConsoleTestState = st;
+      st.out.write_str(fmt!("\nresult: "));
+      if success {
+          // There's no parallelism at this point so it's safe to use color
+          write_ok(st.out, true);
+      } else {
+          write_failed(st.out, true);
+      }
+      st.out.write_str(fmt!(". %u passed; %u failed; %u ignored\n\n",
+                            st.passed, st.failed, st.ignored));
     }
-    st.out.write_str(fmt!(". %u passed; %u failed; %u ignored\n\n",
-                          st.passed, st.failed, st.ignored));
 
     return success;
 
@@ -356,7 +359,7 @@ pub fn run_tests_console(opts: &TestOpts,
     }
 }
 
-fn print_failures(st: @ConsoleTestState) {
+fn print_failures(st: &ConsoleTestState) {
     st.out.write_line(~"\nfailures:");
     let mut failures = ~[];
     for uint::range(0, vec::uniq_len(&const st.failures)) |i| {
@@ -390,12 +393,12 @@ fn should_sort_failures_before_printing_them() {
             out: wr,
             log_out: option::None,
             use_color: false,
-            mut total: 0u,
-            mut passed: 0u,
-            mut failed: 0u,
-            mut ignored: 0u,
-            mut benchmarked: 0u,
-            mut failures: ~[test_b, test_a]
+            total: 0u,
+            passed: 0u,
+            failed: 0u,
+            ignored: 0u,
+            benchmarked: 0u,
+            failures: ~[test_b, test_a]
         };
 
         print_failures(st);

From 255193cc1af5e07753906ad18bae077b45b5c3f0 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Mon, 8 Apr 2013 16:50:34 -0400
Subject: [PATCH 2/2] Removing no longer needed unsafe blocks

---
 src/libcore/char.rs          |  10 +-
 src/libcore/hash.rs          |  62 ++++-----
 src/libcore/num/strconv.rs   |  76 +++++------
 src/libcore/result.rs        |   6 +-
 src/libcore/str.rs           |  58 ++++-----
 src/libcore/to_str.rs        |  63 ++++------
 src/libcore/vec.rs           |  81 +++++-------
 src/libstd/base64.rs         | 144 +++++++++++----------
 src/libstd/dlist.rs          |   9 +-
 src/libstd/json.rs           |  33 +++--
 src/libstd/md4.rs            |   4 +-
 src/libstd/num/bigint.rs     |   2 +-
 src/libstd/sha1.rs           | 238 +++++++++++++++++------------------
 src/libstd/sort.rs           |  30 ++---
 src/libstd/time.rs           |   8 +-
 src/libsyntax/codemap.rs     |  16 ++-
 src/libsyntax/parse/lexer.rs |  10 +-
 17 files changed, 373 insertions(+), 477 deletions(-)

diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index 4f1dbe6ab7f..6ca33540cee 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -202,12 +202,10 @@ pub fn escape_unicode(c: char) -> ~str {
                     else { ('U', 8u) });
     assert!(str::len(s) <= pad);
     let mut out = ~"\\";
-    unsafe {
-        str::push_str(&mut out, str::from_char(c));
-        for uint::range(str::len(s), pad) |_i|
-            { str::push_str(&mut out, ~"0"); }
-        str::push_str(&mut out, s);
-    }
+    str::push_str(&mut out, str::from_char(c));
+    for uint::range(str::len(s), pad) |_i|
+        { str::push_str(&mut out, ~"0"); }
+    str::push_str(&mut out, s);
     out
 }
 
diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs
index d31f35b0115..c229bc17311 100644
--- a/src/libcore/hash.rs
+++ b/src/libcore/hash.rs
@@ -76,36 +76,30 @@ pub trait Streaming {
 impl<A:IterBytes> Hash for A {
     #[inline(always)]
     fn hash_keyed(&self, k0: u64, k1: u64) -> u64 {
-        unsafe {
-            let s = &State(k0, k1);
-            for self.iter_bytes(true) |bytes| {
-                s.input(bytes);
-            }
-            s.result_u64()
+        let s = &State(k0, k1);
+        for self.iter_bytes(true) |bytes| {
+            s.input(bytes);
         }
+        s.result_u64()
     }
 }
 
 fn hash_keyed_2<A: IterBytes,
                 B: IterBytes>(a: &A, b: &B, k0: u64, k1: u64) -> u64 {
-    unsafe {
-        let s = &State(k0, k1);
-        for a.iter_bytes(true) |bytes| { s.input(bytes); }
-        for b.iter_bytes(true) |bytes| { s.input(bytes); }
-        s.result_u64()
-    }
+    let s = &State(k0, k1);
+    for a.iter_bytes(true) |bytes| { s.input(bytes); }
+    for b.iter_bytes(true) |bytes| { s.input(bytes); }
+    s.result_u64()
 }
 
 fn hash_keyed_3<A: IterBytes,
                 B: IterBytes,
                 C: IterBytes>(a: &A, b: &B, c: &C, k0: u64, k1: u64) -> u64 {
-    unsafe {
-        let s = &State(k0, k1);
-        for a.iter_bytes(true) |bytes| { s.input(bytes); }
-        for b.iter_bytes(true) |bytes| { s.input(bytes); }
-        for c.iter_bytes(true) |bytes| { s.input(bytes); }
-        s.result_u64()
-    }
+    let s = &State(k0, k1);
+    for a.iter_bytes(true) |bytes| { s.input(bytes); }
+    for b.iter_bytes(true) |bytes| { s.input(bytes); }
+    for c.iter_bytes(true) |bytes| { s.input(bytes); }
+    s.result_u64()
 }
 
 fn hash_keyed_4<A: IterBytes,
@@ -113,14 +107,12 @@ fn hash_keyed_4<A: IterBytes,
                 C: IterBytes,
                 D: IterBytes>(a: &A, b: &B, c: &C, d: &D, k0: u64, k1: u64)
                            -> u64 {
-    unsafe {
-        let s = &State(k0, k1);
-        for a.iter_bytes(true) |bytes| { s.input(bytes); }
-        for b.iter_bytes(true) |bytes| { s.input(bytes); }
-        for c.iter_bytes(true) |bytes| { s.input(bytes); }
-        for d.iter_bytes(true) |bytes| { s.input(bytes); }
-        s.result_u64()
-    }
+    let s = &State(k0, k1);
+    for a.iter_bytes(true) |bytes| { s.input(bytes); }
+    for b.iter_bytes(true) |bytes| { s.input(bytes); }
+    for c.iter_bytes(true) |bytes| { s.input(bytes); }
+    for d.iter_bytes(true) |bytes| { s.input(bytes); }
+    s.result_u64()
 }
 
 fn hash_keyed_5<A: IterBytes,
@@ -129,15 +121,13 @@ fn hash_keyed_5<A: IterBytes,
                 D: IterBytes,
                 E: IterBytes>(a: &A, b: &B, c: &C, d: &D, e: &E,
                               k0: u64, k1: u64) -> u64 {
-    unsafe {
-        let s = &State(k0, k1);
-        for a.iter_bytes(true) |bytes| { s.input(bytes); }
-        for b.iter_bytes(true) |bytes| { s.input(bytes); }
-        for c.iter_bytes(true) |bytes| { s.input(bytes); }
-        for d.iter_bytes(true) |bytes| { s.input(bytes); }
-        for e.iter_bytes(true) |bytes| { s.input(bytes); }
-        s.result_u64()
-    }
+    let s = &State(k0, k1);
+    for a.iter_bytes(true) |bytes| { s.input(bytes); }
+    for b.iter_bytes(true) |bytes| { s.input(bytes); }
+    for c.iter_bytes(true) |bytes| { s.input(bytes); }
+    for d.iter_bytes(true) |bytes| { s.input(bytes); }
+    for e.iter_bytes(true) |bytes| { s.input(bytes); }
+    s.result_u64()
 }
 
 // Implement State as SipState
diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs
index 5299203eb42..9374829dcb8 100644
--- a/src/libcore/num/strconv.rs
+++ b/src/libcore/num/strconv.rs
@@ -228,10 +228,8 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
         deccum /= radix_gen;
         deccum = deccum.round_to_zero();
 
-        unsafe { // FIXME: Pureness workaround (#4568)
-            buf.push(char::from_digit(current_digit.to_int() as uint, radix)
-                 .unwrap() as u8);
-        }
+        buf.push(char::from_digit(current_digit.to_int() as uint, radix)
+             .unwrap() as u8);
 
         // No more digits to calculate for the non-fractional part -> break
         if deccum == _0 { break; }
@@ -247,21 +245,15 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
     // Decide what sign to put in front
     match sign {
         SignNeg | SignAll if neg => {
-            unsafe { // FIXME: Pureness workaround (#4568)
-                buf.push('-' as u8);
-            }
+            buf.push('-' as u8);
         }
         SignAll => {
-            unsafe { // FIXME: Pureness workaround (#4568)
-                buf.push('+' as u8);
-            }
+            buf.push('+' as u8);
         }
         _ => ()
     }
 
-    unsafe { // FIXME: Pureness workaround (#4568)
-        vec::reverse(buf);
-    }
+    vec::reverse(buf);
 
     // Remember start of the fractional digits.
     // Points one beyond end of buf if none get generated,
@@ -271,9 +263,7 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
     // Now emit the fractional part, if any
     deccum = num.fractional_part();
     if deccum != _0 || (limit_digits && exact && digit_count > 0) {
-        unsafe { // FIXME: Pureness workaround (#4568)
-            buf.push('.' as u8);
-        }
+        buf.push('.' as u8);
         let mut dig = 0u;
 
         // calculate new digits while
@@ -299,10 +289,8 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
                 current_digit_signed
             };
 
-            unsafe { // FIXME: Pureness workaround (#4568)
-                buf.push(char::from_digit(
-                    current_digit.to_int() as uint, radix).unwrap() as u8);
-            }
+            buf.push(char::from_digit(
+                current_digit.to_int() as uint, radix).unwrap() as u8);
 
             // Decrease the deccumulator one fractional digit at a time
             deccum = deccum.fractional_part();
@@ -320,33 +308,31 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
                 char::from_digit(val, radix).unwrap() as u8
             };
 
-            unsafe { // FIXME: Pureness workaround (#4568)
-                let extra_digit = ascii2value(buf.pop());
-                if extra_digit >= radix / 2 { // -> need to round
-                    let mut i: int = buf.len() as int - 1;
-                    loop {
-                        // If reached left end of number, have to
-                        // insert additional digit:
-                        if i < 0
-                        || buf[i] == '-' as u8
-                        || buf[i] == '+' as u8 {
-                            buf.insert((i + 1) as uint, value2ascii(1));
-                            break;
-                        }
+            let extra_digit = ascii2value(buf.pop());
+            if extra_digit >= radix / 2 { // -> need to round
+                let mut i: int = buf.len() as int - 1;
+                loop {
+                    // If reached left end of number, have to
+                    // insert additional digit:
+                    if i < 0
+                    || buf[i] == '-' as u8
+                    || buf[i] == '+' as u8 {
+                        buf.insert((i + 1) as uint, value2ascii(1));
+                        break;
+                    }
 
-                        // Skip the '.'
-                        if buf[i] == '.' as u8 { i -= 1; loop; }
+                    // Skip the '.'
+                    if buf[i] == '.' as u8 { i -= 1; loop; }
 
-                        // Either increment the digit,
-                        // or set to 0 if max and carry the 1.
-                        let current_digit = ascii2value(buf[i]);
-                        if current_digit < (radix - 1) {
-                            buf[i] = value2ascii(current_digit+1);
-                            break;
-                        } else {
-                            buf[i] = value2ascii(0);
-                            i -= 1;
-                        }
+                    // Either increment the digit,
+                    // or set to 0 if max and carry the 1.
+                    let current_digit = ascii2value(buf[i]);
+                    if current_digit < (radix - 1) {
+                        buf[i] = value2ascii(current_digit+1);
+                        break;
+                    } else {
+                        buf[i] = value2ascii(0);
+                        i -= 1;
                     }
                 }
             }
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 24822f52e1e..8fd81a20603 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -39,9 +39,8 @@ pub enum Result<T, U> {
 pub fn get<T:Copy,U>(res: &Result<T, U>) -> T {
     match *res {
       Ok(copy t) => t,
-      Err(ref the_err) => unsafe {
+      Err(ref the_err) =>
         fail!(fmt!("get called on error result: %?", *the_err))
-      }
     }
 }
 
@@ -56,9 +55,8 @@ pub fn get<T:Copy,U>(res: &Result<T, U>) -> T {
 pub fn get_ref<'a, T, U>(res: &'a Result<T, U>) -> &'a T {
     match *res {
         Ok(ref t) => t,
-        Err(ref the_err) => unsafe {
+        Err(ref the_err) =>
             fail!(fmt!("get_ref called on error result: %?", *the_err))
-        }
     }
 }
 
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 18ea169d96e..f1605309fb4 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -1020,11 +1020,9 @@ pub fn any(ss: &str, pred: &fn(char) -> bool) -> bool {
 /// Apply a function to each character
 pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str {
     let mut result = ~"";
-    unsafe {
-        reserve(&mut result, len(ss));
-        for ss.each_char |cc| {
-            str::push_char(&mut result, ff(cc));
-        }
+    reserve(&mut result, len(ss));
+    for ss.each_char |cc| {
+        str::push_char(&mut result, ff(cc));
     }
     result
 }
@@ -1660,20 +1658,18 @@ pub fn to_utf16(s: &str) -> ~[u16] {
         // Arithmetic with u32 literals is easier on the eyes than chars.
         let mut ch = ch as u32;
 
-        unsafe {
-            if (ch & 0xFFFF_u32) == ch {
-                // The BMP falls through (assuming non-surrogate, as it
-                // should)
-                assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32);
-                u.push(ch as u16)
-            } else {
-                // Supplementary planes break into surrogates.
-                assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32);
-                ch -= 0x1_0000_u32;
-                let w1 = 0xD800_u16 | ((ch >> 10) as u16);
-                let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16);
-                u.push_all(~[w1, w2])
-            }
+        if (ch & 0xFFFF_u32) == ch {
+            // The BMP falls through (assuming non-surrogate, as it
+            // should)
+            assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32);
+            u.push(ch as u16)
+        } else {
+            // Supplementary planes break into surrogates.
+            assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32);
+            ch -= 0x1_0000_u32;
+            let w1 = 0xD800_u16 | ((ch >> 10) as u16);
+            let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16);
+            u.push_all(~[w1, w2])
         }
     }
     u
@@ -1705,16 +1701,14 @@ pub fn utf16_chars(v: &[u16], f: &fn(char)) {
 
 pub fn from_utf16(v: &[u16]) -> ~str {
     let mut buf = ~"";
-    unsafe {
-        reserve(&mut buf, vec::len(v));
-        utf16_chars(v, |ch| push_char(&mut buf, ch));
-    }
+    reserve(&mut buf, vec::len(v));
+    utf16_chars(v, |ch| push_char(&mut buf, ch));
     buf
 }
 
 pub fn with_capacity(capacity: uint) -> ~str {
     let mut buf = ~"";
-    unsafe { reserve(&mut buf, capacity); }
+    reserve(&mut buf, capacity);
     buf
 }
 
@@ -2105,11 +2099,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 = ~"";
-    unsafe {
-        reserve_at_least(&mut out, str::len(s));
-        for s.each_char |c| {
-            push_str(&mut out, char::escape_default(c));
-        }
+    reserve_at_least(&mut out, str::len(s));
+    for s.each_char |c| {
+        push_str(&mut out, char::escape_default(c));
     }
     out
 }
@@ -2117,11 +2109,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 = ~"";
-    unsafe {
-        reserve_at_least(&mut out, str::len(s));
-        for s.each_char |c| {
-            push_str(&mut out, char::escape_unicode(c));
-        }
+    reserve_at_least(&mut out, str::len(s));
+    for s.each_char |c| {
+        push_str(&mut out, char::escape_unicode(c));
     }
     out
 }
diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs
index a6004ed1241..980d4b445d0 100644
--- a/src/libcore/to_str.rs
+++ b/src/libcore/to_str.rs
@@ -72,63 +72,42 @@ impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
 impl<'self,A:ToStr> ToStr for &'self [A] {
     #[inline(always)]
     fn to_str(&self) -> ~str {
-        unsafe {
-            // FIXME #4568
-            // Bleh -- not really unsafe
-            // push_str and push_char
-            let mut acc = ~"[", first = true;
-            for self.each |elt| {
-                unsafe {
-                    if first { first = false; }
-                    else { str::push_str(&mut acc, ~", "); }
-                    str::push_str(&mut acc, elt.to_str());
-                }
-            }
-            str::push_char(&mut acc, ']');
-            acc
+        let mut acc = ~"[", first = true;
+        for self.each |elt| {
+            if first { first = false; }
+            else { str::push_str(&mut acc, ~", "); }
+            str::push_str(&mut acc, elt.to_str());
         }
+        str::push_char(&mut acc, ']');
+        acc
     }
 }
 
 impl<A:ToStr> ToStr for ~[A] {
     #[inline(always)]
     fn to_str(&self) -> ~str {
-        unsafe {
-            // FIXME #4568
-            // Bleh -- not really unsafe
-            // push_str and push_char
-            let mut acc = ~"[", first = true;
-            for self.each |elt| {
-                unsafe {
-                    if first { first = false; }
-                    else { str::push_str(&mut acc, ~", "); }
-                    str::push_str(&mut acc, elt.to_str());
-                }
-            }
-            str::push_char(&mut acc, ']');
-            acc
+        let mut acc = ~"[", first = true;
+        for self.each |elt| {
+            if first { first = false; }
+            else { str::push_str(&mut acc, ~", "); }
+            str::push_str(&mut acc, elt.to_str());
         }
+        str::push_char(&mut acc, ']');
+        acc
     }
 }
 
 impl<A:ToStr> ToStr for @[A] {
     #[inline(always)]
     fn to_str(&self) -> ~str {
-        unsafe {
-            // FIXME #4568
-            // Bleh -- not really unsafe
-            // push_str and push_char
-            let mut acc = ~"[", first = true;
-            for self.each |elt| {
-                unsafe {
-                    if first { first = false; }
-                    else { str::push_str(&mut acc, ~", "); }
-                    str::push_str(&mut acc, elt.to_str());
-                }
-            }
-            str::push_char(&mut acc, ']');
-            acc
+        let mut acc = ~"[", first = true;
+        for self.each |elt| {
+            if first { first = false; }
+            else { str::push_str(&mut acc, ~", "); }
+            str::push_str(&mut acc, elt.to_str());
         }
+        str::push_char(&mut acc, ']');
+        acc
     }
 }
 
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 21e876ea0fb..5b06591f9ec 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -167,7 +167,7 @@ pub fn from_slice<T:Copy>(t: &[T]) -> ~[T] {
 
 pub fn with_capacity<T>(capacity: uint) -> ~[T] {
     let mut vec = ~[];
-    unsafe { reserve(&mut vec, capacity); }
+    reserve(&mut vec, capacity);
     vec
 }
 
@@ -186,7 +186,7 @@ pub fn with_capacity<T>(capacity: uint) -> ~[T] {
 #[inline(always)]
 pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> ~[A] {
     let mut vec = with_capacity(size);
-    builder(|x| unsafe { vec.push(x) });
+    builder(|x| vec.push(x));
     vec
 }
 
@@ -437,12 +437,10 @@ pub fn partitioned<T:Copy>(v: &[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) {
     let mut rights = ~[];
 
     for each(v) |elt| {
-        unsafe {
-            if f(elt) {
-                lefts.push(*elt);
-            } else {
-                rights.push(*elt);
-            }
+        if f(elt) {
+            lefts.push(*elt);
+        } else {
+            rights.push(*elt);
         }
     }
 
@@ -735,16 +733,14 @@ pub fn dedup<T:Eq>(v: &mut ~[T]) {
 #[inline(always)]
 pub fn append<T:Copy>(lhs: ~[T], rhs: &const [T]) -> ~[T] {
     let mut v = lhs;
-    unsafe {
-        v.push_all(rhs);
-    }
+    v.push_all(rhs);
     v
 }
 
 #[inline(always)]
 pub fn append_one<T>(lhs: ~[T], x: T) -> ~[T] {
     let mut v = lhs;
-    unsafe { v.push(x); }
+    v.push(x);
     v
 }
 
@@ -811,9 +807,7 @@ pub fn grow_set<T:Copy>(v: &mut ~[T], index: uint, initval: &T, val: T) {
 pub fn map<T, U>(v: &[T], f: &fn(t: &T) -> U) -> ~[U] {
     let mut result = with_capacity(len(v));
     for each(v) |elem| {
-        unsafe {
-            result.push(f(elem));
-        }
+        result.push(f(elem));
     }
     result
 }
@@ -841,7 +835,7 @@ pub fn mapi<T, U>(v: &[T], f: &fn(uint, t: &T) -> U) -> ~[U] {
  */
 pub fn flat_map<T, U>(v: &[T], f: &fn(t: &T) -> ~[U]) -> ~[U] {
     let mut result = ~[];
-    for each(v) |elem| { unsafe{ result.push_all_move(f(elem)); } }
+    for each(v) |elem| { result.push_all_move(f(elem)); }
     result
 }
 
@@ -853,7 +847,7 @@ pub fn map2<T:Copy,U:Copy,V>(v0: &[T], v1: &[U],
     let mut u: ~[V] = ~[];
     let mut i = 0u;
     while i < v0_len {
-        unsafe { u.push(f(&v0[i], &v1[i])) };
+        u.push(f(&v0[i], &v1[i]));
         i += 1u;
     }
     u
@@ -894,7 +888,7 @@ pub fn filter_mapped<T, U: Copy>(
     for each(v) |elem| {
         match f(elem) {
           None => {/* no-op */ }
-          Some(result_elem) => unsafe { result.push(result_elem); }
+          Some(result_elem) => { result.push(result_elem); }
         }
     }
     result
@@ -927,7 +921,7 @@ pub fn filter<T>(v: ~[T], f: &fn(t: &T) -> bool) -> ~[T] {
 pub fn filtered<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[T] {
     let mut result = ~[];
     for each(v) |elem| {
-        if f(elem) { unsafe { result.push(*elem); } }
+        if f(elem) { result.push(*elem); }
     }
     result
 }
@@ -959,7 +953,7 @@ pub fn retain<T>(v: &mut ~[T], f: &fn(t: &T) -> bool) {
  */
 pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] {
     let mut r = ~[];
-    for each(v) |inner| { unsafe { r.push_all(*inner); } }
+    for each(v) |inner| { r.push_all(*inner); }
     r
 }
 
@@ -968,8 +962,8 @@ pub fn connect<T:Copy>(v: &[~[T]], sep: &T) -> ~[T] {
     let mut r: ~[T] = ~[];
     let mut first = true;
     for each(v) |inner| {
-        if first { first = false; } else { unsafe { r.push(*sep); } }
-        unsafe { r.push_all(*inner) };
+        if first { first = false; } else { r.push(*sep); }
+        r.push_all(*inner);
     }
     r
 }
@@ -1236,10 +1230,8 @@ pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) {
     let mut ts = ~[], us = ~[];
     for each(v) |p| {
         let (t, u) = *p;
-        unsafe {
-            ts.push(t);
-            us.push(u);
-        }
+        ts.push(t);
+        us.push(u);
     }
     (ts, us)
 }
@@ -1254,12 +1246,10 @@ pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) {
  */
 pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) {
     let mut ts = ~[], us = ~[];
-    unsafe {
-        do consume(v) |_i, p| {
-            let (t, u) = p;
-            ts.push(t);
-            us.push(u);
-        }
+    do consume(v) |_i, p| {
+        let (t, u) = p;
+        ts.push(t);
+        us.push(u);
     }
     (ts, us)
 }
@@ -1274,7 +1264,8 @@ pub fn zip_slice<T:Copy,U:Copy>(v: &const [T], u: &const [U])
     let mut i = 0u;
     assert!(sz == len(u));
     while i < sz {
-        unsafe { zipped.push((v[i], u[i])); i += 1u; }
+        zipped.push((v[i], u[i]));
+        i += 1u;
     }
     zipped
 }
@@ -1290,10 +1281,10 @@ pub fn zip<T, U>(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] {
     assert!(i == len(u));
     let mut w = with_capacity(i);
     while i > 0 {
-        unsafe { w.push((v.pop(),u.pop())); }
+        w.push((v.pop(),u.pop()));
         i -= 1;
     }
-    unsafe { reverse(w); }
+    reverse(w);
     w
 }
 
@@ -1322,10 +1313,8 @@ pub fn reversed<T:Copy>(v: &const [T]) -> ~[T] {
     let mut rs: ~[T] = ~[];
     let mut i = len::<T>(v);
     if i == 0 { return (rs); } else { i -= 1; }
-    unsafe {
-        while i != 0 { rs.push(v[i]); i -= 1; }
-        rs.push(v[0]);
-    }
+    while i != 0 { rs.push(v[i]); i -= 1; }
+    rs.push(v[0]);
     rs
 }
 
@@ -1495,12 +1484,10 @@ pub fn each_permutation<T:Copy>(v: &[T], put: &fn(ts: &[T]) -> bool) {
         while i < ln {
             let elt = v[i];
             let mut rest = slice(v, 0u, i).to_vec();
-            unsafe {
-                rest.push_all(const_slice(v, i+1u, ln));
-                for each_permutation(rest) |permutation| {
-                    if !put(append(~[elt], permutation)) {
-                        return;
-                    }
+            rest.push_all(const_slice(v, i+1u, ln));
+            for each_permutation(rest) |permutation| {
+                if !put(append(~[elt], permutation)) {
+                    return;
                 }
             }
             i += 1u;
@@ -1514,9 +1501,7 @@ pub fn windowed<TT:Copy>(nn: uint, xx: &[TT]) -> ~[~[TT]] {
     for vec::eachi (xx) |ii, _x| {
         let len = xx.len();
         if ii+nn <= len {
-            unsafe {
-                ww.push(slice(xx, ii, ii+nn).to_vec());
-            }
+            ww.push(slice(xx, ii, ii+nn).to_vec());
         }
     }
     ww
diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs
index 0266f2d8631..781a720b1a4 100644
--- a/src/libstd/base64.rs
+++ b/src/libstd/base64.rs
@@ -29,47 +29,45 @@ static CHARS: [char, ..64] = [
 impl<'self> ToBase64 for &'self [u8] {
     fn to_base64(&self) -> ~str {
         let mut s = ~"";
-        unsafe {
-            let len = self.len();
-            str::reserve(&mut s, ((len + 3u) / 4u) * 3u);
+        let len = self.len();
+        str::reserve(&mut s, ((len + 3u) / 4u) * 3u);
 
-            let mut i = 0u;
+        let mut i = 0u;
 
-            while i < len - (len % 3u) {
-                let n = (self[i] as uint) << 16u |
-                        (self[i + 1u] as uint) << 8u |
-                        (self[i + 2u] as uint);
+        while i < len - (len % 3u) {
+            let n = (self[i] as uint) << 16u |
+                    (self[i + 1u] as uint) << 8u |
+                    (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]);
+            // 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]);
 
-                i += 3u;
-            }
+            i += 3u;
+        }
 
-            // Heh, would be cool if we knew this was exhaustive
-            // (the dream of bounded integer types)
-            match len % 3 {
-              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, '=');
-              }
-              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, '=');
-              }
-              _ => fail!(~"Algebra is broken, please alert the math police")
-            }
+        // Heh, would be cool if we knew this was exhaustive
+        // (the dream of bounded integer types)
+        match len % 3 {
+          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, '=');
+          }
+          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, '=');
+          }
+          _ => fail!(~"Algebra is broken, please alert the math police")
         }
         s
     }
@@ -99,49 +97,47 @@ impl FromBase64 for ~[u8] {
 
         let mut r = vec::with_capacity((len / 4u) * 3u - padding);
 
-        unsafe {
-            let mut i = 0u;
-            while i < len {
-                let mut n = 0u;
+        let mut i = 0u;
+        while i < len {
+            let mut n = 0u;
 
-                for iter::repeat(4u) {
-                    let ch = self[i] as char;
-                    n <<= 6u;
+            for iter::repeat(4u) {
+                let ch = self[i] as char;
+                n <<= 6u;
 
-                    if ch >= 'A' && ch <= 'Z' {
-                        n |= (ch as uint) - 0x41u;
-                    } else if ch >= 'a' && ch <= 'z' {
-                        n |= (ch as uint) - 0x47u;
-                    } else if ch >= '0' && ch <= '9' {
-                        n |= (ch as uint) + 0x04u;
-                    } else if ch == '+' {
-                        n |= 0x3Eu;
-                    } else if ch == '/' {
-                        n |= 0x3Fu;
-                    } else if ch == '=' {
-                        match len - i {
-                          1u => {
-                            r.push(((n >> 16u) & 0xFFu) as u8);
-                            r.push(((n >> 8u ) & 0xFFu) as u8);
-                            return copy r;
-                          }
-                          2u => {
-                            r.push(((n >> 10u) & 0xFFu) as u8);
-                            return copy r;
-                          }
-                          _ => fail!(~"invalid base64 padding")
-                        }
-                    } else {
-                        fail!(~"invalid base64 character");
+                if ch >= 'A' && ch <= 'Z' {
+                    n |= (ch as uint) - 0x41u;
+                } else if ch >= 'a' && ch <= 'z' {
+                    n |= (ch as uint) - 0x47u;
+                } else if ch >= '0' && ch <= '9' {
+                    n |= (ch as uint) + 0x04u;
+                } else if ch == '+' {
+                    n |= 0x3Eu;
+                } else if ch == '/' {
+                    n |= 0x3Fu;
+                } else if ch == '=' {
+                    match len - i {
+                      1u => {
+                        r.push(((n >> 16u) & 0xFFu) as u8);
+                        r.push(((n >> 8u ) & 0xFFu) as u8);
+                        return copy r;
+                      }
+                      2u => {
+                        r.push(((n >> 10u) & 0xFFu) as u8);
+                        return copy r;
+                      }
+                      _ => fail!(~"invalid base64 padding")
                     }
+                } else {
+                    fail!(~"invalid base64 character");
+                }
 
-                    i += 1u;
-                };
+                i += 1u;
+            };
 
-                r.push(((n >> 16u) & 0xFFu) as u8);
-                r.push(((n >> 8u ) & 0xFFu) as u8);
-                r.push(((n       ) & 0xFFu) as u8);
-            }
+            r.push(((n >> 16u) & 0xFFu) as u8);
+            r.push(((n >> 8u ) & 0xFFu) as u8);
+            r.push(((n       ) & 0xFFu) as u8);
         }
         r
     }
diff --git a/src/libstd/dlist.rs b/src/libstd/dlist.rs
index e7701974097..a490065b835 100644
--- a/src/libstd/dlist.rs
+++ b/src/libstd/dlist.rs
@@ -99,7 +99,7 @@ pub fn DList<T>() -> @mut DList<T> {
 /// Creates a new dlist with a single element
 pub fn from_elem<T>(data: T) -> @mut DList<T> {
     let list = DList();
-    unsafe { list.push(data); }
+    list.push(data);
     list
 }
 
@@ -484,11 +484,8 @@ pub impl<T:Copy> DList<T> {
     /// Get the elements of the list as a vector. O(n).
     fn to_vec(@mut self) -> ~[T] {
         let mut v = vec::with_capacity(self.size);
-        unsafe {
-            // Take this out of the unchecked when iter's functions are pure
-            for iter::eachi(&self) |index,data| {
-                v[index] = *data;
-            }
+        for iter::eachi(&self) |index,data| {
+            v[index] = *data;
         }
         v
     }
diff --git a/src/libstd/json.rs b/src/libstd/json.rs
index 5a2bfd2113b..d733a60f34f 100644
--- a/src/libstd/json.rs
+++ b/src/libstd/json.rs
@@ -342,10 +342,7 @@ pub fn to_writer(wr: @io::Writer, json: &Json) {
 
 /// Encodes a json value into a string
 pub fn to_str(json: &Json) -> ~str {
-    unsafe {
-        // ugh, should be safe
-        io::with_str_writer(|wr| to_writer(wr, json))
-    }
+    io::with_str_writer(|wr| to_writer(wr, json))
 }
 
 /// Encodes a json value into a io::writer
@@ -988,23 +985,21 @@ impl Ord for Json {
                 match *other {
                     Number(_) | String(_) | Boolean(_) | List(_) => false,
                     Object(ref d1) => {
-                        unsafe {
-                            let mut d0_flat = ~[];
-                            let mut d1_flat = ~[];
+                        let mut d0_flat = ~[];
+                        let mut d1_flat = ~[];
 
-                            // FIXME #4430: this is horribly inefficient...
-                            for d0.each |&(k, v)| {
-                                 d0_flat.push((@copy *k, @copy *v));
-                            }
-                            d0_flat.qsort();
-
-                            for d1.each |&(k, v)| {
-                                d1_flat.push((@copy *k, @copy *v));
-                            }
-                            d1_flat.qsort();
-
-                            d0_flat < d1_flat
+                        // FIXME #4430: this is horribly inefficient...
+                        for d0.each |&(k, v)| {
+                             d0_flat.push((@copy *k, @copy *v));
                         }
+                        d0_flat.qsort();
+
+                        for d1.each |&(k, v)| {
+                            d1_flat.push((@copy *k, @copy *v));
+                        }
+                        d1_flat.qsort();
+
+                        d0_flat < d1_flat
                     }
                     Null => true
                 }
diff --git a/src/libstd/md4.rs b/src/libstd/md4.rs
index 8f35376a6f1..24dd08c362e 100644
--- a/src/libstd/md4.rs
+++ b/src/libstd/md4.rs
@@ -29,14 +29,14 @@ pub fn md4(msg: &[u8]) -> Quad {
     let mut msg = vec::append(vec::from_slice(msg), ~[0x80u8]);
     let mut bitlen = orig_len + 8u64;
     while (bitlen + 64u64) % 512u64 > 0u64 {
-        unsafe {msg.push(0u8);}
+        msg.push(0u8);
         bitlen += 8u64;
     }
 
     // append length
     let mut i = 0u64;
     while i < 8u64 {
-        unsafe {msg.push((orig_len >> (i * 8u64)) as u8);}
+        msg.push((orig_len >> (i * 8u64)) as u8);
         i += 1u64;
     }
 
diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs
index f15632b1431..ec5d2cded8d 100644
--- a/src/libstd/num/bigint.rs
+++ b/src/libstd/num/bigint.rs
@@ -341,7 +341,7 @@ pub impl BigUint {
 
         if new_len == v.len() { return BigUint { data: v }; }
         let mut v = v;
-        unsafe { v.truncate(new_len); }
+        v.truncate(new_len);
         return BigUint { data: v };
     }
 
diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs
index 1a2d4a87d98..f5f7f5e326a 100644
--- a/src/libstd/sha1.rs
+++ b/src/libstd/sha1.rs
@@ -283,134 +283,132 @@ mod tests {
 
     #[test]
     pub fn test() {
-        unsafe {
-            struct Test {
-                input: ~str,
-                output: ~[u8],
-                output_str: ~str,
+        struct Test {
+            input: ~str,
+            output: ~[u8],
+            output_str: ~str,
+        }
+
+        fn a_million_letter_a() -> ~str {
+            let mut i = 0;
+            let mut rs = ~"";
+            while i < 100000 {
+                str::push_str(&mut rs, ~"aaaaaaaaaa");
+                i += 1;
             }
+            return rs;
+        }
+        // Test messages from FIPS 180-1
 
-            fn a_million_letter_a() -> ~str {
-                let mut i = 0;
-                let mut rs = ~"";
-                while i < 100000 {
-                    str::push_str(&mut rs, ~"aaaaaaaaaa");
-                    i += 1;
-                }
-                return rs;
+        let fips_180_1_tests = ~[
+            Test {
+                input: ~"abc",
+                output: ~[
+                    0xA9u8, 0x99u8, 0x3Eu8, 0x36u8,
+                    0x47u8, 0x06u8, 0x81u8, 0x6Au8,
+                    0xBAu8, 0x3Eu8, 0x25u8, 0x71u8,
+                    0x78u8, 0x50u8, 0xC2u8, 0x6Cu8,
+                    0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8,
+                ],
+                output_str: ~"a9993e364706816aba3e25717850c26c9cd0d89d"
+            },
+            Test {
+                input:
+                     ~"abcdbcdecdefdefgefghfghighij" +
+                     ~"hijkijkljklmklmnlmnomnopnopq",
+                output: ~[
+                    0x84u8, 0x98u8, 0x3Eu8, 0x44u8,
+                    0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8,
+                    0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8,
+                    0xF9u8, 0x51u8, 0x29u8, 0xE5u8,
+                    0xE5u8, 0x46u8, 0x70u8, 0xF1u8,
+                ],
+                output_str: ~"84983e441c3bd26ebaae4aa1f95129e5e54670f1"
+            },
+            Test {
+                input: a_million_letter_a(),
+                output: ~[
+                    0x34u8, 0xAAu8, 0x97u8, 0x3Cu8,
+                    0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8,
+                    0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8,
+                    0xDBu8, 0xADu8, 0x27u8, 0x31u8,
+                    0x65u8, 0x34u8, 0x01u8, 0x6Fu8,
+                ],
+                output_str: ~"34aa973cd4c4daa4f61eeb2bdbad27316534016f"
+            },
+        ];
+        // Examples from wikipedia
+
+        let wikipedia_tests = ~[
+            Test {
+                input: ~"The quick brown fox jumps over the lazy dog",
+                output: ~[
+                    0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8,
+                    0x7au8, 0x2du8, 0x28u8, 0xfcu8,
+                    0xedu8, 0x84u8, 0x9eu8, 0xe1u8,
+                    0xbbu8, 0x76u8, 0xe7u8, 0x39u8,
+                    0x1bu8, 0x93u8, 0xebu8, 0x12u8,
+                ],
+                output_str: ~"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
+            },
+            Test {
+                input: ~"The quick brown fox jumps over the lazy cog",
+                output: ~[
+                    0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8,
+                    0xd2u8, 0x5eu8, 0x1bu8, 0x3au8,
+                    0xfau8, 0xd3u8, 0xe8u8, 0x5au8,
+                    0x0bu8, 0xd1u8, 0x7du8, 0x9bu8,
+                    0x10u8, 0x0du8, 0xb4u8, 0xb3u8,
+                ],
+                output_str: ~"de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3",
+            },
+        ];
+        let tests = fips_180_1_tests + wikipedia_tests;
+        fn check_vec_eq(v0: ~[u8], v1: ~[u8]) {
+            assert!((vec::len::<u8>(v0) == vec::len::<u8>(v1)));
+            let len = vec::len::<u8>(v0);
+            let mut i = 0u;
+            while i < len {
+                let a = v0[i];
+                let b = v1[i];
+                assert!((a == b));
+                i += 1u;
             }
-            // Test messages from FIPS 180-1
+        }
+        // Test that it works when accepting the message all at once
 
-            let fips_180_1_tests = ~[
-                Test {
-                    input: ~"abc",
-                    output: ~[
-                        0xA9u8, 0x99u8, 0x3Eu8, 0x36u8,
-                        0x47u8, 0x06u8, 0x81u8, 0x6Au8,
-                        0xBAu8, 0x3Eu8, 0x25u8, 0x71u8,
-                        0x78u8, 0x50u8, 0xC2u8, 0x6Cu8,
-                        0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8,
-                    ],
-                    output_str: ~"a9993e364706816aba3e25717850c26c9cd0d89d"
-                },
-                Test {
-                    input:
-                         ~"abcdbcdecdefdefgefghfghighij" +
-                         ~"hijkijkljklmklmnlmnomnopnopq",
-                    output: ~[
-                        0x84u8, 0x98u8, 0x3Eu8, 0x44u8,
-                        0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8,
-                        0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8,
-                        0xF9u8, 0x51u8, 0x29u8, 0xE5u8,
-                        0xE5u8, 0x46u8, 0x70u8, 0xF1u8,
-                    ],
-                    output_str: ~"84983e441c3bd26ebaae4aa1f95129e5e54670f1"
-                },
-                Test {
-                    input: a_million_letter_a(),
-                    output: ~[
-                        0x34u8, 0xAAu8, 0x97u8, 0x3Cu8,
-                        0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8,
-                        0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8,
-                        0xDBu8, 0xADu8, 0x27u8, 0x31u8,
-                        0x65u8, 0x34u8, 0x01u8, 0x6Fu8,
-                    ],
-                    output_str: ~"34aa973cd4c4daa4f61eeb2bdbad27316534016f"
-                },
-            ];
-            // Examples from wikipedia
+        let mut sh = sha1::sha1();
+        for vec::each(tests) |t| {
+            sh.input_str(t.input);
+            let out = sh.result();
+            check_vec_eq(t.output, out);
 
-            let wikipedia_tests = ~[
-                Test {
-                    input: ~"The quick brown fox jumps over the lazy dog",
-                    output: ~[
-                        0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8,
-                        0x7au8, 0x2du8, 0x28u8, 0xfcu8,
-                        0xedu8, 0x84u8, 0x9eu8, 0xe1u8,
-                        0xbbu8, 0x76u8, 0xe7u8, 0x39u8,
-                        0x1bu8, 0x93u8, 0xebu8, 0x12u8,
-                    ],
-                    output_str: ~"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
-                },
-                Test {
-                    input: ~"The quick brown fox jumps over the lazy cog",
-                    output: ~[
-                        0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8,
-                        0xd2u8, 0x5eu8, 0x1bu8, 0x3au8,
-                        0xfau8, 0xd3u8, 0xe8u8, 0x5au8,
-                        0x0bu8, 0xd1u8, 0x7du8, 0x9bu8,
-                        0x10u8, 0x0du8, 0xb4u8, 0xb3u8,
-                    ],
-                    output_str: ~"de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3",
-                },
-            ];
-            let tests = fips_180_1_tests + wikipedia_tests;
-            fn check_vec_eq(v0: ~[u8], v1: ~[u8]) {
-                assert!((vec::len::<u8>(v0) == vec::len::<u8>(v1)));
-                let len = vec::len::<u8>(v0);
-                let mut i = 0u;
-                while i < len {
-                    let a = v0[i];
-                    let b = v1[i];
-                    assert!((a == b));
-                    i += 1u;
-                }
+            let out_str = sh.result_str();
+            assert!((out_str.len() == 40));
+            assert!((out_str == t.output_str));
+
+            sh.reset();
+        }
+
+
+        // Test that it works when accepting the message in pieces
+        for vec::each(tests) |t| {
+            let len = str::len(t.input);
+            let mut left = len;
+            while left > 0u {
+                let take = (left + 1u) / 2u;
+                sh.input_str(str::slice(t.input, len - left,
+                             take + len - left).to_owned());
+                left = left - take;
             }
-            // Test that it works when accepting the message all at once
+            let out = sh.result();
+            check_vec_eq(t.output, out);
 
-            let mut sh = sha1::sha1();
-            for vec::each(tests) |t| {
-                sh.input_str(t.input);
-                let out = sh.result();
-                check_vec_eq(t.output, out);
+            let out_str = sh.result_str();
+            assert!((out_str.len() == 40));
+            assert!((out_str == t.output_str));
 
-                let out_str = sh.result_str();
-                assert!((out_str.len() == 40));
-                assert!((out_str == t.output_str));
-
-                sh.reset();
-            }
-
-
-            // Test that it works when accepting the message in pieces
-            for vec::each(tests) |t| {
-                let len = str::len(t.input);
-                let mut left = len;
-                while left > 0u {
-                    let take = (left + 1u) / 2u;
-                    sh.input_str(str::slice(t.input, len - left,
-                                 take + len - left).to_owned());
-                    left = left - take;
-                }
-                let out = sh.result();
-                check_vec_eq(t.output, out);
-
-                let out_str = sh.result_str();
-                assert!((out_str.len() == 40));
-                assert!((out_str == t.output_str));
-
-                sh.reset();
-            }
+            sh.reset();
         }
     }
 }
diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs
index 40a12895175..39ca9bb5ba6 100644
--- a/src/libstd/sort.rs
+++ b/src/libstd/sort.rs
@@ -27,7 +27,7 @@ type Le<'self, T> = &'self fn(v1: &T, v2: &T) -> bool;
 pub fn merge_sort<T:Copy>(v: &const [T], le: Le<T>) -> ~[T] {
     type Slice = (uint, uint);
 
-    unsafe {return merge_sort_(v, (0u, len(v)), le);}
+    return merge_sort_(v, (0u, len(v)), le);
 
     fn merge_sort_<T:Copy>(v: &const [T], slice: Slice, le: Le<T>)
         -> ~[T] {
@@ -68,14 +68,11 @@ fn part<T>(arr: &mut [T], left: uint,
     let mut storage_index: uint = left;
     let mut i: uint = left;
     while i < right {
-        // XXX: Unsafe because borrow check doesn't handle this right
-        unsafe {
-            let a: &T = cast::transmute(&mut arr[i]);
-            let b: &T = cast::transmute(&mut arr[right]);
-            if compare_func(a, b) {
-                arr[i] <-> arr[storage_index];
-                storage_index += 1;
-            }
+        let a: &mut T = &mut arr[i];
+        let b: &mut T = &mut arr[right];
+        if compare_func(a, b) {
+            arr[i] <-> arr[storage_index];
+            storage_index += 1;
         }
         i += 1;
     }
@@ -888,12 +885,9 @@ mod tests {
         // tjc: funny that we have to use parens
         fn ile(x: &(&'static str), y: &(&'static str)) -> bool
         {
-            unsafe // to_lower is not pure...
-            {
-                let x = x.to_lower();
-                let y = y.to_lower();
-                x <= y
-            }
+            let x = x.to_lower();
+            let y = y.to_lower();
+            x <= y
         }
 
         let names1 = ~["joe bob", "Joe Bob", "Jack Brown", "JOE Bob",
@@ -921,10 +915,8 @@ mod test_tim_sort {
 
     impl Ord for CVal {
         fn lt(&self, other: &CVal) -> bool {
-            unsafe {
-                let rng = rand::Rng();
-                if rng.gen_float() > 0.995 { fail!(~"It's happening!!!"); }
-            }
+            let rng = rand::Rng();
+            if rng.gen_float() > 0.995 { fail!(~"It's happening!!!"); }
             (*self).val < other.val
         }
         fn le(&self, other: &CVal) -> bool { (*self).val <= other.val }
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 3af193e8748..adfa12594aa 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -176,16 +176,12 @@ pub fn now() -> Tm {
 
 /// Parses the time from the string according to the format string.
 pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> {
-    // unsafe only because do_strptime is annoying to make pure
-    // (it does IO with a str_reader)
-    unsafe {do_strptime(s, format)}
+    do_strptime(s, format)
 }
 
 /// Formats the time according to the format string.
 pub fn strftime(format: &str, tm: &Tm) -> ~str {
-    // unsafe only because do_strftime is annoying to make pure
-    // (it does IO with a str_reader)
-    unsafe { do_strftime(format, tm) }
+    do_strftime(format, tm)
 }
 
 pub impl Tm {
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 7a8aff121a8..fc08073686d 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -252,15 +252,13 @@ pub impl FileMap {
 
     // get a line from the list of pre-computed line-beginnings
     pub fn get_line(&self, line: int) -> ~str {
-        unsafe {
-            let begin: BytePos = self.lines[line] - self.start_pos;
-            let begin = begin.to_uint();
-            let end = match str::find_char_from(*self.src, '\n', begin) {
-                Some(e) => e,
-                None => str::len(*self.src)
-            };
-            str::slice(*self.src, begin, end).to_owned()
-        }
+        let begin: BytePos = self.lines[line] - self.start_pos;
+        let begin = begin.to_uint();
+        let end = match str::find_char_from(*self.src, '\n', begin) {
+            Some(e) => e,
+            None => str::len(*self.src)
+        };
+        str::slice(*self.src, begin, end).to_owned()
     }
 
     pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) {
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 5e06ecf6090..de3d97de177 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -175,12 +175,10 @@ fn byte_offset(rdr: @mut StringReader) -> BytePos {
 }
 
 pub fn get_str_from(rdr: @mut StringReader, start: BytePos) -> ~str {
-    unsafe {
-        // I'm pretty skeptical about this subtraction. What if there's a
-        // multi-byte character before the mark?
-        return str::slice(*rdr.src, start.to_uint() - 1u,
-                          byte_offset(rdr).to_uint() - 1u).to_owned();
-    }
+    // I'm pretty skeptical about this subtraction. What if there's a
+    // multi-byte character before the mark?
+    return str::slice(*rdr.src, start.to_uint() - 1u,
+                      byte_offset(rdr).to_uint() - 1u).to_owned();
 }
 
 // EFFECT: advance the StringReader by one character. If a newline is