about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/back/link.rs129
-rw-r--r--src/rustc/back/rpath.rs255
-rw-r--r--src/rustc/driver/driver.rs65
-rw-r--r--src/rustc/driver/rustc.rs8
-rw-r--r--src/rustc/driver/session.rs6
-rw-r--r--src/rustc/metadata/creader.rs4
-rw-r--r--src/rustc/metadata/cstore.rs10
-rw-r--r--src/rustc/metadata/filesearch.rs83
-rw-r--r--src/rustc/metadata/loader.rs32
-rw-r--r--src/rustc/middle/trans/base.rs2
-rw-r--r--src/rustc/middle/trans/debuginfo.rs13
-rw-r--r--src/rustc/util/ppaux.rs3
12 files changed, 284 insertions, 326 deletions
diff --git a/src/rustc/back/link.rs b/src/rustc/back/link.rs
index 33fce8bc72c..7c227e012a9 100644
--- a/src/rustc/back/link.rs
+++ b/src/rustc/back/link.rs
@@ -57,18 +57,7 @@ mod write {
         return false;
     }
 
-    // Decides what to call an intermediate file, given the name of the output
-    // and the extension to use.
-    fn mk_intermediate_name(output_path: ~str, extension: ~str) ->
-        ~str unsafe {
-        let stem = match str::find_char(output_path, '.') {
-          some(dot_pos) => str::slice(output_path, 0u, dot_pos),
-          none => output_path
-        };
-        return stem + ~"." + extension;
-    }
-
-    fn run_passes(sess: session, llmod: ModuleRef, output: ~str) {
+    fn run_passes(sess: session, llmod: ModuleRef, output: &Path) {
         let opts = sess.opts;
         if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
         let mut pm = mk_pass_manager();
@@ -85,15 +74,15 @@ mod write {
             match opts.output_type {
               output_type_bitcode => {
                 if opts.optimize != session::No {
-                    let filename = mk_intermediate_name(output, ~"no-opt.bc");
-                    str::as_c_str(filename, |buf| {
+                    let filename = output.with_filetype("no-opt.bc");
+                    str::as_c_str(filename.to_str(), |buf| {
                         llvm::LLVMWriteBitcodeToFile(llmod, buf)
                     });
                 }
               }
               _ => {
-                let filename = mk_intermediate_name(output, ~"bc");
-                str::as_c_str(filename, |buf| {
+                let filename = output.with_filetype("bc");
+                str::as_c_str(filename.to_str(), |buf| {
                     llvm::LLVMWriteBitcodeToFile(llmod, buf)
                 });
               }
@@ -163,9 +152,9 @@ mod write {
             if opts.save_temps {
                 // Always output the bitcode file with --save-temps
 
-                let filename = mk_intermediate_name(output, ~"opt.bc");
+                let filename = output.with_filetype("opt.bc");
                 llvm::LLVMRunPassManager(pm.llpm, llmod);
-                str::as_c_str(filename, |buf| {
+                str::as_c_str(filename.to_str(), |buf| {
                     llvm::LLVMWriteBitcodeToFile(llmod, buf)
                 });
                 pm = mk_pass_manager();
@@ -175,7 +164,7 @@ mod write {
                     let _: () = str::as_c_str(
                         sess.targ_cfg.target_strs.target_triple,
                         |buf_t| {
-                            str::as_c_str(output, |buf_o| {
+                            str::as_c_str(output.to_str(), |buf_o| {
                                 WriteOutputFile(
                                     sess,
                                     pm.llpm,
@@ -197,7 +186,7 @@ mod write {
                     let _: () = str::as_c_str(
                         sess.targ_cfg.target_strs.target_triple,
                         |buf_t| {
-                            str::as_c_str(output, |buf_o| {
+                            str::as_c_str(output.to_str(), |buf_o| {
                                 WriteOutputFile(
                                     sess,
                                     pm.llpm,
@@ -217,7 +206,7 @@ mod write {
                 let _: () = str::as_c_str(
                     sess.targ_cfg.target_strs.target_triple,
                     |buf_t| {
-                        str::as_c_str(output, |buf_o| {
+                        str::as_c_str(output.to_str(), |buf_o| {
                             WriteOutputFile(
                                 sess,
                                 pm.llpm,
@@ -239,13 +228,13 @@ mod write {
 
         if opts.output_type == output_type_llvm_assembly {
             // Given options "-S --emit-llvm": output LLVM assembly
-            str::as_c_str(output, |buf_o| {
+            str::as_c_str(output.to_str(), |buf_o| {
                 llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)});
         } else {
             // If only a bitcode file is asked for by using the '--emit-llvm'
             // flag, then output it here
             llvm::LLVMRunPassManager(pm.llpm, llmod);
-            str::as_c_str(output,
+            str::as_c_str(output.to_str(),
                         |buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) );
         }
 
@@ -306,7 +295,7 @@ mod write {
  *
  */
 
-fn build_link_meta(sess: session, c: ast::crate, output: ~str,
+fn build_link_meta(sess: session, c: ast::crate, output: &Path,
                    symbol_hasher: &hash::State) -> link_meta {
 
     type provided_metas =
@@ -384,21 +373,16 @@ fn build_link_meta(sess: session, c: ast::crate, output: ~str,
     }
 
     fn crate_meta_name(sess: session, _crate: ast::crate,
-                       output: ~str, metas: provided_metas) -> ~str {
+                       output: &Path, metas: provided_metas) -> ~str {
         return match metas.name {
               some(v) => v,
               none => {
-                let name =
-                    {
-                        let mut os =
-                            str::split_char(path::basename(output), '.');
-                        if (vec::len(os) < 2u) {
-                            sess.fatal(fmt!("output file name `%s` doesn't\
-                              appear to have an extension", output));
-                        }
-                        vec::pop(os);
-                        str::connect(os, ~".")
-                    };
+                let name = match output.filestem() {
+                  none => sess.fatal(fmt!("output file name `%s` doesn't\
+                                           appear to have a stem",
+                                          output.to_str())),
+                  some(s) => s
+                };
                 warn_missing(sess, ~"name", name);
                 name
               }
@@ -552,31 +536,17 @@ fn mangle_internal_name_by_seq(ccx: @crate_ctxt, flav: ~str) -> ~str {
 // If the user wants an exe generated we need to invoke
 // cc to link the object file with some libs
 fn link_binary(sess: session,
-               obj_filename: ~str,
-               out_filename: ~str,
+               obj_filename: &Path,
+               out_filename: &Path,
                lm: link_meta) {
-    // Converts a library file name into a cc -l argument
-    fn unlib(config: @session::config, filename: ~str) -> ~str unsafe {
-        let rmlib = fn@(filename: ~str) -> ~str {
-            let found = str::find_str(filename, ~"lib");
-            if config.os == session::os_macos ||
-                (config.os == session::os_linux ||
-                 config.os == session::os_freebsd) &&
-                option::is_some(found) && option::get(found) == 0u {
-                return str::slice(filename, 3u, str::len(filename));
-            } else { return filename; }
-        };
-        fn rmext(filename: ~str) -> ~str {
-            let mut parts = str::split_char(filename, '.');
-            vec::pop(parts);
-            return str::connect(parts, ~".");
+    // Converts a library file-stem into a cc -l argument
+    fn unlib(config: @session::config, stem: ~str) -> ~str {
+        if stem.starts_with("lib") &&
+            config.os != session::os_win32 {
+            stem.slice(3, stem.len())
+        } else {
+            stem
         }
-        return match config.os {
-              session::os_macos => rmext(rmlib(filename)),
-              session::os_linux => rmext(rmlib(filename)),
-              session::os_freebsd => rmext(rmlib(filename)),
-              _ => rmext(filename)
-            };
     }
 
     let output = if sess.building_library {
@@ -585,17 +555,19 @@ fn link_binary(sess: session,
                                   lm.name, lm.extras_hash, lm.vers));
         debug!("link_meta.name:  %s", lm.name);
         debug!("long_libname: %s", long_libname);
-        debug!("out_filename: %s", out_filename);
-        debug!("dirname(out_filename): %s", path::dirname(out_filename));
+        debug!("out_filename: %s", out_filename.to_str());
+        debug!("dirname(out_filename): %s", out_filename.dir_path().to_str());
 
-        path::connect(path::dirname(out_filename), long_libname)
-    } else { out_filename };
+        out_filename.dir_path().push(long_libname)
+    } else {
+        *out_filename
+    };
 
-    log(debug, ~"output: " + output);
+    log(debug, ~"output: " + output.to_str());
 
     // The default library location, we need this to find the runtime.
     // The location of crates will be determined as needed.
-    let stage: ~str = ~"-L" + sess.filesearch.get_target_lib_path();
+    let stage: ~str = ~"-L" + sess.filesearch.get_target_lib_path().to_str();
 
     // In the future, FreeBSD will use clang as default compiler.
     // It would be flexible to use cc (system's default C compiler)
@@ -609,27 +581,28 @@ fn link_binary(sess: session,
     let mut cc_args =
         vec::append(~[stage], sess.targ_cfg.target_strs.cc_args);
     vec::push(cc_args, ~"-o");
-    vec::push(cc_args, output);
-    vec::push(cc_args, obj_filename);
+    vec::push(cc_args, output.to_str());
+    vec::push(cc_args, obj_filename.to_str());
 
     let mut lib_cmd;
     let os = sess.targ_cfg.os;
     if os == session::os_macos {
         lib_cmd = ~"-dynamiclib";
-    } else { lib_cmd = ~"-shared"; }
+    } else {
+        lib_cmd = ~"-shared";
+    }
 
     // # Crate linking
 
     let cstore = sess.cstore;
     for cstore::get_used_crate_files(cstore).each |cratepath| {
-        if str::ends_with(cratepath, ~".rlib") {
-            vec::push(cc_args, cratepath);
+        if cratepath.filetype() == some(~"rlib") {
+            vec::push(cc_args, cratepath.to_str());
             again;
         }
-        let cratepath = cratepath;
-        let dir = path::dirname(cratepath);
+        let dir = cratepath.dirname();
         if dir != ~"" { vec::push(cc_args, ~"-L" + dir); }
-        let libarg = unlib(sess.targ_cfg, path::basename(cratepath));
+        let libarg = unlib(sess.targ_cfg, option::get(cratepath.filestem()));
         vec::push(cc_args, ~"-l" + libarg);
     }
 
@@ -645,7 +618,7 @@ fn link_binary(sess: session,
     // forces to make sure that library can be found at runtime.
 
     let addl_paths = sess.opts.addl_lib_search_paths;
-    for addl_paths.each |path| { vec::push(cc_args, ~"-L" + path); }
+    for addl_paths.each |path| { vec::push(cc_args, ~"-L" + path.to_str()); }
 
     // The names of the extern libraries
     let used_libs = cstore::get_used_libraries(cstore);
@@ -658,7 +631,7 @@ fn link_binary(sess: session,
         // be rpathed
         if sess.targ_cfg.os == session::os_macos {
             vec::push(cc_args, ~"-Wl,-install_name,@rpath/"
-                      + path::basename(output));
+                      + option::get(output.filename()));
         }
     }
 
@@ -701,7 +674,7 @@ fn link_binary(sess: session,
 
     // FIXME (#2397): At some point we want to rpath our guesses as to where
     // extern libraries might live, based on the addl_lib_search_paths
-    vec::push_all(cc_args, rpath::get_rpath_flags(sess, output));
+    vec::push_all(cc_args, rpath::get_rpath_flags(sess, &output));
 
     debug!("%s link args: %s", cc_prog, str::connect(cc_args, ~" "));
     // We run 'cc' here
@@ -717,14 +690,14 @@ fn link_binary(sess: session,
 
     // Clean up on Darwin
     if sess.targ_cfg.os == session::os_macos {
-        run::run_program(~"dsymutil", ~[output]);
+        run::run_program(~"dsymutil", ~[output.to_str()]);
     }
 
     // Remove the temporary object file if we aren't saving temps
     if !sess.opts.save_temps {
         if ! os::remove_file(obj_filename) {
             sess.warn(fmt!("failed to delete object file `%s`",
-                           obj_filename));
+                           obj_filename.to_str()));
         }
     }
 }
diff --git a/src/rustc/back/rpath.rs b/src/rustc/back/rpath.rs
index b6f6d17e444..0d02821a24c 100644
--- a/src/rustc/back/rpath.rs
+++ b/src/rustc/back/rpath.rs
@@ -13,7 +13,7 @@ pure fn not_win32(os: session::os) -> bool {
   }
 }
 
-fn get_rpath_flags(sess: session::session, out_filename: ~str) -> ~[~str] {
+fn get_rpath_flags(sess: session::session, out_filename: &Path) -> ~[~str] {
     let os = sess.targ_cfg.os;
 
     // No rpath on windows
@@ -23,7 +23,6 @@ fn get_rpath_flags(sess: session::session, out_filename: ~str) -> ~[~str] {
 
     debug!("preparing the RPATH!");
 
-    let cwd = os::getcwd();
     let sysroot = sess.filesearch.sysroot();
     let output = out_filename;
     let libs = cstore::get_used_crate_files(sess.cstore);
@@ -32,50 +31,48 @@ fn get_rpath_flags(sess: session::session, out_filename: ~str) -> ~[~str] {
     let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess));
 
     let target_triple = sess.opts.target_triple;
-    let rpaths = get_rpaths(os, cwd, sysroot, output, libs, target_triple);
+    let rpaths = get_rpaths(os, &sysroot, output, libs, target_triple);
     rpaths_to_flags(rpaths)
 }
 
-fn get_sysroot_absolute_rt_lib(sess: session::session) -> path::Path {
-    let mut path = vec::append(~[sess.filesearch.sysroot()],
-                           filesearch::relative_target_lib_path(
-                               sess.opts.target_triple));
-    vec::push(path, os::dll_filename(~"rustrt"));
-    path::connect_many(path)
+fn get_sysroot_absolute_rt_lib(sess: session::session) -> Path {
+    let r = filesearch::relative_target_lib_path(sess.opts.target_triple);
+    sess.filesearch.sysroot().push_rel(&r).push(os::dll_filename("rustrt"))
 }
 
-fn rpaths_to_flags(rpaths: ~[~str]) -> ~[~str] {
-    vec::map(rpaths, |rpath| fmt!("-Wl,-rpath,%s",rpath) )
+fn rpaths_to_flags(rpaths: &[Path]) -> ~[~str] {
+    vec::map(rpaths, |rpath| fmt!("-Wl,-rpath,%s",rpath.to_str()))
 }
 
-fn get_rpaths(os: session::os, cwd: path::Path, sysroot: path::Path,
-              output: path::Path, libs: ~[path::Path],
-              target_triple: ~str) -> ~[~str] {
-    debug!("cwd: %s", cwd);
-    debug!("sysroot: %s", sysroot);
-    debug!("output: %s", output);
+fn get_rpaths(os: session::os,
+              sysroot: &Path,
+              output: &Path,
+              libs: &[Path],
+              target_triple: &str) -> ~[Path] {
+    debug!("sysroot: %s", sysroot.to_str());
+    debug!("output: %s", output.to_str());
     debug!("libs:");
     for libs.each |libpath| {
-        debug!("    %s", libpath);
+        debug!("    %s", libpath.to_str());
     }
     debug!("target_triple: %s", target_triple);
 
     // Use relative paths to the libraries. Binaries can be moved
     // as long as they maintain the relative relationship to the
     // crates they depend on.
-    let rel_rpaths = get_rpaths_relative_to_output(os, cwd, output, libs);
+    let rel_rpaths = get_rpaths_relative_to_output(os, output, libs);
 
     // Make backup absolute paths to the libraries. Binaries can
     // be moved as long as the crates they link against don't move.
-    let abs_rpaths = get_absolute_rpaths(cwd, libs);
+    let abs_rpaths = get_absolute_rpaths(libs);
 
     // And a final backup rpath to the global library location.
-    let fallback_rpaths = ~[get_install_prefix_rpath(cwd, target_triple)];
+    let fallback_rpaths = ~[get_install_prefix_rpath(target_triple)];
 
-    fn log_rpaths(desc: ~str, rpaths: ~[~str]) {
+    fn log_rpaths(desc: &str, rpaths: &[Path]) {
         debug!("%s rpaths:", desc);
         for rpaths.each |rpath| {
-            debug!("    %s", rpath);
+            debug!("    %s", rpath.to_str());
         }
     }
 
@@ -93,43 +90,37 @@ fn get_rpaths(os: session::os, cwd: path::Path, sysroot: path::Path,
 }
 
 fn get_rpaths_relative_to_output(os: session::os,
-                                 cwd: path::Path,
-                                 output: path::Path,
-                                 libs: ~[path::Path]) -> ~[~str] {
+                                 output: &Path,
+                                 libs: &[Path]) -> ~[Path] {
     vec::map(libs, |a| {
-        get_rpath_relative_to_output(os, cwd, output, a)
+        get_rpath_relative_to_output(os, output, &a)
     })
 }
 
 fn get_rpath_relative_to_output(os: session::os,
-                                cwd: path::Path,
-                                output: path::Path,
-                                &&lib: path::Path) -> ~str {
+                                output: &Path,
+                                lib: &Path) -> Path {
     assert not_win32(os);
 
     // Mac doesn't appear to support $ORIGIN
     let prefix = match os {
-        session::os_linux => ~"$ORIGIN" + path::path_sep(),
-        session::os_freebsd => ~"$ORIGIN" + path::path_sep(),
-        session::os_macos => ~"@executable_path" + path::path_sep(),
+        session::os_linux | session::os_freebsd => "$ORIGIN",
+        session::os_macos => "@executable_path",
         session::os_win32 => core::unreachable()
     };
 
-    prefix + get_relative_to(
-        get_absolute(cwd, output),
-        get_absolute(cwd, lib))
+    Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output),
+                                           &os::make_absolute(lib)))
 }
 
 // Find the relative path from one file to another
-fn get_relative_to(abs1: path::Path, abs2: path::Path) -> path::Path {
-    assert path::path_is_absolute(abs1);
-    assert path::path_is_absolute(abs2);
+fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
+    assert abs1.is_absolute;
+    assert abs2.is_absolute;
     debug!("finding relative path from %s to %s",
-           abs1, abs2);
-    let normal1 = path::normalize(abs1);
-    let normal2 = path::normalize(abs2);
-    let split1 = path::split(normal1);
-    let split2 = path::split(normal2);
+           abs1.to_str(), abs2.to_str());
+    let split1 = abs1.components;
+    let split2 = abs2.components;
     let len1 = vec::len(split1);
     let len2 = vec::len(split2);
     assert len1 > 0u;
@@ -148,48 +139,39 @@ fn get_relative_to(abs1: path::Path, abs2: path::Path) -> path::Path {
     vec::push_all(path, vec::view(split2, start_idx, len2 - 1u));
 
     if vec::is_not_empty(path) {
-        return path::connect_many(path);
+        return Path("").push_many(path);
     } else {
-        return ~".";
+        return Path(".");
     }
 }
 
-fn get_absolute_rpaths(cwd: path::Path, libs: ~[path::Path]) -> ~[~str] {
-    vec::map(libs, |a| get_absolute_rpath(cwd, a) )
+fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] {
+    vec::map(libs, |a| get_absolute_rpath(&a) )
 }
 
-fn get_absolute_rpath(cwd: path::Path, &&lib: path::Path) -> ~str {
-    path::dirname(get_absolute(cwd, lib))
+fn get_absolute_rpath(lib: &Path) -> Path {
+    os::make_absolute(lib).dir_path()
 }
 
-fn get_absolute(cwd: path::Path, lib: path::Path) -> path::Path {
-    if path::path_is_absolute(lib) {
-        lib
-    } else {
-        path::connect(cwd, lib)
-    }
-}
-
-fn get_install_prefix_rpath(cwd: path::Path, target_triple: ~str) -> ~str {
+fn get_install_prefix_rpath(target_triple: &str) -> Path {
     let install_prefix = env!("CFG_PREFIX");
 
     if install_prefix == ~"" {
         fail ~"rustc compiled without CFG_PREFIX environment variable";
     }
 
-    let path = vec::append(
-        ~[install_prefix],
-        filesearch::relative_target_lib_path(target_triple));
-    get_absolute(cwd, path::connect_many(path))
+    let tlib = filesearch::relative_target_lib_path(target_triple);
+    os::make_absolute(&Path(install_prefix).push_rel(&tlib))
 }
 
-fn minimize_rpaths(rpaths: ~[~str]) -> ~[~str] {
+fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
     let set = map::str_hash::<()>();
     let mut minimized = ~[];
     for rpaths.each |rpath| {
-        if !set.contains_key(rpath) {
+        let s = rpath.to_str();
+        if !set.contains_key(s) {
             vec::push(minimized, rpath);
-            set.insert(rpath, ());
+            set.insert(s, ());
         }
     }
     return minimized;
@@ -199,116 +181,112 @@ fn minimize_rpaths(rpaths: ~[~str]) -> ~[~str] {
 mod test {
     #[test]
     fn test_rpaths_to_flags() {
-        let flags = rpaths_to_flags(~[~"path1", ~"path2"]);
+        let flags = rpaths_to_flags(~[Path("path1"),
+                                      Path("path2")]);
         assert flags == ~[~"-Wl,-rpath,path1", ~"-Wl,-rpath,path2"];
     }
 
     #[test]
-    fn test_get_absolute1() {
-        let cwd = ~"/dir";
-        let lib = ~"some/path/lib";
-        let res = get_absolute(cwd, lib);
-        assert res == ~"/dir/some/path/lib";
-    }
-
-    #[test]
-    fn test_get_absolute2() {
-        let cwd = ~"/dir";
-        let lib = ~"/some/path/lib";
-        let res = get_absolute(cwd, lib);
-        assert res == ~"/some/path/lib";
-    }
-
-    #[test]
     fn test_prefix_rpath() {
-        let res = get_install_prefix_rpath(~"/usr/lib", ~"triple");
-        let d = path::connect(env!("CFG_PREFIX"), ~"/lib/rustc/triple/lib");
-        assert str::ends_with(res, d);
+        let res = get_install_prefix_rpath("triple");
+        let d = Path(env!("CFG_PREFIX"))
+            .push_rel(&Path("lib/rustc/triple/lib"));
+        debug!("test_prefix_path: %s vs. %s",
+               res.to_str(),
+               d.to_str());
+        assert str::ends_with(res.to_str(), d.to_str());
     }
 
     #[test]
     fn test_prefix_rpath_abs() {
-        let res = get_install_prefix_rpath(~"/usr/lib", ~"triple");
-        assert path::path_is_absolute(res);
+        let res = get_install_prefix_rpath("triple");
+        assert res.is_absolute;
     }
 
     #[test]
     fn test_minimize1() {
-        let res = minimize_rpaths(~[~"rpath1", ~"rpath2", ~"rpath1"]);
-        assert res == ~[~"rpath1", ~"rpath2"];
+        let res = minimize_rpaths([Path("rpath1"),
+                                   Path("rpath2"),
+                                   Path("rpath1")]);
+        assert res == ~[Path("rpath1"), Path("rpath2")];
     }
 
     #[test]
     fn test_minimize2() {
-        let res = minimize_rpaths(~[~"1a", ~"2", ~"2", ~"1a", ~"4a",
-                                   ~"1a", ~"2", ~"3", ~"4a", ~"3"]);
-        assert res == ~[~"1a", ~"2", ~"4a", ~"3"];
+        let res = minimize_rpaths(~[Path("1a"), Path("2"), Path("2"),
+                                    Path("1a"), Path("4a"),Path("1a"),
+                                    Path("2"), Path("3"), Path("4a"),
+                                    Path("3")]);
+        assert res == ~[Path("1a"), Path("2"), Path("4a"), Path("3")];
     }
 
     #[test]
     fn test_relative_to1() {
-        let p1 = ~"/usr/bin/rustc";
-        let p2 = ~"/usr/lib/mylib";
-        let res = get_relative_to(p1, p2);
-        assert res == ~"../lib";
+        let p1 = Path("/usr/bin/rustc");
+        let p2 = Path("/usr/lib/mylib");
+        let res = get_relative_to(&p1, &p2);
+        assert res == Path("../lib");
     }
 
     #[test]
     fn test_relative_to2() {
-        let p1 = ~"/usr/bin/rustc";
-        let p2 = ~"/usr/bin/../lib/mylib";
-        let res = get_relative_to(p1, p2);
-        assert res == ~"../lib";
+        let p1 = Path("/usr/bin/rustc");
+        let p2 = Path("/usr/bin/../lib/mylib");
+        let res = get_relative_to(&p1, &p2);
+        assert res == Path("../lib");
     }
 
     #[test]
     fn test_relative_to3() {
-        let p1 = ~"/usr/bin/whatever/rustc";
-        let p2 = ~"/usr/lib/whatever/mylib";
-        let res = get_relative_to(p1, p2);
-        assert res == ~"../../lib/whatever";
+        let p1 = Path("/usr/bin/whatever/rustc");
+        let p2 = Path("/usr/lib/whatever/mylib");
+        let res = get_relative_to(&p1, &p2);
+        assert res == Path("../../lib/whatever");
     }
 
     #[test]
     fn test_relative_to4() {
-        let p1 = ~"/usr/bin/whatever/../rustc";
-        let p2 = ~"/usr/lib/whatever/mylib";
-        let res = get_relative_to(p1, p2);
-        assert res == ~"../lib/whatever";
+        let p1 = Path("/usr/bin/whatever/../rustc");
+        let p2 = Path("/usr/lib/whatever/mylib");
+        let res = get_relative_to(&p1, &p2);
+        assert res == Path("../lib/whatever");
     }
 
     #[test]
     fn test_relative_to5() {
-        let p1 = ~"/usr/bin/whatever/../rustc";
-        let p2 = ~"/usr/lib/whatever/../mylib";
-        let res = get_relative_to(p1, p2);
-        assert res == ~"../lib";
+        let p1 = Path("/usr/bin/whatever/../rustc");
+        let p2 = Path("/usr/lib/whatever/../mylib");
+        let res = get_relative_to(&p1, &p2);
+        assert res == Path("../lib");
     }
 
     #[test]
     fn test_relative_to6() {
-        let p1 = ~"/1";
-        let p2 = ~"/2/3";
-        let res = get_relative_to(p1, p2);
-        assert res == ~"2";
+        let p1 = Path("/1");
+        let p2 = Path("/2/3");
+        let res = get_relative_to(&p1, &p2);
+        assert res == Path("2");
     }
 
     #[test]
     fn test_relative_to7() {
-        let p1 = ~"/1/2";
-        let p2 = ~"/3";
-        let res = get_relative_to(p1, p2);
-        assert res == ~"..";
+        let p1 = Path("/1/2");
+        let p2 = Path("/3");
+        let res = get_relative_to(&p1, &p2);
+        assert res == Path("..");
     }
 
     #[test]
     fn test_relative_to8() {
-        let p1 = ~"/home/brian/Dev/rust/build/"
-            + ~"stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so";
-        let p2 = ~"/home/brian/Dev/rust/build/stage2/bin/.."
-            + ~"/lib/rustc/i686-unknown-linux-gnu/lib/libstd.so";
-        let res = get_relative_to(p1, p2);
-        assert res == ~".";
+        let p1 = Path("/home/brian/Dev/rust/build/").push_rel(
+            &Path("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
+        let p2 = Path("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
+            &Path("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
+        let res = get_relative_to(&p1, &p2);
+        debug!("test_relative_tu8: %s vs. %s",
+               res.to_str(),
+               Path(".").to_str());
+        assert res == Path(".");
     }
 
     #[test]
@@ -316,8 +294,8 @@ mod test {
     fn test_rpath_relative() {
       let o = session::os_linux;
       let res = get_rpath_relative_to_output(o,
-            ~"/usr", ~"bin/rustc", ~"lib/libstd.so");
-      assert res == ~"$ORIGIN/../lib";
+            &Path("bin/rustc"), &Path("lib/libstd.so"));
+      assert res == Path("$ORIGIN/../lib");
     }
 
     #[test]
@@ -325,8 +303,8 @@ mod test {
     fn test_rpath_relative() {
         let o = session::os_freebsd;
         let res = get_rpath_relative_to_output(o,
-            ~"/usr", ~"bin/rustc", ~"lib/libstd.so");
-        assert res == ~"$ORIGIN/../lib";
+            &Path("bin/rustc"), &Path("lib/libstd.so"));
+        assert res == Path("$ORIGIN/../lib");
     }
 
     #[test]
@@ -334,14 +312,19 @@ mod test {
     fn test_rpath_relative() {
         // this is why refinements would be nice
         let o = session::os_macos;
-        let res = get_rpath_relative_to_output(o, ~"/usr", ~"bin/rustc",
-                                               ~"lib/libstd.so");
-        assert res == ~"@executable_path/../lib";
+        let res = get_rpath_relative_to_output(o,
+                                               &Path("bin/rustc"),
+                                               &Path("lib/libstd.so"));
+        assert res == Path("@executable_path/../lib");
     }
 
     #[test]
     fn test_get_absolute_rpath() {
-        let res = get_absolute_rpath(~"/usr", ~"lib/libstd.so");
-        assert res == ~"/usr/lib";
+        let res = get_absolute_rpath(&Path("lib/libstd.so"));
+        debug!("test_get_absolute_rpath: %s vs. %s",
+               res.to_str(),
+               os::make_absolute(&Path("lib")).to_str());
+
+        assert res == os::make_absolute(&Path("lib"));
     }
 }
diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs
index 087c6c3b833..c1a371af4dd 100644
--- a/src/rustc/driver/driver.rs
+++ b/src/rustc/driver/driver.rs
@@ -27,7 +27,7 @@ fn anon_src() -> ~str { ~"<anon>" }
 
 fn source_name(input: input) -> ~str {
     match input {
-      file_input(ifile) => ifile,
+      file_input(ifile) => ifile.to_str(),
       str_input(_) => anon_src()
     }
 }
@@ -92,7 +92,7 @@ fn parse_cfgspecs(cfgspecs: ~[~str]) -> ast::crate_cfg {
 
 enum input {
     /// Load source from file
-    file_input(~str),
+    file_input(Path),
     /// The string is the source
     str_input(~str)
 }
@@ -101,7 +101,7 @@ fn parse_input(sess: session, cfg: ast::crate_cfg, input: input)
     -> @ast::crate {
     match input {
       file_input(file) => {
-        parse::parse_crate_from_file(file, cfg, sess.parse_sess)
+        parse::parse_crate_from_file(&file, cfg, sess.parse_sess)
       }
       str_input(src) => {
         // FIXME (#2319): Don't really want to box the source string
@@ -236,11 +236,13 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
                 vtable_map: vtable_map};
 
     let (llmod, link_meta) = time(time_passes, ~"translation", ||
-        trans::base::trans_crate(sess, crate, ty_cx, outputs.obj_filename,
+        trans::base::trans_crate(sess, crate, ty_cx,
+                                 &outputs.obj_filename,
                                  exp_map, exp_map2, maps));
 
     time(time_passes, ~"LLVM passes", ||
-        link::write::run_passes(sess, llmod, outputs.obj_filename));
+        link::write::run_passes(sess, llmod,
+                                &outputs.obj_filename));
 
     let stop_after_codegen =
         sess.opts.output_type != link::output_type_exe ||
@@ -249,14 +251,15 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
     if stop_after_codegen { return {crate: crate, tcx: some(ty_cx)}; }
 
     time(time_passes, ~"linking", ||
-         link::link_binary(sess, outputs.obj_filename,
-                           outputs.out_filename, link_meta));
+         link::link_binary(sess,
+                           &outputs.obj_filename,
+                           &outputs.out_filename, link_meta));
 
     return {crate: crate, tcx: some(ty_cx)};
 }
 
 fn compile_input(sess: session, cfg: ast::crate_cfg, input: input,
-                 outdir: option<~str>, output: option<~str>) {
+                 outdir: &option<Path>, output: &option<Path>) {
 
     let upto = if sess.opts.parse_only { cu_parse }
                else if sess.opts.no_trans { cu_no_trans }
@@ -483,6 +486,7 @@ fn build_session_options(matches: getopts::matches,
     let extra_debuginfo = opt_present(matches, ~"xg");
     let debuginfo = opt_present(matches, ~"g") || extra_debuginfo;
     let sysroot_opt = getopts::opt_maybe_str(matches, ~"sysroot");
+    let sysroot_opt = option::map(sysroot_opt, |m| Path(m));
     let target_opt = getopts::opt_maybe_str(matches, ~"target");
     let save_temps = getopts::opt_present(matches, ~"save-temps");
     match output_type {
@@ -514,7 +518,9 @@ fn build_session_options(matches: getopts::matches,
             some(s) => s
         };
 
-    let addl_lib_search_paths = getopts::opt_strs(matches, ~"L");
+    let addl_lib_search_paths =
+        getopts::opt_strs(matches, ~"L")
+        .map(|s| Path(s));
     let cfg = parse_cfgspecs(getopts::opt_strs(matches, ~"cfg"));
     let test = opt_present(matches, ~"test");
     let sopts: @session::options =
@@ -614,11 +620,11 @@ fn opts() -> ~[getopts::opt] {
           optflag(~"static"), optflag(~"gc")];
 }
 
-type output_filenames = @{out_filename: ~str, obj_filename:~str};
+type output_filenames = @{out_filename:Path, obj_filename:Path};
 
 fn build_output_filenames(input: input,
-                          odir: option<~str>,
-                          ofile: option<~str>,
+                          odir: &option<Path>,
+                          ofile: &option<Path>,
                           sess: session)
         -> output_filenames {
     let obj_path;
@@ -639,37 +645,30 @@ fn build_output_filenames(input: input,
           link::output_type_object | link::output_type_exe => ~"o"
         };
 
-    match ofile {
+    match *ofile {
       none => {
         // "-" as input file will cause the parser to read from stdin so we
         // have to make up a name
         // We want to toss everything after the final '.'
-        let dirname = match odir {
+        let dirpath = match *odir {
           some(d) => d,
           none => match input {
             str_input(_) => os::getcwd(),
-            file_input(ifile) => path::dirname(ifile)
+            file_input(ifile) => ifile.dir_path()
           }
         };
 
-        let base_filename = match input {
-          file_input(ifile) => {
-            let (path, _) = path::splitext(ifile);
-            path::basename(path)
-          }
+        let stem = match input {
+          file_input(ifile) => option::get(ifile.filestem()),
           str_input(_) => ~"rust_out"
         };
-        let base_path = path::connect(dirname, base_filename);
-
 
         if sess.building_library {
-            let basename = path::basename(base_path);
-            let dylibname = os::dll_filename(basename);
-            out_path = path::connect(dirname, dylibname);
-            obj_path = path::connect(dirname, basename + ~"." + obj_suffix);
+            out_path = dirpath.push(os::dll_filename(stem));
+            obj_path = dirpath.push(stem).with_filetype(obj_suffix);
         } else {
-            out_path = base_path;
-            obj_path = base_path + ~"." + obj_suffix;
+            out_path = dirpath.push(stem);
+            obj_path = dirpath.push(stem).with_filetype(obj_suffix);
         }
       }
 
@@ -678,9 +677,7 @@ fn build_output_filenames(input: input,
         obj_path = if stop_after_codegen {
             out_file
         } else {
-            let (base, _) = path::splitext(out_file);
-            let modified = base + ~"." + obj_suffix;
-            modified
+            out_file.with_filetype(obj_suffix)
         };
 
         if sess.building_library {
@@ -690,13 +687,13 @@ fn build_output_filenames(input: input,
             // lib<basename>-<hash>-<version>.so no matter what.
         }
 
-        if odir != none {
+        if *odir != none {
             sess.warn(~"ignoring --out-dir flag due to -o flag.");
         }
       }
     }
     return @{out_filename: out_path,
-          obj_filename: obj_path};
+             obj_filename: obj_path};
 }
 
 fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! {
@@ -704,7 +701,7 @@ fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! {
     fail;
 }
 
-fn list_metadata(sess: session, path: ~str, out: io::Writer) {
+fn list_metadata(sess: session, path: &Path, out: io::Writer) {
     metadata::loader::list_file_metadata(
         sess.parse_sess.interner,
         session::sess_os_to_meta_os(sess.targ_cfg.os), path, out);
diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs
index 0770a132a1d..e26465fce5d 100644
--- a/src/rustc/driver/rustc.rs
+++ b/src/rustc/driver/rustc.rs
@@ -159,7 +159,7 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
             let src = str::from_bytes(io::stdin().read_whole_stream());
             str_input(src)
         } else {
-            file_input(ifile)
+            file_input(Path(ifile))
         }
       }
       _ => early_error(demitter, ~"multiple input filenames provided")
@@ -168,7 +168,9 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
     let sopts = build_session_options(matches, demitter);
     let sess = build_session(sopts, demitter);
     let odir = getopts::opt_maybe_str(matches, ~"out-dir");
+    let odir = option::map(odir, |o| Path(o));
     let ofile = getopts::opt_maybe_str(matches, ~"o");
+    let ofile = option::map(ofile, |o| Path(o));
     let cfg = build_configuration(sess, binary, input);
     let pretty =
         option::map(getopts::opt_default(matches, ~"pretty",
@@ -185,7 +187,7 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
     if ls {
         match input {
           file_input(ifile) => {
-            list_metadata(sess, ifile, io::stdout());
+            list_metadata(sess, &ifile, io::stdout());
           }
           str_input(_) => {
             early_error(demitter, ~"can not list metadata for stdin");
@@ -194,7 +196,7 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
         return;
     }
 
-    compile_input(sess, cfg, input, odir, ofile);
+    compile_input(sess, cfg, input, &odir, &ofile);
 }
 
 /*
diff --git a/src/rustc/driver/session.rs b/src/rustc/driver/session.rs
index cd663c06ce7..10c0f283525 100644
--- a/src/rustc/driver/session.rs
+++ b/src/rustc/driver/session.rs
@@ -89,8 +89,8 @@ type options =
      lint_opts: ~[(lint::lint, lint::level)],
      save_temps: bool,
      output_type: back::link::output_type,
-     addl_lib_search_paths: ~[~str],
-     maybe_sysroot: option<~str>,
+     addl_lib_search_paths: ~[Path],
+     maybe_sysroot: option<Path>,
      target_triple: ~str,
      cfg: ast::crate_cfg,
      test: bool,
@@ -111,7 +111,7 @@ type session_ = {targ_cfg: @config,
                  span_diagnostic: diagnostic::span_handler,
                  filesearch: filesearch::filesearch,
                  mut building_library: bool,
-                 working_dir: ~str,
+                 working_dir: Path,
                  lint_settings: lint::lint_settings};
 
 enum session {
diff --git a/src/rustc/metadata/creader.rs b/src/rustc/metadata/creader.rs
index 5867dc12672..685717e8e8d 100644
--- a/src/rustc/metadata/creader.rs
+++ b/src/rustc/metadata/creader.rs
@@ -199,7 +199,7 @@ fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item],
         };
         let cinfo = loader::load_library_crate(load_ctxt);
 
-        let cfilename = cinfo.ident;
+        let cfilename = Path(cinfo.ident);
         let cdata = cinfo.data;
 
         let attrs = decoder::get_crate_attributes(cdata);
@@ -225,7 +225,7 @@ fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item],
 
         let cstore = e.cstore;
         cstore::set_crate_data(cstore, cnum, cmeta);
-        cstore::add_used_crate_file(cstore, cfilename);
+        cstore::add_used_crate_file(cstore, &cfilename);
         return cnum;
       }
       some(cnum) => {
diff --git a/src/rustc/metadata/cstore.rs b/src/rustc/metadata/cstore.rs
index 4b65953781a..d2cab8c3177 100644
--- a/src/rustc/metadata/cstore.rs
+++ b/src/rustc/metadata/cstore.rs
@@ -56,7 +56,7 @@ type cstore_private =
     @{metas: map::hashmap<ast::crate_num, crate_metadata>,
       use_crate_map: use_crate_map,
       mod_path_map: mod_path_map,
-      mut used_crate_files: ~[~str],
+      mut used_crate_files: ~[Path],
       mut used_libraries: ~[~str],
       mut used_link_args: ~[~str],
       intr: ident_interner};
@@ -114,13 +114,13 @@ fn iter_crate_data(cstore: cstore, i: fn(ast::crate_num, crate_metadata)) {
     for p(cstore).metas.each |k,v| { i(k, v);};
 }
 
-fn add_used_crate_file(cstore: cstore, lib: ~str) {
-    if !vec::contains(p(cstore).used_crate_files, lib) {
-        vec::push(p(cstore).used_crate_files, lib);
+fn add_used_crate_file(cstore: cstore, lib: &Path) {
+    if !vec::contains(p(cstore).used_crate_files, copy *lib) {
+        vec::push(p(cstore).used_crate_files, copy *lib);
     }
 }
 
-fn get_used_crate_files(cstore: cstore) -> ~[~str] {
+fn get_used_crate_files(cstore: cstore) -> ~[Path] {
     return p(cstore).used_crate_files;
 }
 
diff --git a/src/rustc/metadata/filesearch.rs b/src/rustc/metadata/filesearch.rs
index 72661891163..de0c31b9c3d 100644
--- a/src/rustc/metadata/filesearch.rs
+++ b/src/rustc/metadata/filesearch.rs
@@ -14,12 +14,10 @@ export get_cargo_root;
 export get_cargo_root_nearest;
 export libdir;
 
-import path::Path;
+type pick<T> = fn(path: &Path) -> option<T>;
 
-type pick<T> = fn(path: Path) -> option<T>;
-
-fn pick_file(file: Path, path: Path) -> option<Path> {
-    if path::basename(path) == file { option::some(path) }
+fn pick_file(file: Path, path: &Path) -> option<Path> {
+    if path.file_path() == file { option::some(copy *path) }
     else { option::none }
 }
 
@@ -27,11 +25,11 @@ trait filesearch {
     fn sysroot() -> Path;
     fn lib_search_paths() -> ~[Path];
     fn get_target_lib_path() -> Path;
-    fn get_target_lib_file_path(file: Path) -> Path;
+    fn get_target_lib_file_path(file: &Path) -> Path;
 }
 
 fn mk_filesearch(maybe_sysroot: option<Path>,
-                 target_triple: ~str,
+                 target_triple: &str,
                  addl_lib_search_paths: ~[Path]) -> filesearch {
     type filesearch_impl = {sysroot: Path,
                             addl_lib_search_paths: ~[Path],
@@ -42,7 +40,8 @@ fn mk_filesearch(maybe_sysroot: option<Path>,
             let mut paths = self.addl_lib_search_paths;
 
             vec::push(paths,
-                      make_target_lib_path(self.sysroot, self.target_triple));
+                      make_target_lib_path(&self.sysroot,
+                                           self.target_triple));
             match get_cargo_lib_path_nearest() {
               result::ok(p) => vec::push(paths, p),
               result::err(p) => ()
@@ -54,33 +53,33 @@ fn mk_filesearch(maybe_sysroot: option<Path>,
             paths
         }
         fn get_target_lib_path() -> Path {
-            make_target_lib_path(self.sysroot, self.target_triple)
+            make_target_lib_path(&self.sysroot, self.target_triple)
         }
-        fn get_target_lib_file_path(file: Path) -> Path {
-            path::connect(self.get_target_lib_path(), file)
+        fn get_target_lib_file_path(file: &Path) -> Path {
+            self.get_target_lib_path().push_rel(file)
         }
     }
 
     let sysroot = get_sysroot(maybe_sysroot);
-    debug!("using sysroot = %s", sysroot);
+    debug!("using sysroot = %s", sysroot.to_str());
     {sysroot: sysroot,
      addl_lib_search_paths: addl_lib_search_paths,
-     target_triple: target_triple} as filesearch
+     target_triple: str::from_slice(target_triple)} as filesearch
 }
 
 fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
     let mut rslt = none;
     for filesearch.lib_search_paths().each |lib_search_path| {
-        debug!("searching %s", lib_search_path);
-        for os::list_dir_path(lib_search_path).each |path| {
-            debug!("testing %s", path);
+        debug!("searching %s", lib_search_path.to_str());
+        for os::list_dir_path(&lib_search_path).each |path| {
+            debug!("testing %s", path.to_str());
             let maybe_picked = pick(path);
             if option::is_some(maybe_picked) {
-                debug!("picked %s", path);
+                debug!("picked %s", path.to_str());
                 rslt = maybe_picked;
                 break;
             } else {
-                debug!("rejected %s", path);
+                debug!("rejected %s", path.to_str());
             }
         }
         if option::is_some(rslt) { break; }
@@ -88,21 +87,20 @@ fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
     return rslt;
 }
 
-fn relative_target_lib_path(target_triple: ~str) -> ~[Path] {
-    ~[libdir(), ~"rustc", target_triple, libdir()]
+fn relative_target_lib_path(target_triple: &str) -> Path {
+    Path(libdir()).push_many([~"rustc",
+                              str::from_slice(target_triple),
+                              libdir()])
 }
 
-fn make_target_lib_path(sysroot: Path,
-                        target_triple: ~str) -> Path {
-    let path = vec::append(~[sysroot],
-                           relative_target_lib_path(target_triple));
-    let path = path::connect_many(path);
-    return path;
+fn make_target_lib_path(sysroot: &Path,
+                        target_triple: &str) -> Path {
+    sysroot.push_rel(&relative_target_lib_path(target_triple))
 }
 
 fn get_default_sysroot() -> Path {
     match os::self_exe_path() {
-      option::some(p) => path::normalize(path::connect(p, ~"..")),
+      option::some(p) => p.pop(),
       option::none => fail ~"can't determine value for sysroot"
     }
 }
@@ -115,15 +113,14 @@ fn get_sysroot(maybe_sysroot: option<Path>) -> Path {
 }
 
 fn get_cargo_sysroot() -> result<Path, ~str> {
-    let path = ~[get_default_sysroot(), libdir(), ~"cargo"];
-    result::ok(path::connect_many(path))
+    result::ok(get_default_sysroot().push_many([libdir(), ~"cargo"]))
 }
 
 fn get_cargo_root() -> result<Path, ~str> {
     match os::getenv(~"CARGO_ROOT") {
-        some(_p) => result::ok(_p),
+        some(_p) => result::ok(Path(_p)),
         none => match os::homedir() {
-          some(_q) => result::ok(path::connect(_q, ~".cargo")),
+          some(_q) => result::ok(_q.push(".cargo")),
           none => result::err(~"no CARGO_ROOT or home directory")
         }
     }
@@ -132,21 +129,21 @@ fn get_cargo_root() -> result<Path, ~str> {
 fn get_cargo_root_nearest() -> result<Path, ~str> {
     do result::chain(get_cargo_root()) |p| {
         let cwd = os::getcwd();
-        let mut dirname = path::dirname(cwd);
-        let mut dirpath = path::split(dirname);
-        let cwd_cargo = path::connect(cwd, ~".cargo");
-        let mut par_cargo = path::connect(dirname, ~".cargo");
+        let cwd_cargo = cwd.push(".cargo");
+        let mut par_cargo = cwd.pop().push(".cargo");
         let mut rslt = result::ok(cwd_cargo);
 
-        if !os::path_is_dir(cwd_cargo) && cwd_cargo != p {
-            while vec::is_not_empty(dirpath) && par_cargo != p {
-                if os::path_is_dir(par_cargo) {
+        if !os::path_is_dir(&cwd_cargo) && cwd_cargo != p {
+            while par_cargo != p {
+                if os::path_is_dir(&par_cargo) {
                     rslt = result::ok(par_cargo);
                     break;
                 }
-                vec::pop(dirpath);
-                dirname = path::dirname(dirname);
-                par_cargo = path::connect(dirname, ~".cargo");
+                if par_cargo.components.len() == 1 {
+                    // We just checked /.cargo, stop now.
+                    break;
+                }
+                par_cargo = par_cargo.pop().pop().push(".cargo");
             }
         }
         rslt
@@ -155,13 +152,13 @@ fn get_cargo_root_nearest() -> result<Path, ~str> {
 
 fn get_cargo_lib_path() -> result<Path, ~str> {
     do result::chain(get_cargo_root()) |p| {
-        result::ok(path::connect(p, libdir()))
+        result::ok(p.push(libdir()))
     }
 }
 
 fn get_cargo_lib_path_nearest() -> result<Path, ~str> {
     do result::chain(get_cargo_root_nearest()) |p| {
-        result::ok(path::connect(p, libdir()))
+        result::ok(p.push(libdir()))
     }
 }
 
diff --git a/src/rustc/metadata/loader.rs b/src/rustc/metadata/loader.rs
index f010b7e9754..513b4dd4216 100644
--- a/src/rustc/metadata/loader.rs
+++ b/src/rustc/metadata/loader.rs
@@ -74,27 +74,28 @@ fn find_library_crate_aux(cx: ctxt,
 
     let mut matches = ~[];
     filesearch::search(filesearch, |path| {
-        debug!("inspecting file %s", path);
-        let f: ~str = path::basename(path);
+        debug!("inspecting file %s", path.to_str());
+        let f: ~str = option::get(path.filename());
         if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
-            debug!("skipping %s, doesn't look like %s*%s", path, prefix,
-                   suffix);
+            debug!("skipping %s, doesn't look like %s*%s", path.to_str(),
+                   prefix, suffix);
             option::none::<()>
         } else {
-            debug!("%s is a candidate", path);
+            debug!("%s is a candidate", path.to_str());
             match get_metadata_section(cx.os, path) {
               option::some(cvec) => {
                 if !crate_matches(cvec, cx.metas, cx.hash) {
-                    debug!("skipping %s, metadata doesn't match", path);
+                    debug!("skipping %s, metadata doesn't match",
+                           path.to_str());
                     option::none::<()>
                 } else {
-                    debug!("found %s with matching metadata", path);
-                    vec::push(matches, {ident: path, data: cvec});
+                    debug!("found %s with matching metadata", path.to_str());
+                    vec::push(matches, {ident: path.to_str(), data: cvec});
                     option::none::<()>
                 }
               }
               _ => {
-                debug!("could not load metadata for %s", path);
+                debug!("could not load metadata for %s", path.to_str());
                 option::none::<()>
               }
             }
@@ -168,10 +169,10 @@ fn metadata_matches(extern_metas: ~[@ast::meta_item],
 }
 
 fn get_metadata_section(os: os,
-                        filename: ~str) -> option<@~[u8]> unsafe {
-    let mb = str::as_c_str(filename, |buf| {
+                        filename: &Path) -> option<@~[u8]> unsafe {
+    let mb = str::as_c_str(filename.to_str(), |buf| {
         llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
-                                   });
+    });
     if mb as int == 0 { return option::none::<@~[u8]>; }
     let of = match mk_object_file(mb) {
         option::some(of) => of,
@@ -204,12 +205,13 @@ fn meta_section_name(os: os) -> ~str {
 }
 
 // A diagnostic function for dumping crate metadata to an output stream
-fn list_file_metadata(intr: ident_interner, os: os, path: ~str,
-                      out: io::Writer) {
+fn list_file_metadata(intr: ident_interner,
+                      os: os, path: &Path, out: io::Writer) {
     match get_metadata_section(os, path) {
       option::some(bytes) => decoder::list_crate_metadata(intr, bytes, out),
       option::none => {
-        out.write_str(~"could not find metadata in " + path + ~".\n");
+        out.write_str(~"could not find metadata in "
+                      + path.to_str() + ~".\n");
       }
     }
 }
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index dddcdd64da3..fe0d49a3532 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -5778,7 +5778,7 @@ fn write_abi_version(ccx: @crate_ctxt) {
 fn trans_crate(sess: session::session,
                crate: @ast::crate,
                tcx: ty::ctxt,
-               output: ~str,
+               output: &Path,
                emap: resolve3::ExportMap,
                emap2: resolve3::ExportMap2,
                maps: astencode::maps)
diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs
index 04e0f7be75f..42b8274d78c 100644
--- a/src/rustc/middle/trans/debuginfo.rs
+++ b/src/rustc/middle/trans/debuginfo.rs
@@ -172,7 +172,7 @@ fn create_compile_unit(cx: @crate_ctxt)
       option::none => ()
     }
 
-    let (_, work_dir) = get_file_path_and_dir(cx.sess.working_dir,
+    let (_, work_dir) = get_file_path_and_dir(cx.sess.working_dir.to_str(),
                                               crate_name);
     let unit_metadata = ~[lltag(tg),
                          llunused(),
@@ -197,13 +197,13 @@ fn get_cache(cx: @crate_ctxt) -> metadata_cache {
     option::get(cx.dbg_cx).llmetadata
 }
 
-fn get_file_path_and_dir(work_dir: ~str, full_path: ~str) -> (~str, ~str) {
+fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) {
     (if str::starts_with(full_path, work_dir) {
         str::slice(full_path, str::len(work_dir) + 1u,
                    str::len(full_path))
     } else {
-        full_path
-    }, work_dir)
+        str::from_slice(full_path)
+    }, str::from_slice(work_dir))
 }
 
 fn create_file(cx: @crate_ctxt, full_path: ~str) -> @metadata<file_md> {
@@ -215,8 +215,9 @@ fn create_file(cx: @crate_ctxt, full_path: ~str) -> @metadata<file_md> {
         option::none => ()
     }
 
-    let (file_path, work_dir) = get_file_path_and_dir(cx.sess.working_dir,
-                                                      full_path);
+    let (file_path, work_dir) =
+        get_file_path_and_dir(cx.sess.working_dir.to_str(),
+                              full_path);
     let unit_node = create_compile_unit(cx).node;
     let file_md = ~[lltag(tg),
                    llstr(file_path),
diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs
index 1634d38577e..9d952517052 100644
--- a/src/rustc/util/ppaux.rs
+++ b/src/rustc/util/ppaux.rs
@@ -210,6 +210,9 @@ fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str {
       ty::vstore_fixed(_) => {
         fmt!("%s/%s", ty, vstore_to_str(cx, vs))
       }
+      ty::vstore_slice(_) => {
+        fmt!("%s/%s", vstore_to_str(cx, vs), ty)
+      }
       _ => fmt!("%s%s", vstore_to_str(cx, vs), ty)
     }
 }