about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-10-16 17:05:28 -0700
committerAlex Crichton <alex@alexcrichton.com>2013-10-24 14:21:57 -0700
commitb46f60a72968bd62560c0230b2e5dc63f107f468 (patch)
treedf6fe4b607e94b3d9b4fb19a0abb5e45ad307176
parent9110a38cbfd801983a838775c690c83e9189b4c3 (diff)
downloadrust-b46f60a72968bd62560c0230b2e5dc63f107f468.tar.gz
rust-b46f60a72968bd62560c0230b2e5dc63f107f468.zip
Remove IoFactoryObject for ~IoFactory
This involved changing a fair amount of code, rooted in how we access the local
IoFactory instance. I added a helper method to the rtio module to access the
optional local IoFactory. This is different than before in which it was assumed
that a local IoFactory was *always* present. Now, a separate io_error is raised
when an IoFactory is not present, yet I/O is requested.
-rw-r--r--src/libstd/c_str.rs4
-rw-r--r--src/libstd/rt/io/file.rs114
-rw-r--r--src/libstd/rt/io/mod.rs6
-rw-r--r--src/libstd/rt/io/net/addrinfo.rs22
-rw-r--r--src/libstd/rt/io/net/tcp.rs39
-rw-r--r--src/libstd/rt/io/net/udp.rs19
-rw-r--r--src/libstd/rt/io/net/unix.rs36
-rw-r--r--src/libstd/rt/io/process.rs31
-rw-r--r--src/libstd/rt/io/stdio.rs45
-rw-r--r--src/libstd/rt/io/timer.rs28
-rw-r--r--src/libstd/rt/local.rs20
-rw-r--r--src/libstd/rt/rtio.rs33
-rw-r--r--src/libstd/rt/sched.rs7
-rw-r--r--src/libstd/rt/test.rs4
-rw-r--r--src/libstd/rt/uv/file.rs52
-rw-r--r--src/libstd/rt/uv/uvio.rs157
-rw-r--r--src/libstd/str.rs1
17 files changed, 303 insertions, 315 deletions
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index ba64a71553f..b2e68c8d20f 100644
--- a/src/libstd/c_str.rs
+++ b/src/libstd/c_str.rs
@@ -382,6 +382,7 @@ mod tests {
     use libc;
     use ptr;
     use option::{Some, None};
+    use vec;
 
     #[test]
     fn test_str_multistring_parsing() {
@@ -391,7 +392,8 @@ mod tests {
             let expected = ["zero", "one"];
             let mut it = expected.iter();
             let result = do from_c_multistring(ptr as *libc::c_char, None) |c| {
-                assert_eq!(c.as_str(), expected.next().unwrap());
+                let cbytes = c.as_bytes().slice_to(c.len());
+                assert_eq!(cbytes, it.next().unwrap().as_bytes());
             };
             assert_eq!(result, 2);
             assert!(it.next().is_none());
diff --git a/src/libstd/rt/io/file.rs b/src/libstd/rt/io/file.rs
index cc39db44431..0bd0213b5b0 100644
--- a/src/libstd/rt/io/file.rs
+++ b/src/libstd/rt/io/file.rs
@@ -34,12 +34,11 @@ use prelude::*;
 use c_str::ToCStr;
 use super::{Reader, Writer, Seek};
 use super::{SeekStyle, Read, Write};
-use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
+use rt::rtio::{RtioFileStream, IoFactory, with_local_io};
 use rt::io::{io_error, read_error, EndOfFile,
             FileMode, FileAccess, FileStat, IoError,
             PathAlreadyExists, PathDoesntExist,
             MismatchedFileTypeForOperation, ignore_io_error};
-use rt::local::Local;
 use option::{Some, None};
 use path::Path;
 
@@ -90,19 +89,17 @@ use path::Path;
 pub fn open<P: ToCStr>(path: &P,
                        mode: FileMode,
                        access: FileAccess
-                       ) -> Option<FileStream> {
-    let open_result = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_open(&path.to_c_str(), mode, access)
-    };
-    match open_result {
-        Ok(fd) => Some(FileStream {
-            fd: fd,
-            last_nread: -1
-        }),
-        Err(ioerr) => {
-            io_error::cond.raise(ioerr);
-            None
+                      ) -> Option<FileStream> {
+    do with_local_io |io| {
+        match io.fs_open(&path.to_c_str(), mode, access) {
+            Ok(fd) => Some(FileStream {
+                fd: fd,
+                last_nread: -1
+            }),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
         }
     }
 }
@@ -129,16 +126,15 @@ pub fn open<P: ToCStr>(path: &P,
 /// This function will raise an `io_error` condition if the user lacks permissions to
 /// remove the file or if some other filesystem-level error occurs
 pub fn unlink<P: ToCStr>(path: &P) {
-    let unlink_result = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_unlink(&path.to_c_str())
-    };
-    match unlink_result {
-        Ok(_) => (),
-        Err(ioerr) => {
-            io_error::cond.raise(ioerr);
+    do with_local_io |io| {
+        match io.fs_unlink(&path.to_c_str()) {
+            Ok(_) => Some(()),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
         }
-    }
+    };
 }
 
 /// Create a new, empty directory at the provided path
@@ -158,16 +154,15 @@ pub fn unlink<P: ToCStr>(path: &P) {
 /// This call will raise an `io_error` condition if the user lacks permissions to make a
 /// new directory at the provided path, or if the directory already exists
 pub fn mkdir<P: ToCStr>(path: &P) {
-    let mkdir_result = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_mkdir(&path.to_c_str())
-    };
-    match mkdir_result {
-        Ok(_) => (),
-        Err(ioerr) => {
-            io_error::cond.raise(ioerr);
+    do with_local_io |io| {
+        match io.fs_mkdir(&path.to_c_str()) {
+            Ok(_) => Some(()),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
         }
-    }
+    };
 }
 
 /// Remove an existing, empty directory
@@ -187,16 +182,15 @@ pub fn mkdir<P: ToCStr>(path: &P) {
 /// This call will raise an `io_error` condition if the user lacks permissions to remove the
 /// directory at the provided path, or if the directory isn't empty
 pub fn rmdir<P: ToCStr>(path: &P) {
-    let rmdir_result = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_rmdir(&path.to_c_str())
-    };
-    match rmdir_result {
-        Ok(_) => (),
-        Err(ioerr) => {
-            io_error::cond.raise(ioerr);
+    do with_local_io |io| {
+        match io.fs_rmdir(&path.to_c_str()) {
+            Ok(_) => Some(()),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
         }
-    }
+    };
 }
 
 /// Get information on the file, directory, etc at the provided path
@@ -235,17 +229,13 @@ pub fn rmdir<P: ToCStr>(path: &P) {
 /// permissions to perform a `stat` call on the given path or if there is no
 /// entry in the filesystem at the provided path.
 pub fn stat<P: ToCStr>(path: &P) -> Option<FileStat> {
-    let open_result = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_stat(&path.to_c_str())
-    };
-    match open_result {
-        Ok(p) => {
-            Some(p)
-        },
-        Err(ioerr) => {
-            io_error::cond.raise(ioerr);
-            None
+    do with_local_io |io| {
+        match io.fs_stat(&path.to_c_str()) {
+            Ok(p) => Some(p),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
         }
     }
 }
@@ -275,17 +265,13 @@ pub fn stat<P: ToCStr>(path: &P) -> Option<FileStat> {
 /// the process lacks permissions to view the contents or if the `path` points
 /// at a non-directory file
 pub fn readdir<P: ToCStr>(path: &P) -> Option<~[Path]> {
-    let readdir_result = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_readdir(&path.to_c_str(), 0)
-    };
-    match readdir_result {
-        Ok(p) => {
-            Some(p)
-        },
-        Err(ioerr) => {
-            io_error::cond.raise(ioerr);
-            None
+    do with_local_io |io| {
+        match io.fs_readdir(&path.to_c_str(), 0) {
+            Ok(p) => Some(p),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
         }
     }
 }
diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs
index cb6361ff4e3..1a5c197fd52 100644
--- a/src/libstd/rt/io/mod.rs
+++ b/src/libstd/rt/io/mod.rs
@@ -369,7 +369,8 @@ pub enum IoErrorKind {
     BrokenPipe,
     PathAlreadyExists,
     PathDoesntExist,
-    MismatchedFileTypeForOperation
+    MismatchedFileTypeForOperation,
+    IoUnavailable,
 }
 
 // FIXME: #8242 implementing manually because deriving doesn't work for some reason
@@ -389,7 +390,8 @@ impl ToStr for IoErrorKind {
             BrokenPipe => ~"BrokenPipe",
             PathAlreadyExists => ~"PathAlreadyExists",
             PathDoesntExist => ~"PathDoesntExist",
-            MismatchedFileTypeForOperation => ~"MismatchedFileTypeForOperation"
+            MismatchedFileTypeForOperation => ~"MismatchedFileTypeForOperation",
+            IoUnavailable => ~"IoUnavailable",
         }
     }
 }
diff --git a/src/libstd/rt/io/net/addrinfo.rs b/src/libstd/rt/io/net/addrinfo.rs
index ae0d542acbe..e0c92730cd9 100644
--- a/src/libstd/rt/io/net/addrinfo.rs
+++ b/src/libstd/rt/io/net/addrinfo.rs
@@ -19,10 +19,9 @@ getaddrinfo()
 
 use option::{Option, Some, None};
 use result::{Ok, Err};
-use rt::io::io_error;
+use rt::io::{io_error};
 use rt::io::net::ip::{SocketAddr, IpAddr};
-use rt::rtio::{IoFactory, IoFactoryObject};
-use rt::local::Local;
+use rt::rtio::{IoFactory, with_local_io};
 
 /// Hints to the types of sockets that are desired when looking up hosts
 pub enum SocketType {
@@ -94,16 +93,13 @@ pub fn get_host_addresses(host: &str) -> Option<~[IpAddr]> {
 /// On failure, this will raise on the `io_error` condition.
 pub fn lookup(hostname: Option<&str>, servname: Option<&str>,
               hint: Option<Hint>) -> Option<~[Info]> {
-    let ipaddrs = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).get_host_addresses(hostname, servname, hint)
-    };
-
-    match ipaddrs {
-        Ok(i) => Some(i),
-        Err(ioerr) => {
-            io_error::cond.raise(ioerr);
-            None
+    do with_local_io |io| {
+        match io.get_host_addresses(hostname, servname, hint) {
+            Ok(i) => Some(i),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
         }
     }
 }
diff --git a/src/libstd/rt/io/net/tcp.rs b/src/libstd/rt/io/net/tcp.rs
index 946ecbea6f7..bafde180d5c 100644
--- a/src/libstd/rt/io/net/tcp.rs
+++ b/src/libstd/rt/io/net/tcp.rs
@@ -13,9 +13,8 @@ use result::{Ok, Err};
 use rt::io::net::ip::SocketAddr;
 use rt::io::{Reader, Writer, Listener, Acceptor};
 use rt::io::{io_error, read_error, EndOfFile};
-use rt::rtio::{IoFactory, IoFactoryObject, RtioTcpListenerObject,
+use rt::rtio::{IoFactory, RtioTcpListenerObject, with_local_io,
                RtioSocket, RtioTcpListener, RtioTcpAcceptor, RtioTcpStream};
-use rt::local::Local;
 
 pub struct TcpStream {
     priv obj: ~RtioTcpStream
@@ -27,19 +26,13 @@ impl TcpStream {
     }
 
     pub fn connect(addr: SocketAddr) -> Option<TcpStream> {
-        let stream = unsafe {
-            rtdebug!("borrowing io to connect");
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
-            rtdebug!("about to connect");
-            (*io).tcp_connect(addr)
-        };
-
-        match stream {
-            Ok(s) => Some(TcpStream::new(s)),
-            Err(ioerr) => {
-                rtdebug!("failed to connect: {:?}", ioerr);
-                io_error::cond.raise(ioerr);
-                None
+        do with_local_io |io| {
+            match io.tcp_connect(addr) {
+                Ok(s) => Some(TcpStream::new(s)),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
             }
         }
     }
@@ -101,15 +94,13 @@ pub struct TcpListener {
 
 impl TcpListener {
     pub fn bind(addr: SocketAddr) -> Option<TcpListener> {
-        let listener = unsafe {
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
-            (*io).tcp_bind(addr)
-        };
-        match listener {
-            Ok(l) => Some(TcpListener { obj: l }),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                return None;
+        do with_local_io |io| {
+            match io.tcp_bind(addr) {
+                Ok(l) => Some(TcpListener { obj: l }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
             }
         }
     }
diff --git a/src/libstd/rt/io/net/udp.rs b/src/libstd/rt/io/net/udp.rs
index ed01dc9dcda..eee5dce7b6c 100644
--- a/src/libstd/rt/io/net/udp.rs
+++ b/src/libstd/rt/io/net/udp.rs
@@ -13,8 +13,7 @@ use result::{Ok, Err};
 use rt::io::net::ip::SocketAddr;
 use rt::io::{Reader, Writer};
 use rt::io::{io_error, read_error, EndOfFile};
-use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, IoFactoryObject};
-use rt::local::Local;
+use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, with_local_io};
 
 pub struct UdpSocket {
     priv obj: ~RtioUdpSocket
@@ -22,15 +21,13 @@ pub struct UdpSocket {
 
 impl UdpSocket {
     pub fn bind(addr: SocketAddr) -> Option<UdpSocket> {
-        let socket = unsafe {
-            let factory: *mut IoFactoryObject = Local::unsafe_borrow();
-            (*factory).udp_bind(addr)
-        };
-        match socket {
-            Ok(s) => Some(UdpSocket { obj: s }),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
+        do with_local_io |io| {
+            match io.udp_bind(addr) {
+                Ok(s) => Some(UdpSocket { obj: s }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
             }
         }
     }
diff --git a/src/libstd/rt/io/net/unix.rs b/src/libstd/rt/io/net/unix.rs
index fe045bff050..b98d5b52cb2 100644
--- a/src/libstd/rt/io/net/unix.rs
+++ b/src/libstd/rt/io/net/unix.rs
@@ -25,11 +25,10 @@ instances as clients.
 use prelude::*;
 
 use c_str::ToCStr;
-use rt::rtio::{IoFactory, IoFactoryObject, RtioUnixListener};
+use rt::rtio::{IoFactory, RtioUnixListener, with_local_io};
 use rt::rtio::{RtioUnixAcceptor, RtioPipe, RtioUnixListenerObject};
 use rt::io::pipe::PipeStream;
 use rt::io::{io_error, Listener, Acceptor, Reader, Writer};
-use rt::local::Local;
 
 /// A stream which communicates over a named pipe.
 pub struct UnixStream {
@@ -60,16 +59,13 @@ impl UnixStream {
     ///     stream.write([1, 2, 3]);
     ///
     pub fn connect<P: ToCStr>(path: &P) -> Option<UnixStream> {
-        let pipe = unsafe {
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
-            (*io).unix_connect(path)
-        };
-
-        match pipe {
-            Ok(s) => Some(UnixStream::new(s)),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
+        do with_local_io |io| {
+            match io.unix_connect(&path.to_c_str()) {
+                Ok(s) => Some(UnixStream::new(s)),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
             }
         }
     }
@@ -113,15 +109,13 @@ impl UnixListener {
     ///     }
     ///
     pub fn bind<P: ToCStr>(path: &P) -> Option<UnixListener> {
-        let listener = unsafe {
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
-            (*io).unix_bind(path)
-        };
-        match listener {
-            Ok(s) => Some(UnixListener{ obj: s }),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
+        do with_local_io |io| {
+            match io.unix_bind(&path.to_c_str()) {
+                Ok(s) => Some(UnixListener{ obj: s }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
             }
         }
     }
diff --git a/src/libstd/rt/io/process.rs b/src/libstd/rt/io/process.rs
index c13b275ae52..c45429ca2e6 100644
--- a/src/libstd/rt/io/process.rs
+++ b/src/libstd/rt/io/process.rs
@@ -11,12 +11,12 @@
 //! Bindings for executing child processes
 
 use prelude::*;
+use cell::Cell;
 
 use libc;
 use rt::io;
 use rt::io::io_error;
-use rt::local::Local;
-use rt::rtio::{RtioProcess, IoFactoryObject, IoFactory};
+use rt::rtio::{RtioProcess, IoFactory, with_local_io};
 
 // windows values don't matter as long as they're at least one of unix's
 // TERM/KILL/INT signals
@@ -83,20 +83,19 @@ impl Process {
     /// Creates a new pipe initialized, but not bound to any particular
     /// source/destination
     pub fn new(config: ProcessConfig) -> Option<Process> {
-        let process = unsafe {
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
-            (*io).spawn(config)
-        };
-        match process {
-            Ok((p, io)) => Some(Process{
-                handle: p,
-                io: io.move_iter().map(|p|
-                    p.map(|p| io::PipeStream::new_bound(p))
-                ).collect()
-            }),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
+        let config = Cell::new(config);
+        do with_local_io |io| {
+            match io.spawn(config.take()) {
+                Ok((p, io)) => Some(Process{
+                    handle: p,
+                    io: io.move_iter().map(|p|
+                        p.map(|p| io::PipeStream::new_bound(p))
+                    ).collect()
+                }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
             }
         }
     }
diff --git a/src/libstd/rt/io/stdio.rs b/src/libstd/rt/io/stdio.rs
index 77ac87830e2..a3cbe87431d 100644
--- a/src/libstd/rt/io/stdio.rs
+++ b/src/libstd/rt/io/stdio.rs
@@ -12,19 +12,22 @@ use fmt;
 use libc;
 use option::{Option, Some, None};
 use result::{Ok, Err};
-use rt::local::Local;
-use rt::rtio::{IoFactoryObject, IoFactory, RtioTTY};
+use rt::rtio::{IoFactory, RtioTTY, with_local_io};
 use super::{Reader, Writer, io_error};
 
 /// Creates a new non-blocking handle to the stdin of the current process.
 ///
 /// See `stdout()` for notes about this function.
 pub fn stdin() -> StdReader {
-    let stream = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).tty_open(libc::STDIN_FILENO, true, false)
-    }.unwrap();
-    StdReader { inner: stream }
+    do with_local_io |io| {
+        match io.tty_open(libc::STDIN_FILENO, true, false) {
+            Ok(tty) => Some(StdReader { inner: tty }),
+            Err(e) => {
+                io_error::cond.raise(e);
+                None
+            }
+        }
+    }.unwrap()
 }
 
 /// Creates a new non-blocking handle to the stdout of the current process.
@@ -34,22 +37,30 @@ pub fn stdin() -> StdReader {
 /// task context because the stream returned will be a non-blocking object using
 /// the local scheduler to perform the I/O.
 pub fn stdout() -> StdWriter {
-    let stream = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).tty_open(libc::STDOUT_FILENO, false, false)
-    }.unwrap();
-    StdWriter { inner: stream }
+    do with_local_io |io| {
+        match io.tty_open(libc::STDOUT_FILENO, false, false) {
+            Ok(tty) => Some(StdWriter { inner: tty }),
+            Err(e) => {
+                io_error::cond.raise(e);
+                None
+            }
+        }
+    }.unwrap()
 }
 
 /// Creates a new non-blocking handle to the stderr of the current process.
 ///
 /// See `stdout()` for notes about this function.
 pub fn stderr() -> StdWriter {
-    let stream = unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).tty_open(libc::STDERR_FILENO, false, false)
-    }.unwrap();
-    StdWriter { inner: stream }
+    do with_local_io |io| {
+        match io.tty_open(libc::STDERR_FILENO, false, false) {
+            Ok(tty) => Some(StdWriter { inner: tty }),
+            Err(e) => {
+                io_error::cond.raise(e);
+                None
+            }
+        }
+    }.unwrap()
 }
 
 /// Prints a string to the stdout of the current process. No newline is emitted
diff --git a/src/libstd/rt/io/timer.rs b/src/libstd/rt/io/timer.rs
index 7d13e034dc1..fab0062ee00 100644
--- a/src/libstd/rt/io/timer.rs
+++ b/src/libstd/rt/io/timer.rs
@@ -10,9 +10,8 @@
 
 use option::{Option, Some, None};
 use result::{Ok, Err};
-use rt::io::{io_error};
-use rt::rtio::{IoFactory, IoFactoryObject, RtioTimer};
-use rt::local::Local;
+use rt::io::io_error;
+use rt::rtio::{IoFactory, RtioTimer, with_local_io};
 
 pub struct Timer {
     priv obj: ~RtioTimer
@@ -27,20 +26,19 @@ pub fn sleep(msecs: u64) {
 
 impl Timer {
 
+    /// Creates a new timer which can be used to put the current task to sleep
+    /// for a number of milliseconds.
     pub fn new() -> Option<Timer> {
-        let timer = unsafe {
-            rtdebug!("Timer::init: borrowing io to init timer");
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
-            rtdebug!("about to init timer");
-            (*io).timer_init()
-        };
-        match timer {
-            Ok(t) => Some(Timer { obj: t }),
-            Err(ioerr) => {
-                rtdebug!("Timer::init: failed to init: {:?}", ioerr);
-                io_error::cond.raise(ioerr);
-                None
+        do with_local_io |io| {
+            match io.timer_init() {
+                Ok(t) => Some(Timer { obj: t }),
+                Err(ioerr) => {
+                    rtdebug!("Timer::init: failed to init: {:?}", ioerr);
+                    io_error::cond.raise(ioerr);
+                    None
+                }
             }
+
         }
     }
 
diff --git a/src/libstd/rt/local.rs b/src/libstd/rt/local.rs
index d4f31879c00..1ddc2f86f4b 100644
--- a/src/libstd/rt/local.rs
+++ b/src/libstd/rt/local.rs
@@ -12,8 +12,6 @@ use option::{Option, Some, None};
 use rt::sched::Scheduler;
 use rt::task::Task;
 use rt::local_ptr;
-use rt::rtio::{EventLoop, IoFactoryObject};
-//use borrow::to_uint;
 use cell::Cell;
 
 pub trait Local {
@@ -122,24 +120,6 @@ impl Local for Scheduler {
     }
 }
 
-// XXX: This formulation won't work once ~IoFactoryObject is a real trait pointer
-impl Local for IoFactoryObject {
-    fn put(_value: ~IoFactoryObject) { rtabort!("unimpl") }
-    fn take() -> ~IoFactoryObject { rtabort!("unimpl") }
-    fn exists(_: Option<IoFactoryObject>) -> bool { rtabort!("unimpl") }
-    fn borrow<T>(_f: &fn(&mut IoFactoryObject) -> T) -> T { rtabort!("unimpl") }
-    unsafe fn unsafe_take() -> ~IoFactoryObject { rtabort!("unimpl") }
-    unsafe fn unsafe_borrow() -> *mut IoFactoryObject {
-        let sched: *mut Scheduler = Local::unsafe_borrow();
-        let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap();
-        return io;
-    }
-    unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> {
-        rtabort!("unimpl")
-    }
-}
-
-
 #[cfg(test)]
 mod test {
     use option::None;
diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs
index c889355f353..897bf328f23 100644
--- a/src/libstd/rt/rtio.rs
+++ b/src/libstd/rt/rtio.rs
@@ -33,8 +33,10 @@ pub trait EventLoop {
     fn pausible_idle_callback(&mut self) -> ~PausibleIdleCallback;
     fn callback_ms(&mut self, ms: u64, ~fn());
     fn remote_callback(&mut self, ~fn()) -> ~RemoteCallback;
+
     /// The asynchronous I/O services. Not all event loops may provide one
-    fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory>;
+    // FIXME(#9382) this is an awful interface
+    fn io<'a>(&'a mut self, f: &fn(&'a mut IoFactory));
 }
 
 pub trait RemoteCallback {
@@ -59,16 +61,36 @@ pub struct FileOpenConfig {
     priv mode: int
 }
 
+pub fn with_local_io<T>(f: &fn(&mut IoFactory) -> Option<T>) -> Option<T> {
+    use rt::sched::Scheduler;
+    use rt::local::Local;
+    use rt::io::{io_error, standard_error, IoUnavailable};
+
+    unsafe {
+        let sched: *mut Scheduler = Local::unsafe_borrow();
+        let mut io = None;
+        (*sched).event_loop.io(|i| io = Some(i));
+        match io {
+            Some(io) => f(io),
+            None => {
+                io_error::cond.raise(standard_error(IoUnavailable));
+                None
+            }
+        }
+    }
+}
+
 pub trait IoFactory {
     fn tcp_connect(&mut self, addr: SocketAddr) -> Result<~RtioTcpStream, IoError>;
     fn tcp_bind(&mut self, addr: SocketAddr) -> Result<~RtioTcpListenerObject, IoError>;
     fn udp_bind(&mut self, addr: SocketAddr) -> Result<~RtioUdpSocket, IoError>;
+    fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
+                          hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError>;
     fn timer_init(&mut self) -> Result<~RtioTimer, IoError>;
     fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileStream;
     fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
         -> Result<~RtioFileStream, IoError>;
-    fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
-                          hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError>;
+    fn fs_unlink(&mut self, path: &CString) -> Result<(), IoError>;
     fn fs_stat(&mut self, path: &CString) -> Result<FileStat, IoError>;
     fn fs_mkdir(&mut self, path: &CString) -> Result<(), IoError>;
     fn fs_rmdir(&mut self, path: &CString) -> Result<(), IoError>;
@@ -77,10 +99,9 @@ pub trait IoFactory {
     fn spawn(&mut self, config: ProcessConfig)
             -> Result<(~RtioProcess, ~[Option<~RtioPipe>]), IoError>;
 
-    fn unix_bind<P: PathLike>(&mut self, path: &P) ->
+    fn unix_bind(&mut self, path: &CString) ->
         Result<~RtioUnixListenerObject, IoError>;
-    fn unix_connect<P: PathLike>(&mut self, path: &P) ->
-        Result<~RtioPipe, IoError>;
+    fn unix_connect(&mut self, path: &CString) -> Result<~RtioPipe, IoError>;
     fn tty_open(&mut self, fd: c_int, readable: bool, close_on_drop: bool)
             -> Result<~RtioTTY, IoError>;
 }
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index 464e2b2c4c2..6e661884616 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -905,6 +905,7 @@ mod test {
     use cell::Cell;
     use rt::thread::Thread;
     use rt::task::{Task, Sched};
+    use rt::rtio::EventLoop;
     use rt::util;
     use option::{Some};
 
@@ -1020,7 +1021,7 @@ mod test {
 
             // Our normal scheduler
             let mut normal_sched = ~Scheduler::new(
-                ~UvEventLoop::new(),
+                ~UvEventLoop::new() as ~EventLoop,
                 normal_queue,
                 queues.clone(),
                 sleepers.clone());
@@ -1031,7 +1032,7 @@ mod test {
 
             // Our special scheduler
             let mut special_sched = ~Scheduler::new_special(
-                ~UvEventLoop::new(),
+                ~UvEventLoop::new() as ~EventLoop,
                 special_queue.clone(),
                 queues.clone(),
                 sleepers.clone(),
@@ -1202,7 +1203,7 @@ mod test {
                 let queues = ~[queue.clone()];
 
                 let mut sched = ~Scheduler::new(
-                    ~UvEventLoop::new(),
+                    ~UvEventLoop::new() as ~EventLoop,
                     queue,
                     queues.clone(),
                     sleepers.clone());
diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs
index 66d3f3de6ec..c238b1dfba1 100644
--- a/src/libstd/rt/test.rs
+++ b/src/libstd/rt/test.rs
@@ -13,7 +13,7 @@ use rand::Rng;
 use os;
 use libc;
 use option::{Some, None};
-use path::{Path, GenericPath};
+use path::Path;
 use cell::Cell;
 use clone::Clone;
 use container::Container;
@@ -335,7 +335,7 @@ pub fn next_test_port() -> u16 {
 /// Get a temporary path which could be the location of a unix socket
 #[fixed_stack_segment] #[inline(never)]
 pub fn next_test_unix() -> Path {
-    os::tmpdir().push(rand::task_rng().gen_ascii_str(20))
+    os::tmpdir().join(rand::task_rng().gen_ascii_str(20))
 }
 
 /// Get a unique IPv4 localhost:port pair starting at 9600
diff --git a/src/libstd/rt/uv/file.rs b/src/libstd/rt/uv/file.rs
index 07a22bc00e3..78b3a88f5f1 100644
--- a/src/libstd/rt/uv/file.rs
+++ b/src/libstd/rt/uv/file.rs
@@ -272,7 +272,6 @@ impl FsRequest {
     }
 
     pub fn each_path(&mut self, f: &fn(&CString)) {
-        use str;
         let ptr = self.get_ptr();
         match self.get_result() {
             n if (n <= 0) => {}
@@ -350,7 +349,6 @@ mod test {
     use vec;
     use str;
     use unstable::run_in_bare_thread;
-    use path::Path;
     use rt::uv::{Loop, Buf, slice_to_uv_buf};
     use libc::{O_CREAT, O_RDWR, O_RDONLY, S_IWUSR, S_IRUSR};
 
@@ -373,10 +371,9 @@ mod test {
             let read_mem = vec::from_elem(read_buf_len, 0u8);
             let read_buf = slice_to_uv_buf(read_mem);
             let read_buf_ptr: *Buf = &read_buf;
-            let p = Path::new(path_str);
             let open_req = FsRequest::new();
-            do open_req.open(&loop_, &p, create_flags as int, mode as int)
-            |req, uverr| {
+            do open_req.open(&loop_, &path_str.to_c_str(), create_flags as int,
+                             mode as int) |req, uverr| {
                 assert!(uverr.is_none());
                 let fd = req.get_result();
                 let buf = unsafe { *write_buf_ptr };
@@ -387,8 +384,8 @@ mod test {
                         assert!(uverr.is_none());
                         let loop_ = req.get_loop();
                         let open_req = FsRequest::new();
-                        do open_req.open(&loop_, &Path::new(path_str), read_flags as int,0)
-                            |req, uverr| {
+                        do open_req.open(&loop_, &path_str.to_c_str(),
+                                         read_flags as int,0) |req, uverr| {
                             assert!(uverr.is_none());
                             let loop_ = req.get_loop();
                             let fd = req.get_result();
@@ -413,7 +410,8 @@ mod test {
                                         assert!(uverr.is_none());
                                         let loop_ = &req.get_loop();
                                         let unlink_req = FsRequest::new();
-                                        do unlink_req.unlink(loop_, &Path::new(path_str))
+                                        do unlink_req.unlink(loop_,
+                                                             &path_str.to_c_str())
                                         |_,uverr| {
                                             assert!(uverr.is_none());
                                         };
@@ -447,8 +445,8 @@ mod test {
             let write_buf = slice_to_uv_buf(write_val);
             // open/create
             let open_req = FsRequest::new();
-            let result = open_req.open_sync(&loop_, &Path::new(path_str),
-                                                   create_flags as int, mode as int);
+            let result = open_req.open_sync(&loop_, &path_str.to_c_str(),
+                                            create_flags as int, mode as int);
             assert!(result.is_ok());
             let fd = result.unwrap();
             // write
@@ -461,7 +459,7 @@ mod test {
             assert!(result.is_ok());
             // re-open
             let open_req = FsRequest::new();
-            let result = open_req.open_sync(&loop_, &Path::new(path_str),
+            let result = open_req.open_sync(&loop_, &path_str.to_c_str(),
                                                    read_flags as int,0);
             assert!(result.is_ok());
             let len = 1028;
@@ -485,7 +483,7 @@ mod test {
                 assert!(result.is_ok());
                 // unlink
                 let unlink_req = FsRequest::new();
-                let result = unlink_req.unlink_sync(&loop_, &Path::new(path_str));
+                let result = unlink_req.unlink_sync(&loop_, &path_str.to_c_str());
                 assert!(result.is_ok());
             } else { fail!("nread was 0.. wudn't expectin' that."); }
             loop_.close();
@@ -521,8 +519,8 @@ mod test {
             let write_buf  = slice_to_uv_buf(write_val);
             let write_buf_ptr: *Buf = &write_buf;
             let open_req = FsRequest::new();
-            do open_req.open(&loop_, &path, create_flags as int, mode as int)
-            |req, uverr| {
+            do open_req.open(&loop_, &path.to_c_str(), create_flags as int,
+                             mode as int) |req, uverr| {
                 assert!(uverr.is_none());
                 let fd = req.get_result();
                 let buf = unsafe { *write_buf_ptr };
@@ -531,7 +529,7 @@ mod test {
                     assert!(uverr.is_none());
                     let loop_ = req.get_loop();
                     let stat_req = FsRequest::new();
-                    do stat_req.stat(&loop_, &path) |req, uverr| {
+                    do stat_req.stat(&loop_, &path.to_c_str()) |req, uverr| {
                         assert!(uverr.is_none());
                         let loop_ = req.get_loop();
                         let stat = req.get_stat();
@@ -542,11 +540,13 @@ mod test {
                             assert!(uverr.is_none());
                             let loop_ = req.get_loop();
                             let unlink_req = FsRequest::new();
-                            do unlink_req.unlink(&loop_, &path) |req,uverr| {
+                            do unlink_req.unlink(&loop_,
+                                                 &path.to_c_str()) |req,uverr| {
                                 assert!(uverr.is_none());
                                 let loop_ = req.get_loop();
                                 let stat_req = FsRequest::new();
-                                do stat_req.stat(&loop_, &path) |_, uverr| {
+                                do stat_req.stat(&loop_,
+                                                 &path.to_c_str()) |_, uverr| {
                                     // should cause an error because the
                                     // file doesn't exist anymore
                                     assert!(uverr.is_some());
@@ -569,22 +569,23 @@ mod test {
             let mode = S_IWUSR |
                 S_IRUSR;
             let mkdir_req = FsRequest::new();
-            do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
+            do mkdir_req.mkdir(&loop_, &path.to_c_str(),
+                               mode as int) |req,uverr| {
                 assert!(uverr.is_none());
                 let loop_ = req.get_loop();
                 let stat_req = FsRequest::new();
-                do stat_req.stat(&loop_, &path) |req, uverr| {
+                do stat_req.stat(&loop_, &path.to_c_str()) |req, uverr| {
                     assert!(uverr.is_none());
                     let loop_ = req.get_loop();
                     let stat = req.get_stat();
                     naive_print(&loop_, format!("{:?}", stat));
                     assert!(stat.is_dir());
                     let rmdir_req = FsRequest::new();
-                    do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
+                    do rmdir_req.rmdir(&loop_, &path.to_c_str()) |req,uverr| {
                         assert!(uverr.is_none());
                         let loop_ = req.get_loop();
                         let stat_req = FsRequest::new();
-                        do stat_req.stat(&loop_, &path) |_req, uverr| {
+                        do stat_req.stat(&loop_, &path.to_c_str()) |_req, uverr| {
                             assert!(uverr.is_some());
                         }
                     }
@@ -602,16 +603,17 @@ mod test {
             let mode = S_IWUSR |
                 S_IRUSR;
             let mkdir_req = FsRequest::new();
-            do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
+            do mkdir_req.mkdir(&loop_, &path.to_c_str(), mode as int) |req,uverr| {
                 assert!(uverr.is_none());
                 let loop_ = req.get_loop();
                 let mkdir_req = FsRequest::new();
-                do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
+                do mkdir_req.mkdir(&loop_, &path.to_c_str(),
+                                   mode as int) |req,uverr| {
                     assert!(uverr.is_some());
                     let loop_ = req.get_loop();
                     let _stat = req.get_stat();
                     let rmdir_req = FsRequest::new();
-                    do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
+                    do rmdir_req.rmdir(&loop_, &path.to_c_str()) |req,uverr| {
                         assert!(uverr.is_none());
                         let _loop = req.get_loop();
                     }
@@ -627,7 +629,7 @@ mod test {
             let mut loop_ = Loop::new();
             let path = "./tmp/never_existed_dir";
             let rmdir_req = FsRequest::new();
-            do rmdir_req.rmdir(&loop_, &path) |_req, uverr| {
+            do rmdir_req.rmdir(&loop_, &path.to_c_str()) |_req, uverr| {
                 assert!(uverr.is_some());
             }
             loop_.run();
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs
index b0cdce7dd93..96719e98972 100644
--- a/src/libstd/rt/uv/uvio.rs
+++ b/src/libstd/rt/uv/uvio.rs
@@ -18,7 +18,6 @@ use ops::Drop;
 use option::*;
 use ptr;
 use str;
-use str::Str;
 use result::*;
 use rt::io::IoError;
 use rt::io::net::ip::{SocketAddr, IpAddr};
@@ -234,8 +233,8 @@ impl EventLoop for UvEventLoop {
         ~UvRemoteCallback::new(self.uvio.uv_loop(), f) as ~RemoteCallback
     }
 
-    fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory> {
-        Some(&mut self.uvio as &mut IoFactory)
+    fn io<'a>(&'a mut self, f: &fn(&'a mut IoFactory)) {
+        f(&mut self.uvio as &mut IoFactory)
     }
 }
 
@@ -245,7 +244,7 @@ pub struct UvPausibleIdleCallback {
     priv closed: bool
 }
 
-impl RtioPausibleIdleCallback for UvPausibleIdleCallback {
+impl PausibleIdleCallback for UvPausibleIdleCallback {
     #[inline]
     fn start(&mut self, f: ~fn()) {
         do self.watcher.start |_idle_watcher, _status| {
@@ -626,7 +625,9 @@ impl IoFactory for UvIoFactory {
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task_cell = Cell::new(task);
                 let path = path_cell.take();
-                let path_instance = Cell::new(Path::new(path.as_bytes()));
+                // Don't pick up the null byte
+                let slice = path.as_bytes().slice(0, path.len());
+                let path_instance = Cell::new(Path::new(slice));
                 do stat_req.stat(self.uv_loop(), path) |req,err| {
                     let res = match err {
                         None => {
@@ -720,14 +721,17 @@ impl IoFactory for UvIoFactory {
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task_cell = Cell::new(task);
                 let path = path_cell.take();
-                let path_parent = Cell::new(Path::new(path.as_bytes()));
+                // Don't pick up the null byte
+                let slice = path.as_bytes().slice(0, path.len());
+                let path_parent = Cell::new(Path::new(slice));
                 do stat_req.readdir(self.uv_loop(), path, flags) |req,err| {
                     let parent = path_parent.take();
                     let res = match err {
                         None => {
                             let mut paths = ~[];
                             do req.each_path |rel_path| {
-                                paths.push(parent.join(rel_path.as_bytes()));
+                                let p = rel_path.as_bytes();
+                                paths.push(parent.join(p.slice_to(rel_path.len())));
                             }
                             Ok(paths)
                         },
@@ -799,10 +803,10 @@ impl IoFactory for UvIoFactory {
         }
     }
 
-    fn unix_bind<P: PathLike>(&mut self, path: &P) ->
+    fn unix_bind(&mut self, path: &CString) ->
         Result<~RtioUnixListenerObject, IoError> {
         let mut pipe = Pipe::new(self.uv_loop(), false);
-        match pipe.bind(&path.path_as_str(|s| s.to_c_str())) {
+        match pipe.bind(path) {
             Ok(()) => {
                 let handle = get_handle_to_current_scheduler!();
                 let pipe = UvUnboundPipe::new(pipe, handle);
@@ -823,9 +827,7 @@ impl IoFactory for UvIoFactory {
         }
     }
 
-    fn unix_connect<P: PathLike>(&mut self, path: &P) ->
-        Result<~RtioPipe, IoError>
-    {
+    fn unix_connect(&mut self, path: &CString) -> Result<~RtioPipe, IoError> {
         let scheduler: ~Scheduler = Local::take();
         let mut pipe = Pipe::new(self.uv_loop(), false);
         let result_cell = Cell::new_empty();
@@ -833,8 +835,7 @@ impl IoFactory for UvIoFactory {
 
         do scheduler.deschedule_running_task_and_then |_, task| {
             let task_cell = Cell::new(task);
-            let cstr = do path.path_as_str |s| { s.to_c_str() };
-            do pipe.connect(&cstr) |stream, err| {
+            do pipe.connect(path) |stream, err| {
                 let res = match err {
                     None => {
                         let handle = stream.native_handle();
@@ -1841,13 +1842,22 @@ impl RtioTTY for UvTTY {
     }
 }
 
+// this function is full of lies
+unsafe fn local_io() -> &'static mut IoFactory {
+    do Local::borrow |sched: &mut Scheduler| {
+        let mut io = None;
+        sched.event_loop.io(|i| io = Some(i));
+        cast::transmute(io.unwrap())
+    }
+}
+
 #[test]
 fn test_simple_io_no_connect() {
     do run_in_mt_newsched_task {
         unsafe {
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
+            let io = local_io();
             let addr = next_test_ip4();
-            let maybe_chan = (*io).tcp_connect(addr);
+            let maybe_chan = io.tcp_connect(addr);
             assert!(maybe_chan.is_err());
         }
     }
@@ -1857,9 +1867,9 @@ fn test_simple_io_no_connect() {
 fn test_simple_udp_io_bind_only() {
     do run_in_mt_newsched_task {
         unsafe {
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
+            let io = local_io();
             let addr = next_test_ip4();
-            let maybe_socket = (*io).udp_bind(addr);
+            let maybe_socket = io.udp_bind(addr);
             assert!(maybe_socket.is_ok());
         }
     }
@@ -1878,9 +1888,11 @@ fn test_simple_homed_udp_io_bind_then_move_task_then_home_and_close() {
         let work_queue2 = WorkQueue::new();
         let queues = ~[work_queue1.clone(), work_queue2.clone()];
 
-        let mut sched1 = ~Scheduler::new(~UvEventLoop::new(), work_queue1, queues.clone(),
+        let loop1 = ~UvEventLoop::new() as ~EventLoop;
+        let mut sched1 = ~Scheduler::new(loop1, work_queue1, queues.clone(),
                                          sleepers.clone());
-        let mut sched2 = ~Scheduler::new(~UvEventLoop::new(), work_queue2, queues.clone(),
+        let loop2 = ~UvEventLoop::new() as ~EventLoop;
+        let mut sched2 = ~Scheduler::new(loop2, work_queue2, queues.clone(),
                                          sleepers.clone());
 
         let handle1 = Cell::new(sched1.make_handle());
@@ -1894,11 +1906,9 @@ fn test_simple_homed_udp_io_bind_then_move_task_then_home_and_close() {
         };
 
         let test_function: ~fn() = || {
-            let io: *mut IoFactoryObject = unsafe {
-                Local::unsafe_borrow()
-            };
+            let io = unsafe { local_io() };
             let addr = next_test_ip4();
-            let maybe_socket = unsafe { (*io).udp_bind(addr) };
+            let maybe_socket = io.udp_bind(addr);
             // this socket is bound to this event loop
             assert!(maybe_socket.is_ok());
 
@@ -1957,9 +1967,11 @@ fn test_simple_homed_udp_io_bind_then_move_handle_then_home_and_close() {
         let work_queue2 = WorkQueue::new();
         let queues = ~[work_queue1.clone(), work_queue2.clone()];
 
-        let mut sched1 = ~Scheduler::new(~UvEventLoop::new(), work_queue1, queues.clone(),
+        let loop1 = ~UvEventLoop::new() as ~EventLoop;
+        let mut sched1 = ~Scheduler::new(loop1, work_queue1, queues.clone(),
                                          sleepers.clone());
-        let mut sched2 = ~Scheduler::new(~UvEventLoop::new(), work_queue2, queues.clone(),
+        let loop2 = ~UvEventLoop::new() as ~EventLoop;
+        let mut sched2 = ~Scheduler::new(loop2, work_queue2, queues.clone(),
                                          sleepers.clone());
 
         let handle1 = Cell::new(sched1.make_handle());
@@ -1970,11 +1982,9 @@ fn test_simple_homed_udp_io_bind_then_move_handle_then_home_and_close() {
         let chan = Cell::new(chan);
 
         let body1: ~fn() = || {
-            let io: *mut IoFactoryObject = unsafe {
-                Local::unsafe_borrow()
-            };
+            let io = unsafe { local_io() };
             let addr = next_test_ip4();
-            let socket = unsafe { (*io).udp_bind(addr) };
+            let socket = io.udp_bind(addr);
             assert!(socket.is_ok());
             chan.take().send(socket);
         };
@@ -2028,8 +2038,8 @@ fn test_simple_tcp_server_and_client() {
         // Start the server first so it's listening when we connect
         do spawntask {
             unsafe {
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let listener = (*io).tcp_bind(addr).unwrap();
+                let io = local_io();
+                let listener = io.tcp_bind(addr).unwrap();
                 let mut acceptor = listener.listen().unwrap();
                 chan.take().send(());
                 let mut stream = acceptor.accept().unwrap();
@@ -2046,8 +2056,8 @@ fn test_simple_tcp_server_and_client() {
         do spawntask {
             unsafe {
                 port.take().recv();
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let mut stream = (*io).tcp_connect(addr).unwrap();
+                let io = local_io();
+                let mut stream = io.tcp_connect(addr).unwrap();
                 stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
             }
         }
@@ -2071,9 +2081,11 @@ fn test_simple_tcp_server_and_client_on_diff_threads() {
         let client_work_queue = WorkQueue::new();
         let queues = ~[server_work_queue.clone(), client_work_queue.clone()];
 
-        let mut server_sched = ~Scheduler::new(~UvEventLoop::new(), server_work_queue,
+        let sloop = ~UvEventLoop::new() as ~EventLoop;
+        let mut server_sched = ~Scheduler::new(sloop, server_work_queue,
                                                queues.clone(), sleepers.clone());
-        let mut client_sched = ~Scheduler::new(~UvEventLoop::new(), client_work_queue,
+        let cloop = ~UvEventLoop::new() as ~EventLoop;
+        let mut client_sched = ~Scheduler::new(cloop, client_work_queue,
                                                queues.clone(), sleepers.clone());
 
         let server_handle = Cell::new(server_sched.make_handle());
@@ -2090,8 +2102,8 @@ fn test_simple_tcp_server_and_client_on_diff_threads() {
         };
 
         let server_fn: ~fn() = || {
-            let io: *mut IoFactoryObject = unsafe { Local::unsafe_borrow() };
-            let listener = unsafe { (*io).tcp_bind(server_addr).unwrap() };
+            let io = unsafe { local_io() };
+            let listener = io.tcp_bind(server_addr).unwrap();
             let mut acceptor = listener.listen().unwrap();
             let mut stream = acceptor.accept().unwrap();
             let mut buf = [0, .. 2048];
@@ -2103,12 +2115,10 @@ fn test_simple_tcp_server_and_client_on_diff_threads() {
         };
 
         let client_fn: ~fn() = || {
-            let io: *mut IoFactoryObject = unsafe {
-                Local::unsafe_borrow()
-            };
-            let mut stream = unsafe { (*io).tcp_connect(client_addr) };
+            let io = unsafe { local_io() };
+            let mut stream = io.tcp_connect(client_addr);
             while stream.is_err() {
-                stream = unsafe { (*io).tcp_connect(client_addr) };
+                stream = io.tcp_connect(client_addr);
             }
             stream.unwrap().write([0, 1, 2, 3, 4, 5, 6, 7]);
         };
@@ -2147,8 +2157,8 @@ fn test_simple_udp_server_and_client() {
 
         do spawntask {
             unsafe {
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let mut server_socket = (*io).udp_bind(server_addr).unwrap();
+                let io = local_io();
+                let mut server_socket = io.udp_bind(server_addr).unwrap();
                 chan.take().send(());
                 let mut buf = [0, .. 2048];
                 let (nread,src) = server_socket.recvfrom(buf).unwrap();
@@ -2163,8 +2173,8 @@ fn test_simple_udp_server_and_client() {
 
         do spawntask {
             unsafe {
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let mut client_socket = (*io).udp_bind(client_addr).unwrap();
+                let io = local_io();
+                let mut client_socket = io.udp_bind(client_addr).unwrap();
                 port.take().recv();
                 client_socket.sendto([0, 1, 2, 3, 4, 5, 6, 7], server_addr);
             }
@@ -2181,8 +2191,8 @@ fn test_read_and_block() {
         let chan = Cell::new(chan);
 
         do spawntask {
-            let io: *mut IoFactoryObject = unsafe { Local::unsafe_borrow() };
-            let listener = unsafe { (*io).tcp_bind(addr).unwrap() };
+            let io = unsafe { local_io() };
+            let listener = io.tcp_bind(addr).unwrap();
             let mut acceptor = listener.listen().unwrap();
             chan.take().send(());
             let mut stream = acceptor.accept().unwrap();
@@ -2220,8 +2230,8 @@ fn test_read_and_block() {
         do spawntask {
             unsafe {
                 port.take().recv();
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let mut stream = (*io).tcp_connect(addr).unwrap();
+                let io = local_io();
+                let mut stream = io.tcp_connect(addr).unwrap();
                 stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
                 stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
                 stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
@@ -2243,8 +2253,8 @@ fn test_read_read_read() {
 
         do spawntask {
             unsafe {
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let listener = (*io).tcp_bind(addr).unwrap();
+                let io = local_io();
+                let listener = io.tcp_bind(addr).unwrap();
                 let mut acceptor = listener.listen().unwrap();
                 chan.take().send(());
                 let mut stream = acceptor.accept().unwrap();
@@ -2260,8 +2270,8 @@ fn test_read_read_read() {
         do spawntask {
             unsafe {
                 port.take().recv();
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let mut stream = (*io).tcp_connect(addr).unwrap();
+                let io = local_io();
+                let mut stream = io.tcp_connect(addr).unwrap();
                 let mut buf = [0, .. 2048];
                 let mut total_bytes_read = 0;
                 while total_bytes_read < MAX {
@@ -2289,8 +2299,8 @@ fn test_udp_twice() {
 
         do spawntask {
             unsafe {
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let mut client = (*io).udp_bind(client_addr).unwrap();
+                let io = local_io();
+                let mut client = io.udp_bind(client_addr).unwrap();
                 port.take().recv();
                 assert!(client.sendto([1], server_addr).is_ok());
                 assert!(client.sendto([2], server_addr).is_ok());
@@ -2299,8 +2309,8 @@ fn test_udp_twice() {
 
         do spawntask {
             unsafe {
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let mut server = (*io).udp_bind(server_addr).unwrap();
+                let io = local_io();
+                let mut server = io.udp_bind(server_addr).unwrap();
                 chan.take().send(());
                 let mut buf1 = [0];
                 let mut buf2 = [0];
@@ -2334,9 +2344,9 @@ fn test_udp_many_read() {
 
         do spawntask {
             unsafe {
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let mut server_out = (*io).udp_bind(server_out_addr).unwrap();
-                let mut server_in = (*io).udp_bind(server_in_addr).unwrap();
+                let io = local_io();
+                let mut server_out = io.udp_bind(server_out_addr).unwrap();
+                let mut server_in = io.udp_bind(server_in_addr).unwrap();
                 let (port, chan) = first.take();
                 chan.send(());
                 port.recv();
@@ -2360,9 +2370,9 @@ fn test_udp_many_read() {
 
         do spawntask {
             unsafe {
-                let io: *mut IoFactoryObject = Local::unsafe_borrow();
-                let mut client_out = (*io).udp_bind(client_out_addr).unwrap();
-                let mut client_in = (*io).udp_bind(client_in_addr).unwrap();
+                let io = local_io();
+                let mut client_out = io.udp_bind(client_out_addr).unwrap();
+                let mut client_in = io.udp_bind(client_in_addr).unwrap();
                 let (port, chan) = second.take();
                 port.recv();
                 chan.send(());
@@ -2392,8 +2402,8 @@ fn test_udp_many_read() {
 fn test_timer_sleep_simple() {
     do run_in_mt_newsched_task {
         unsafe {
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
-            let timer = (*io).timer_init();
+            let io = local_io();
+            let timer = io.timer_init();
             do timer.map_move |mut t| { t.sleep(1) };
         }
     }
@@ -2403,29 +2413,28 @@ fn file_test_uvio_full_simple_impl() {
     use str::StrSlice; // why does this have to be explicitly imported to work?
                        // compiler was complaining about no trait for str that
                        // does .as_bytes() ..
-    use path::Path;
     use rt::io::{Open, Create, ReadWrite, Read};
     unsafe {
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
+        let io = local_io();
         let write_val = "hello uvio!";
         let path = "./tmp/file_test_uvio_full.txt";
         {
             let create_fm = Create;
             let create_fa = ReadWrite;
-            let mut fd = (*io).fs_open(&path.to_c_str(), create_fm, create_fa).unwrap();
+            let mut fd = io.fs_open(&path.to_c_str(), create_fm, create_fa).unwrap();
             let write_buf = write_val.as_bytes();
             fd.write(write_buf);
         }
         {
             let ro_fm = Open;
             let ro_fa = Read;
-            let mut fd = (*io).fs_open(&path.to_c_str(), ro_fm, ro_fa).unwrap();
+            let mut fd = io.fs_open(&path.to_c_str(), ro_fm, ro_fa).unwrap();
             let mut read_vec = [0, .. 1028];
             let nread = fd.read(read_vec).unwrap();
             let read_val = str::from_utf8(read_vec.slice(0, nread as uint));
             assert!(read_val == write_val.to_owned());
         }
-        (*io).fs_unlink(&path.to_c_str());
+        io.fs_unlink(&path.to_c_str());
     }
 }
 
@@ -2440,9 +2449,9 @@ fn uvio_naive_print(input: &str) {
     use str::StrSlice;
     unsafe {
         use libc::{STDOUT_FILENO};
-        let io: *mut IoFactoryObject = Local::unsafe_borrow();
+        let io = local_io();
         {
-            let mut fd = (*io).fs_from_raw_fd(STDOUT_FILENO, false);
+            let mut fd = io.fs_from_raw_fd(STDOUT_FILENO, false);
             let write_buf = input.as_bytes();
             fd.write(write_buf);
         }
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index 3c89c12dbfa..053076c5d89 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -1018,7 +1018,6 @@ static TAG_CONT_U8: u8 = 128u8;
 
 /// Unsafe operations
 pub mod raw {
-    use option::{Option, Some};
     use cast;
     use libc;
     use ptr;