]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #8905 : sstewartgallus/rust/cleanup_tests, r=bblum
authorbors <bors@rust-lang.org>
Sat, 31 Aug 2013 19:40:40 +0000 (12:40 -0700)
committerbors <bors@rust-lang.org>
Sat, 31 Aug 2013 19:40:40 +0000 (12:40 -0700)
In this commit I:
- removed unneeded heap allocations
- added extra whitespace to crowded expressions
- and removed unneeded syntax

Also, CC @bblum although this change is fairly unobjectionable.

116 files changed:
.gitmodules
doc/rust.md
mk/llvm.mk
mk/platform.mk
mk/rt.mk
mk/tests.mk
src/compiletest/common.rs
src/compiletest/compiletest.rs
src/compiletest/procsrv.rs
src/compiletest/runtest.rs
src/etc/emacs/rust-mode.el
src/libextra/dlist.rs
src/libextra/json.rs
src/libextra/semver.rs
src/libextra/test.rs
src/librustc/back/link.rs
src/librustc/driver/driver.rs
src/librustc/driver/session.rs
src/librustc/lib/llvm.rs
src/librustc/middle/kind.rs
src/librustc/middle/resolve.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/rscope.rs
src/librustdoc/markdown_writer.rs
src/librustpkg/api.rs
src/librustpkg/conditions.rs
src/librustpkg/context.rs
src/librustpkg/package_id.rs
src/librustpkg/package_source.rs
src/librustpkg/path_util.rs
src/librustpkg/rustpkg.rs
src/librustpkg/source_control.rs
src/librustpkg/tests.rs
src/librustpkg/util.rs
src/librustpkg/version.rs
src/librustpkg/workspace.rs
src/libstd/bool.rs
src/libstd/char.rs
src/libstd/cmp.rs
src/libstd/fmt/parse.rs
src/libstd/io.rs
src/libstd/iter.rs [deleted file]
src/libstd/logging.rs
src/libstd/num/f32.rs
src/libstd/num/f64.rs
src/libstd/num/float.rs
src/libstd/num/int_macros.rs
src/libstd/num/num.rs
src/libstd/num/uint.rs
src/libstd/num/uint_macros.rs
src/libstd/os.rs
src/libstd/prelude.rs
src/libstd/ptr.rs
src/libstd/reflect.rs
src/libstd/reflect_stage0.rs [new file with mode: 0644]
src/libstd/repr.rs
src/libstd/repr_stage0.rs [new file with mode: 0644]
src/libstd/rt/args.rs
src/libstd/rt/comm.rs
src/libstd/rt/io/file.rs
src/libstd/rt/io/mod.rs
src/libstd/rt/io/net/tcp.rs
src/libstd/rt/io/pipe.rs [deleted file]
src/libstd/rt/io/support.rs
src/libstd/rt/local_ptr.rs
src/libstd/rt/mod.rs
src/libstd/rt/rtio.rs
src/libstd/rt/sched.rs
src/libstd/rt/util.rs
src/libstd/rt/uv/async.rs
src/libstd/rt/uv/file.rs
src/libstd/rt/uv/idle.rs
src/libstd/rt/uv/mod.rs
src/libstd/rt/uv/net.rs
src/libstd/rt/uv/pipe.rs [deleted file]
src/libstd/rt/uv/process.rs [deleted file]
src/libstd/rt/uv/timer.rs
src/libstd/rt/uv/uvio.rs
src/libstd/rt/uv/uvll.rs
src/libstd/run.rs
src/libstd/select.rs
src/libstd/std.rs
src/libstd/str.rs
src/libstd/sys.rs
src/libstd/unstable/dynamic_lib.rs
src/libstd/unstable/intrinsics.rs
src/libstd/unstable/sync.rs
src/libsyntax/parse/mod.rs
src/libuv
src/llvm
src/rt/rust_uv.cpp
src/rt/rustrt.def.in
src/rustllvm/PassWrapper.cpp
src/rustllvm/RustWrapper.cpp
src/test/auxiliary/nested_item.rs [new file with mode: 0644]
src/test/bench/shootout-pfib.rs
src/test/compile-fail/lint-unused-import-tricky-globs.rs [new file with mode: 0644]
src/test/run-fail/test-tasks-invalid-value.rs [new file with mode: 0644]
src/test/run-pass/const-cross-crate-extern.rs
src/test/run-pass/const-extern-function.rs
src/test/run-pass/core-run-destroy.rs
src/test/run-pass/extern-compare-with-return-type.rs
src/test/run-pass/extern-take-value.rs
src/test/run-pass/issue-5917.rs
src/test/run-pass/monad.rs
src/test/run-pass/nested_item_main.rs [new file with mode: 0644]
src/test/run-pass/reflect-visit-data.rs
src/test/run-pass/reflect-visit-type.rs
src/test/run-pass/rename-directory.rs [new file with mode: 0644]
src/test/run-pass/static-impl.rs
src/test/run-pass/trait-generic.rs

index fa979b6d868ef4bebdcc7a79891e4f61e27ce328..88ead6e608d5c4ee00212451f47c281d09d00846 100644 (file)
@@ -4,5 +4,5 @@
        branch = master
 [submodule "src/libuv"]
        path = src/libuv
-       url = https://github.com/alexcrichton/libuv.git
+       url = https://github.com/brson/libuv.git
        branch = master
index 08c04c6c8887e9c046c0b9991073385eecbe187c..b33006733ab37ab5d760ed35c9d56b0752fd525d 100644 (file)
@@ -209,7 +209,7 @@ break
 do
 else enum extern
 false fn for
-if impl
+if impl in
 let loop
 match mod mut
 priv pub
index 896718be6c451b9cfa67248c1168bcee2809ab5b..12ccc55d4fae135020c85a0529f26f7046cefd54 100644 (file)
@@ -26,7 +26,7 @@ ifeq ($(CFG_LLVM_ROOT),)
 
 $$(LLVM_CONFIG_$(1)): $$(LLVM_DEPS)
        @$$(call E, make: llvm)
-       $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1))
+       $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) $$(CFG_LLVM_BUILD_ENV)
        $$(Q)touch $$(LLVM_CONFIG_$(1))
 endif
 
index 3e7ad914daba19fab8c1c62a9c3e16a031a4af08..6ee5420664d8e1c819efa0bfe8a000519b6a6a0d 100644 (file)
@@ -26,7 +26,10 @@ endef
 $(foreach t,$(CFG_TARGET_TRIPLES),$(eval $(call DEF_OSTYPE_VAR,$(t))))
 $(foreach t,$(CFG_TARGET_TRIPLES),$(info cfg: os for $(t) is $(OSTYPE_$(t))))
 
-CFG_GCCISH_CFLAGS += -DUSE_UTF8
+# FIXME: no-omit-frame-pointer is just so that task_start_wrapper
+# has a frame pointer and the stack walker can understand it. Turning off
+# frame pointers everywhere is overkill
+CFG_GCCISH_CFLAGS += -fno-omit-frame-pointer -DUSE_UTF8
 
 # On Darwin, we need to run dsymutil so the debugging information ends
 # up in the right place.  On other platforms, it automatically gets
@@ -150,6 +153,7 @@ CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-no-whole-archive
 CFG_DEF_SUFFIX_x86_64-unknown-linux-gnu := .linux.def
 CFG_INSTALL_NAME_x86_64-unknown-linux-gnu =
 CFG_LIBUV_LINK_FLAGS_x86_64-unknown-linux-gnu =
+CFG_LLVM_BUILD_ENV_x86_64-unknown-linux-gnu="CXXFLAGS=-fno-omit-frame-pointer"
 CFG_EXE_SUFFIX_x86_64-unknown-linux-gnu =
 CFG_WINDOWSY_x86_64-unknown-linux-gnu :=
 CFG_UNIXY_x86_64-unknown-linux-gnu := 1
@@ -175,6 +179,7 @@ CFG_GCCISH_POST_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-no-whole-archive
 CFG_DEF_SUFFIX_i686-unknown-linux-gnu := .linux.def
 CFG_INSTALL_NAME_i686-unknown-linux-gnu =
 CFG_LIBUV_LINK_FLAGS_i686-unknown-linux-gnu =
+CFG_LLVM_BUILD_ENV_i686-unknown-linux-gnu="CXXFLAGS=-fno-omit-frame-pointer"
 CFG_EXE_SUFFIX_i686-unknown-linux-gnu =
 CFG_WINDOWSY_i686-unknown-linux-gnu :=
 CFG_UNIXY_i686-unknown-linux-gnu := 1
index 366acb7e379181ce48eaa6123142c99251169f06..c260945cbc9b035bb11c4e76967c2c4097e2d1ad 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -168,49 +168,36 @@ LIBUV_DEPS := $$(wildcard \
               $$(S)src/libuv/*/*/*/*)
 endif
 
-LIBUV_GYP := $$(S)src/libuv/build/gyp
-LIBUV_MAKEFILE_$(1)_$(2) := $$(CFG_BUILD_DIR)rt/$(1)/stage$(2)/libuv/Makefile
-LIBUV_NO_LOAD = run-benchmarks.target.mk run-tests.target.mk \
-               uv_dtrace_header.target.mk uv_dtrace_provider.target.mk
-
-$$(LIBUV_MAKEFILE_$(1)_$(2)): $$(LIBUV_GYP)
-       (cd $(S)src/libuv/ && \
-        $$(CFG_PYTHON) ./gyp_uv -f make -Dtarget_arch=$$(LIBUV_ARCH_$(1)) -D ninja \
-          -Goutput_dir=$$(@D) --generator-output $$(@D))
-
 # XXX: Shouldn't need platform-specific conditions here
 ifdef CFG_WINDOWSY_$(1)
 $$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS)
-       $$(Q)rm -f $$(S)src/libuv/libuv.a
-       $$(Q)$$(MAKE) -C $$(S)src/libuv -f Makefile.mingw \
-               CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
-               AR="$$(AR_$(1))" \
+       $$(Q)$$(MAKE) -C $$(S)src/libuv/ \
+               builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/stage$(2)/libuv" \
+               OS=mingw \
                V=$$(VERBOSE)
-       $$(Q)cp $$(S)src/libuv/libuv.a $$@
 else ifeq ($(OSTYPE_$(1)), linux-androideabi)
-$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)_$(2))
-       $$(Q)$$(MAKE) -C $$(@D) \
+$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS)
+       $$(Q)$$(MAKE) -C $$(S)src/libuv/ \
                CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
                LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1)))" \
                CC="$$(CC_$(1))" \
                CXX="$$(CXX_$(1))" \
+               LINK="$$(CXX_$(1))" \
                AR="$$(AR_$(1))" \
-               host=android OS=linux \
-               builddir="." \
+               PLATFORM=android \
                BUILDTYPE=Release \
-               NO_LOAD="$$(LIBUV_NO_LOAD)" \
+               builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/stage$(2)/libuv" \
+               host=android OS=linux \
                V=$$(VERBOSE)
 else
-$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)_$(2))
-       $$(Q)$$(MAKE) -C $$(@D) \
+$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS)
+       $$(Q)$$(MAKE) -C $$(S)src/libuv/ \
                CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
                LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1)))" \
                CC="$$(CC_$(1))" \
                CXX="$$(CXX_$(1))" \
                AR="$$(AR_$(1))" \
-               builddir="." \
-               BUILDTYPE=Release \
-               NO_LOAD="$$(LIBUV_NO_LOAD)" \
+               builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/stage$(2)/libuv" \
                V=$$(VERBOSE)
 endif
 
@@ -274,7 +261,3 @@ endef
 $(foreach stage,$(STAGES), \
        $(foreach target,$(CFG_TARGET_TRIPLES), \
         $(eval $(call DEF_RUNTIME_TARGETS,$(target),$(stage)))))
-
-$(LIBUV_GYP):
-       mkdir -p $(S)src/libuv/build
-       git clone https://git.chromium.org/external/gyp.git $(S)src/libuv/build/gyp
index 67b2a26c3af44c50113424eb778810b3c590664b..c6a4badaed07787d5a642f20c3ea6b2ff0911027 100644 (file)
@@ -869,7 +869,8 @@ $(foreach host,$(CFG_HOST_TRIPLES), \
  $(eval $(foreach target,$(CFG_TARGET_TRIPLES), \
    $(eval $(call DEF_CHECK_FAST_FOR_T_H,,$(target),$(host))))))
 
-check-fast: tidy check-fast-H-$(CFG_BUILD_TRIPLE)
+check-fast: tidy check-fast-H-$(CFG_BUILD_TRIPLE) check-stage2-std check-stage2-extra
+       $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 define DEF_CHECK_FAST_FOR_H
 
index 3ae3600cf88c6a41759e1571b25a625f2fd163f8..6a365ae05dd951b3c262d3d1e87516f27198d3da 100644 (file)
@@ -83,9 +83,6 @@ pub struct config {
     // Run tests using the JIT
     jit: bool,
 
-    // Run tests using the new runtime
-    newrt: bool,
-
     // Target system to be tested
     target: ~str,
 
index 8de79749b54f3f57053fd9db1c59709addeb7e14..be8f9655010bbfa8ccaca45ce7007b68f5fb311c 100644 (file)
@@ -71,7 +71,6 @@ pub fn parse_config(args: ~[~str]) -> config {
           optopt("", "ratchet-noise-percent",
                  "percent change in metrics to consider noise", "N"),
           optflag("", "jit", "run tests under the JIT"),
-          optflag("", "newrt", "run tests on the new runtime / scheduler"),
           optopt("", "target", "the target to build for", "TARGET"),
           optopt("", "adb-path", "path to the android debugger", "PATH"),
           optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"),
@@ -135,7 +134,6 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Path {
         runtool: getopts::opt_maybe_str(matches, "runtool"),
         rustcflags: getopts::opt_maybe_str(matches, "rustcflags"),
         jit: getopts::opt_present(matches, "jit"),
-        newrt: getopts::opt_present(matches, "newrt"),
         target: opt_str2(getopts::opt_maybe_str(matches, "target")).to_str(),
         adb_path: opt_str2(getopts::opt_maybe_str(matches, "adb-path")).to_str(),
         adb_test_dir:
@@ -169,7 +167,6 @@ pub fn log_config(config: &config) {
     logv(c, fmt!("runtool: %s", opt_str(&config.runtool)));
     logv(c, fmt!("rustcflags: %s", opt_str(&config.rustcflags)));
     logv(c, fmt!("jit: %b", config.jit));
-    logv(c, fmt!("newrt: %b", config.newrt));
     logv(c, fmt!("target: %s", config.target));
     logv(c, fmt!("adb_path: %s", config.adb_path));
     logv(c, fmt!("adb_test_dir: %s", config.adb_test_dir));
index 74627829c60ff52b2f37c4e03d6a6582c654edf3..45e4f756d7a15752a7e3d3e7ed672ac2547c8296 100644 (file)
@@ -54,10 +54,10 @@ pub fn run(lib_path: &str,
         in_fd: None,
         out_fd: None,
         err_fd: None
-    }).unwrap();
+    });
 
     for input in input.iter() {
-        proc.input().write(input.as_bytes());
+        proc.input().write_str(*input);
     }
     let output = proc.finish_with_output();
 
index 16de4f8e82233dbdbd1b1c5c4c54d1981cfacc6e..ea94ce662ac1e726779d5ded99db5e2897e9b7cd 100644 (file)
 use util;
 use util::logv;
 
+use std::cell::Cell;
 use std::io;
 use std::os;
 use std::str;
+use std::task::{spawn_sched, SingleThreaded};
 use std::vec;
+use std::unstable::running_on_valgrind;
 
 use extra::test::MetricMap;
 
 pub fn run(config: config, testfile: ~str) {
-    let mut _mm = MetricMap::new();
-    run_metrics(config, testfile, &mut _mm);
+    let config = Cell::new(config);
+    let testfile = Cell::new(testfile);
+    // FIXME #6436: Creating another thread to run the test because this
+    // is going to call waitpid. The new scheduler has some strange
+    // interaction between the blocking tasks and 'friend' schedulers
+    // that destroys parallelism if we let normal schedulers block.
+    // It should be possible to remove this spawn once std::run is
+    // rewritten to be non-blocking.
+    //
+    // We do _not_ create another thread if we're running on V because
+    // it serializes all threads anyways.
+    if running_on_valgrind() {
+        let config = config.take();
+        let testfile = testfile.take();
+        let mut _mm = MetricMap::new();
+        run_metrics(config, testfile, &mut _mm);
+    } else {
+        do spawn_sched(SingleThreaded) {
+            let config = config.take();
+            let testfile = testfile.take();
+            let mut _mm = MetricMap::new();
+            run_metrics(config, testfile, &mut _mm);
+        }
+    }
 }
 
 pub fn run_metrics(config: config, testfile: ~str, mm: &mut MetricMap) {
@@ -522,15 +547,13 @@ fn compile_test_(config: &config, props: &TestProps,
 fn exec_compiled_test(config: &config, props: &TestProps,
                       testfile: &Path) -> ProcRes {
 
-    // If testing the new runtime then set the RUST_NEWRT env var
     let env = props.exec_env.clone();
-    let env = if config.newrt { env + &[(~"RUST_NEWRT", ~"1")] } else { env };
 
     match config.target {
 
         ~"arm-linux-androideabi" => {
             if (config.adb_device_status) {
-                _arm_exec_compiled_test(config, props, testfile)
+                _arm_exec_compiled_test(config, props, testfile, env)
             } else {
                 _dummy_exec_compiled_test(config, props, testfile)
             }
@@ -756,7 +779,7 @@ fn fatal_ProcRes(err: ~str, ProcRes: &ProcRes) -> ! {
 }
 
 fn _arm_exec_compiled_test(config: &config, props: &TestProps,
-                      testfile: &Path) -> ProcRes {
+                      testfile: &Path, env: ~[(~str, ~str)]) -> ProcRes {
 
     let args = make_run_args(config, props, testfile);
     let cmdline = make_cmdline("", args.prog, args.args);
@@ -782,6 +805,9 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
 
     // run test via adb_run_wrapper
     runargs.push(~"shell");
+    for (key, val) in env.move_iter() {
+        runargs.push(fmt!("%s=%s", key, val));
+    }
     runargs.push(fmt!("%s/adb_run_wrapper.sh", config.adb_test_dir));
     runargs.push(fmt!("%s", config.adb_test_dir));
     runargs.push(fmt!("%s", prog_short));
index 4bb0c4040306b18a350a27108833bb5708d39184..92b85247e4891a670dae04ef92f9497bdc757d53 100644 (file)
@@ -5,6 +5,7 @@
 ;; Url: https://github.com/mozilla/rust
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'misc))
 
 ;; Syntax definitions and helpers
 (defvar rust-mode-syntax-table
 
     table))
 
-(defcustom rust-indent-offset default-tab-width
-  "*Indent Rust code by this number of spaces.
-
-The initializer is `DEFAULT-TAB-WIDTH'.")
+(defcustom rust-indent-offset 4
+  "*Indent Rust code by this number of spaces.")
 
 (defun rust-paren-level () (nth 0 (syntax-ppss)))
 (defun rust-in-str-or-cmnt () (nth 8 (syntax-ppss)))
@@ -59,19 +58,39 @@ The initializer is `DEFAULT-TAB-WIDTH'.")
               ;; A closing brace is 1 level unindended
               ((looking-at "}") (* rust-indent-offset (- level 1)))
 
+              ; Doc comments in /** style with leading * indent to line up the *s
+              ((and (nth 4 (syntax-ppss)) (looking-at "*"))
+               (+ 1 (* rust-indent-offset level)))
+
               ;; If we're in any other token-tree / sexp, then:
               ;;  - [ or ( means line up with the opening token
-              ;;  - { means indent to either nesting-level * tab width,
+              ;;  - { means indent to either nesting-level * rust-indent-offset,
               ;;    or one further indent from that if either current line
               ;;    begins with 'else', or previous line didn't end in
-              ;;    semi, comma or brace, and wasn't an attribute. PHEW.
+              ;;    semi, comma or brace (other than whitespace and line
+              ;;    comments) , and wasn't an attribute.  But if we have 
+              ;;    something after the open brace and ending with a comma,
+              ;;    treat it as fields and align them.  PHEW.
               ((> level 0)
                (let ((pt (point)))
                  (rust-rewind-irrelevant)
                  (backward-up-list)
-                 (if (looking-at "[[(]")
-                     (+ 1 (current-column))
+                 (cond 
+                  ((and
+                      (looking-at "[[(]")
+                      ; We don't want to indent out to the open bracket if the
+                      ; open bracket ends the line
+                      (save-excursion 
+                        (forward-char)
+                        (not (looking-at "[[:space:]]*\\(?://.*\\)?$"))))
+                   (+ 1 (current-column)))
+                  ;; Check for fields on the same line as the open curly brace:
+                  ((looking-at "{[[:blank:]]*[^}\n]*,[[:space:]]*$")
                    (progn
+                    (forward-char)
+                    (forward-to-word 1)
+                    (current-column)))
+                  (t (progn
                      (goto-char pt)
                      (back-to-indentation)
                      (if (looking-at "\\<else\\>")
@@ -81,12 +100,12 @@ The initializer is `DEFAULT-TAB-WIDTH'.")
                          (beginning-of-line)
                          (rust-rewind-irrelevant)
                          (end-of-line)
-                         (if (looking-back "[{};,]")
+                         (if (looking-back "[,;{}(][[:space:]]*\\(?://.*\\)?")
                              (* rust-indent-offset level)
                            (back-to-indentation)
                            (if (looking-at "#")
                                (* rust-indent-offset level)
-                             (* rust-indent-offset (+ 1 level))))))))))
+                             (* rust-indent-offset (+ 1 level)))))))))))
 
               ;; Otherwise we're in a column-zero definition
               (t 0))))))
index 8e641073637853e103c1c08e29f0fa465a21cf04..fa8b50fbf672994c71b15571264efe104597557d 100644 (file)
@@ -594,7 +594,7 @@ fn eq(&self, other: &DList<A>) -> bool {
     }
 
     fn ne(&self, other: &DList<A>) -> bool {
-        self.len() != other.len() &&
+        self.len() != other.len() ||
             iterator::order::ne(self.iter(), other.iter())
     }
 }
@@ -978,6 +978,10 @@ fn test_eq() {
         assert!(n != m);
         m.push_back(1);
         assert_eq!(&n, &m);
+
+        let n = list_from([2,3,4]);
+        let m = list_from([1,2,3]);
+        assert!(n != m);
     }
 
     #[test]
index a13836d87bd74f88462813e4decfa28341a9e653..911d53da9092c8cb5ed2bbd7f4b566c3dde94146 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -1164,9 +1164,6 @@ fn lt(&self, other: &Json) -> bool {
             }
         }
     }
-    fn le(&self, other: &Json) -> bool { !(*other).lt(&(*self)) }
-    fn ge(&self, other: &Json) -> bool { !(*self).lt(other) }
-    fn gt(&self, other: &Json) -> bool { (*other).lt(&(*self))  }
 }
 
 /// A trait for converting values to JSON
index b0f89e219d8d8aa81d06240a04aaa853dae5e0b0..8f7c6a03d1a7363ab7b3f4002f646497f83fdb88 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -37,18 +37,6 @@ fn lt(&self, other: &Identifier) -> bool {
             (&AlphaNumeric(_), _) => false
         }
     }
-    #[inline]
-    fn le(&self, other: &Identifier) -> bool {
-        ! (other < self)
-    }
-    #[inline]
-    fn gt(&self, other: &Identifier) -> bool {
-        other < self
-    }
-    #[inline]
-    fn ge(&self, other: &Identifier) -> bool {
-        ! (self < other)
-    }
 }
 
 impl ToStr for Identifier {
index ccade8f19bebc456104c316f15726333364555ac..73f6d2e1bda8be85e217c8082f1bdbad9c64c2b5 100644 (file)
@@ -203,7 +203,7 @@ fn usage(binary: &str, helpstr: &str) -> ! {
 have a substring match, only those tests are run.
 
 By default, all tests are run in parallel. This can be altered with the
-RUST_THREADS environment variable when running tests (set it to 1).
+RUST_TEST_TASKS environment variable when running tests (set it to 1).
 
 Test Attributes:
 
@@ -740,9 +740,20 @@ fn run_tests(opts: &TestOpts,
 
 fn get_concurrency() -> uint {
     use std::rt;
-    let threads = rt::util::default_sched_threads();
-    if threads == 1 { 1 }
-    else { threads * SCHED_OVERCOMMIT }
+    match os::getenv("RUST_TEST_TASKS") {
+        Some(s) => {
+            let opt_n: Option<uint> = FromStr::from_str(s);
+            match opt_n {
+                Some(n) if n > 0 => n,
+                _ => fail!("RUST_TEST_TASKS is `%s`, should be a positive integer.", s)
+            }
+        }
+        None => {
+            let threads = rt::util::default_sched_threads();
+            if threads == 1 { 1 }
+            else { threads * SCHED_OVERCOMMIT }
+        }
+    }
 }
 
 pub fn filter_tests(
index ccebf88ec38b64bb69a982e54260f9aafcdc9f44..7ebb47d5124ba337cf1ce0f39609a0e19a458134 100644 (file)
@@ -216,7 +216,7 @@ pub mod write {
     use lib;
 
     use std::c_str::ToCStr;
-    use std::libc::c_uint;
+    use std::libc::{c_uint, c_int};
     use std::path::Path;
     use std::run;
     use std::str;
@@ -257,17 +257,7 @@ pub fn run_passes(sess: Session,
                 }
             }
 
-            // Copy what clan does by turning on loop vectorization at O2 and
-            // slp vectorization at O3
-            let vectorize_loop = !sess.no_vectorize_loops() &&
-                                 (sess.opts.optimize == session::Default ||
-                                  sess.opts.optimize == session::Aggressive);
-            let vectorize_slp = !sess.no_vectorize_slp() &&
-                                sess.opts.optimize == session::Aggressive;
-            llvm::LLVMRustSetLLVMOptions(sess.print_llvm_passes(),
-                                         vectorize_loop,
-                                         vectorize_slp,
-                                         sess.time_llvm_passes());
+            configure_llvm(sess);
 
             let OptLevel = match sess.opts.optimize {
               session::No => lib::llvm::CodeGenLevelNone,
@@ -293,12 +283,9 @@ pub fn run_passes(sess: Session,
             // Create the two optimizing pass managers. These mirror what clang
             // does, and are by populated by LLVM's default PassManagerBuilder.
             // Each manager has a different set of passes, but they also share
-            // some common passes. Each one is initialized with the analyis
-            // passes the target requires, and then further passes are added.
+            // some common passes.
             let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
             let mpm = llvm::LLVMCreatePassManager();
-            llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
-            llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
 
             // If we're verifying or linting, add them to the function pass
             // manager.
@@ -308,32 +295,11 @@ pub fn run_passes(sess: Session,
             if !sess.no_verify() { assert!(addpass("verify")); }
             if sess.lint_llvm()  { assert!(addpass("lint"));   }
 
-            // Create the PassManagerBuilder for LLVM. We configure it with
-            // reasonable defaults and prepare it to actually populate the pass
-            // manager.
-            let builder = llvm::LLVMPassManagerBuilderCreate();
-            match sess.opts.optimize {
-                session::No => {
-                    // Don't add lifetime intrinsics add O0
-                    llvm::LLVMRustAddAlwaysInlinePass(builder, false);
-                }
-                // numeric values copied from clang
-                session::Less => {
-                    llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
-                                                                        225);
-                }
-                session::Default | session::Aggressive => {
-                    llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
-                                                                        275);
-                }
+            if !sess.no_prepopulate_passes() {
+                llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
+                llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
+                populate_llvm_passess(fpm, mpm, llmod, OptLevel);
             }
-            llvm::LLVMPassManagerBuilderSetOptLevel(builder, OptLevel as c_uint);
-            llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod);
-
-            // Use the builder to populate the function/module pass managers.
-            llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
-            llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
-            llvm::LLVMPassManagerBuilderDispose(builder);
 
             for pass in sess.opts.custom_passes.iter() {
                 do pass.with_c_str |s| {
@@ -424,6 +390,74 @@ pub fn run_assembler(sess: Session, assembly: &Path, object: &Path) {
             sess.abort_if_errors();
         }
     }
+
+    unsafe fn configure_llvm(sess: Session) {
+        // Copy what clan does by turning on loop vectorization at O2 and
+        // slp vectorization at O3
+        let vectorize_loop = !sess.no_vectorize_loops() &&
+                             (sess.opts.optimize == session::Default ||
+                              sess.opts.optimize == session::Aggressive);
+        let vectorize_slp = !sess.no_vectorize_slp() &&
+                            sess.opts.optimize == session::Aggressive;
+
+        let mut llvm_c_strs = ~[];
+        let mut llvm_args = ~[];
+        let add = |arg: &str| {
+            let s = arg.to_c_str();
+            llvm_args.push(s.with_ref(|p| p));
+            llvm_c_strs.push(s);
+        };
+        add("rustc"); // fake program name
+        add("-arm-enable-ehabi");
+        add("-arm-enable-ehabi-descriptors");
+        if vectorize_loop { add("-vectorize-loops"); }
+        if vectorize_slp  { add("-vectorize-slp");   }
+        if sess.time_llvm_passes() { add("-time-passes"); }
+        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
+
+        for arg in sess.opts.llvm_args.iter() {
+            add(*arg);
+        }
+
+        do llvm_args.as_imm_buf |p, len| {
+            llvm::LLVMRustSetLLVMOptions(len as c_int, p);
+        }
+    }
+
+    unsafe fn populate_llvm_passess(fpm: lib::llvm::PassManagerRef,
+                                    mpm: lib::llvm::PassManagerRef,
+                                    llmod: ModuleRef,
+                                    opt: lib::llvm::CodeGenOptLevel) {
+        // Create the PassManagerBuilder for LLVM. We configure it with
+        // reasonable defaults and prepare it to actually populate the pass
+        // manager.
+        let builder = llvm::LLVMPassManagerBuilderCreate();
+        match opt {
+            lib::llvm::CodeGenLevelNone => {
+                // Don't add lifetime intrinsics add O0
+                llvm::LLVMRustAddAlwaysInlinePass(builder, false);
+            }
+            lib::llvm::CodeGenLevelLess => {
+                llvm::LLVMRustAddAlwaysInlinePass(builder, true);
+            }
+            // numeric values copied from clang
+            lib::llvm::CodeGenLevelDefault => {
+                llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
+                                                                    225);
+            }
+            lib::llvm::CodeGenLevelAggressive => {
+                llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
+                                                                    275);
+            }
+        }
+        llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
+        llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod);
+
+        // Use the builder to populate the function/module pass managers.
+        llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
+        llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
+        llvm::LLVMPassManagerBuilderDispose(builder);
+    }
 }
 
 
index 003840b85a16744b063e9fe57bf8c4785be398cf..74452f195493916542bcb611442cda7e138f455f 100644 (file)
@@ -737,6 +737,14 @@ fn set_llvm_debug() {
             }).collect()
         }
     };
+    let llvm_args = match getopts::opt_maybe_str(matches, "llvm-args") {
+        None => ~[],
+        Some(s) => {
+            s.split_iter(|c: char| c == ' ' || c == ',').map(|s| {
+                s.trim().to_owned()
+            }).collect()
+        }
+    };
 
     let sopts = @session::options {
         crate_type: crate_type,
@@ -744,6 +752,7 @@ fn set_llvm_debug() {
         gc: gc,
         optimize: opt_level,
         custom_passes: custom_passes,
+        llvm_args: llvm_args,
         debuginfo: debuginfo,
         extra_debuginfo: extra_debuginfo,
         lint_opts: lint_opts,
@@ -851,6 +860,8 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] {
                         Appends to the default list of passes to run for the \
                         specified current optimization level. A value of \
                         \"list\" will list all of the available passes", "NAMES"),
+  optopt("", "llvm-args", "A list of arguments to pass to llvm, comma \
+                           separated", "ARGS"),
   optopt( "",  "out-dir",
                         "Write output to compiler-chosen filename
                           in <dir>", "DIR"),
index 912fc606f0a344d6e126c4f39c561002c0970b81..90a23c78d3050deb05a9d0b1aca2854d1f07c849 100644 (file)
@@ -79,6 +79,7 @@ pub struct config {
 pub static print_llvm_passes:       uint = 1 << 27;
 pub static no_vectorize_loops:      uint = 1 << 28;
 pub static no_vectorize_slp:        uint = 1 << 29;
+pub static no_prepopulate_passes:   uint = 1 << 30;
 
 pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
     ~[(~"verbose", ~"in general, enable more debug printouts", verbose),
@@ -126,6 +127,10 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
      (~"print-llvm-passes",
       ~"Prints the llvm optimization passes being run",
       print_llvm_passes),
+     (~"no-prepopulate-passes",
+      ~"Don't pre-populate the pass managers with a list of passes, only use \
+        the passes from --passes",
+      no_prepopulate_passes),
      (~"no-vectorize-loops",
       ~"Don't run the loop vectorization optimization passes",
       no_vectorize_loops),
@@ -152,6 +157,7 @@ pub struct options {
     gc: bool,
     optimize: OptLevel,
     custom_passes: ~[~str],
+    llvm_args: ~[~str],
     debuginfo: bool,
     extra_debuginfo: bool,
     lint_opts: ~[(lint::lint, lint::level)],
@@ -320,6 +326,9 @@ pub fn once_fns(@self) -> bool { self.debugging_opt(once_fns) }
     pub fn print_llvm_passes(@self) -> bool {
         self.debugging_opt(print_llvm_passes)
     }
+    pub fn no_prepopulate_passes(@self) -> bool {
+        self.debugging_opt(no_prepopulate_passes)
+    }
     pub fn no_vectorize_loops(@self) -> bool {
         self.debugging_opt(no_vectorize_loops)
     }
@@ -351,6 +360,7 @@ pub fn basic_options() -> @options {
         gc: false,
         optimize: No,
         custom_passes: ~[],
+        llvm_args: ~[],
         debuginfo: false,
         extra_debuginfo: false,
         lint_opts: ~[],
index 220b082fab1cf986fd7fa8318a3f853b1d50d4f5..c9253026488e269493487592e2c00270be922e3e 100644 (file)
@@ -191,6 +191,7 @@ pub enum AsmDialect {
     AD_Intel = 1
 }
 
+#[deriving(Eq)]
 pub enum CodeGenOptLevel {
     CodeGenLevelNone = 0,
     CodeGenLevelLess = 1,
@@ -2123,10 +2124,7 @@ pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
         pub fn LLVMRustPrintModule(PM: PassManagerRef,
                                    M: ModuleRef,
                                    Output: *c_char);
-        pub fn LLVMRustSetLLVMOptions(PrintPasses: bool,
-                                      VectorizeLoops: bool,
-                                      VectorizeSLP: bool,
-                                      TimePasses: bool);
+        pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: **c_char);
         pub fn LLVMRustPrintPasses();
         pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *c_char);
         pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef,
index edea267d22686c70ed6d8e2388c7869c8463b9f9..2daa2bafaacec1488d5b09c372fd06476204b48b 100644 (file)
@@ -129,7 +129,7 @@ fn check_impl_of_trait(cx: Context, it: @item, trait_ref: &trait_ref, self_type:
 
     // If this trait has builtin-kind supertraits, meet them.
     let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id);
-    error!("checking impl with self type %?", ty::get(self_ty).sty);
+    debug!("checking impl with self type %?", ty::get(self_ty).sty);
     do check_builtin_bounds(cx, self_ty, trait_def.bounds) |missing| {
         cx.tcx.sess.span_err(self_type.span,
             fmt!("the type `%s', which does not fulfill `%s`, cannot implement this \
index 2989f1047298ccace23c91427c3adab797062ffb..c5be424e2846cfe9419e8b8b012beecce2594d5a 100644 (file)
@@ -2585,11 +2585,13 @@ pub fn resolve_glob_import(@mut self,
                 debug!("(resolving glob import) ... for value target");
                 dest_import_resolution.value_target =
                     Some(Target(containing_module, name_bindings));
+                dest_import_resolution.value_id = id;
             }
             if name_bindings.defined_in_public_namespace(TypeNS) {
                 debug!("(resolving glob import) ... for type target");
                 dest_import_resolution.type_target =
                     Some(Target(containing_module, name_bindings));
+                dest_import_resolution.type_id = id;
             }
         };
 
index e8186477877f423e019be698ce7719047c721add..1dc30d2221da897d53b4afb9882eba90515c12a1 100644 (file)
@@ -87,6 +87,7 @@
 use syntax::print::pprust::stmt_to_str;
 use syntax::{ast, ast_util, codemap, ast_map};
 use syntax::abi::{X86, X86_64, Arm, Mips};
+use syntax::visit::Visitor;
 
 pub use middle::trans::context::task_llcx;
 
@@ -2162,6 +2163,14 @@ pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
     }
 }
 
+pub struct TransItemVisitor;
+
+impl Visitor<@mut CrateContext> for TransItemVisitor {
+    fn visit_item(&mut self, i: @ast::item, ccx: @mut CrateContext) {
+        trans_item(ccx, i);
+    }
+}
+
 pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
     let _icx = push_ctxt("trans_item");
     let path = match ccx.tcx.items.get_copy(&item.id) {
@@ -2193,15 +2202,10 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
                      item.id,
                      item.attrs);
         } else {
-            for stmt in body.stmts.iter() {
-                match stmt.node {
-                  ast::stmt_decl(@codemap::spanned { node: ast::decl_item(i),
-                                                 _ }, _) => {
-                    trans_item(ccx, i);
-                  }
-                  _ => ()
-                }
-            }
+            // Be sure to travel more than just one layer deep to catch nested
+            // items in blocks and such.
+            let mut v = TransItemVisitor;
+            v.visit_block(body, ccx);
         }
       }
       ast::item_impl(ref generics, _, _, ref ms) => {
index 717dfbb67845396e7561dea48bd44fa6b07125b9..fb4dd8a74fb61cd9e89a158f8b89e450beefbae6 100644 (file)
@@ -37,6 +37,7 @@
 use syntax::ast_map::{path, path_mod, path_name};
 use syntax::ast_util;
 use syntax::{ast, ast_map};
+use syntax::visit;
 
 /**
 The main "translation" pass for methods.  Generates code
@@ -56,7 +57,15 @@ pub fn trans_impl(ccx: @mut CrateContext,
     debug!("trans_impl(path=%s, name=%s, id=%?)",
            path.repr(tcx), name.repr(tcx), id);
 
-    if !generics.ty_params.is_empty() { return; }
+    // Both here and below with generic methods, be sure to recurse and look for
+    // items that we need to translate.
+    if !generics.ty_params.is_empty() {
+        let mut v = TransItemVisitor;
+        for method in methods.iter() {
+            visit::walk_method_helper(&mut v, *method, ccx);
+        }
+        return;
+    }
     let sub_path = vec::append_one(path, path_name(name));
     for method in methods.iter() {
         if method.generics.ty_params.len() == 0u {
@@ -69,6 +78,9 @@ pub fn trans_impl(ccx: @mut CrateContext,
                          *method,
                          None,
                          llfn);
+        } else {
+            let mut v = TransItemVisitor;
+            visit::walk_method_helper(&mut v, *method, ccx);
         }
     }
 }
index 6f90953cd413ab2c3274cc257759178e48e32cec..a3673928df768c6e9f108100a9d609cfa537c3e7 100644 (file)
@@ -4572,7 +4572,7 @@ pub fn visitor_object_ty(tcx: ctxt,
                  trait_ref.def_id,
                  trait_ref.substs.clone(),
                  RegionTraitStore(region),
-                 ast::m_imm,
+                 ast::m_mutbl,
                  EmptyBuiltinBounds())))
 }
 
index 6ebcf4facc180e43413c5644f7cfcc606c767e7d..18cc5e65a8b4c6e7355ab9e01870cbce80bdaba2 100644 (file)
@@ -11,7 +11,7 @@
 /*!
  * Conversion from AST representation of types to the ty.rs
  * representation.  The main routine here is `ast_ty_to_ty()`: each use
- * is parameterized by an instance of `AstConv` and a `region_scope`.
+ * is parameterized by an instance of `AstConv` and a `RegionScope`.
  *
  * The parameterization of `ast_ty_to_ty()` is because it behaves
  * somewhat differently during the collect and check phases,
  * In the check phase, when the @FnCtxt is used as the `AstConv`,
  * `get_item_ty()` just looks up the item type in `tcx.tcache`.
  *
- * The `region_scope` trait controls how region references are
+ * The `RegionScope` trait controls how region references are
  * handled.  It has two methods which are used to resolve anonymous
  * region references (e.g., `&T`) and named region references (e.g.,
  * `&a.T`).  There are numerous region scopes that can be used, but most
- * commonly you want either `empty_rscope`, which permits only the static
- * region, or `type_rscope`, which permits the self region if the type in
+ * commonly you want either `EmptyRscope`, which permits only the static
+ * region, or `TypeRscope`, which permits the self region if the type in
  * question is parameterized by a region.
  *
  * Unlike the `AstConv` trait, the region scope can change as we descend
@@ -58,7 +58,7 @@
 use middle::ty::{ty_param_substs_and_ty};
 use middle::ty;
 use middle::typeck::rscope::in_binding_rscope;
-use middle::typeck::rscope::{region_scope, RegionError};
+use middle::typeck::rscope::{RegionScope, RegionError};
 use middle::typeck::rscope::RegionParamNames;
 use middle::typeck::lookup_def_tcx;
 
@@ -104,7 +104,7 @@ pub fn get_region_reporting_err(
     }
 }
 
-pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Clone + 'static>(
+pub fn ast_region_to_region<AC:AstConv,RS:RegionScope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     default_span: span,
@@ -129,7 +129,7 @@ pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Clone + 'static>(
     get_region_reporting_err(this.tcx(), span, opt_lifetime, res)
 }
 
-fn ast_path_substs<AC:AstConv,RS:region_scope + Clone + 'static>(
+fn ast_path_substs<AC:AstConv,RS:RegionScope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     def_id: ast::def_id,
@@ -200,7 +200,7 @@ fn ast_path_substs<AC:AstConv,RS:region_scope + Clone + 'static>(
 }
 
 pub fn ast_path_to_substs_and_ty<AC:AstConv,
-                                 RS:region_scope + Clone + 'static>(
+                                 RS:RegionScope + Clone + 'static>(
                                  this: &AC,
                                  rscope: &RS,
                                  did: ast::def_id,
@@ -217,7 +217,7 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,
     ty_param_substs_and_ty { substs: substs, ty: ty }
 }
 
-pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Clone + 'static>(
+pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     trait_def_id: ast::def_id,
@@ -240,7 +240,7 @@ pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Clone + 'static>(
     return trait_ref;
 }
 
-pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Clone + 'static>(
+pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope + Clone + 'static>(
         this: &AC,
         rscope: &RS,
         did: ast::def_id,
@@ -262,10 +262,10 @@ pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Clone + 'static>(
 // Parses the programmer's textual representation of a type into our
 // internal notion of a type. `getter` is a function that returns the type
 // corresponding to a definition ID:
-pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Clone + 'static>(
+pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope + Clone + 'static>(
     this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
 
-    fn ast_mt_to_mt<AC:AstConv, RS:region_scope + Clone + 'static>(
+    fn ast_mt_to_mt<AC:AstConv, RS:RegionScope + Clone + 'static>(
         this: &AC, rscope: &RS, mt: &ast::mt) -> ty::mt {
 
         ty::mt {ty: ast_ty_to_ty(this, rscope, mt.ty), mutbl: mt.mutbl}
@@ -274,7 +274,7 @@ fn ast_mt_to_mt<AC:AstConv, RS:region_scope + Clone + 'static>(
     // Handle @, ~, and & being able to mean estrs and evecs.
     // If a_seq_ty is a str or a vec, make it an estr/evec.
     // Also handle first-class trait types.
-    fn mk_pointer<AC:AstConv,RS:region_scope + Clone + 'static>(
+    fn mk_pointer<AC:AstConv,RS:RegionScope + Clone + 'static>(
         this: &AC,
         rscope: &RS,
         a_seq_ty: &ast::mt,
@@ -540,7 +540,7 @@ fn check_path_args(tcx: ty::ctxt,
 }
 
 pub fn ty_of_arg<AC:AstConv,
-                 RS:region_scope + Clone + 'static>(
+                 RS:RegionScope + Clone + 'static>(
                  this: &AC,
                  rscope: &RS,
                  a: &ast::arg,
@@ -588,7 +588,7 @@ struct SelfInfo {
     explicit_self: ast::explicit_self
 }
 
-pub fn ty_of_method<AC:AstConv,RS:region_scope + Clone + 'static>(
+pub fn ty_of_method<AC:AstConv,RS:RegionScope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     purity: ast::purity,
@@ -606,7 +606,7 @@ pub fn ty_of_method<AC:AstConv,RS:region_scope + Clone + 'static>(
     (a.unwrap(), b)
 }
 
-pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Clone + 'static>(
+pub fn ty_of_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     purity: ast::purity,
@@ -619,7 +619,7 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Clone + 'static>(
     b
 }
 
-fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Clone + 'static>(
+fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     purity: ast::purity,
@@ -657,7 +657,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Clone + 'static>(
                                 output: output_ty}
             });
 
-    fn transform_self_ty<AC:AstConv,RS:region_scope + Clone + 'static>(
+    fn transform_self_ty<AC:AstConv,RS:RegionScope + Clone + 'static>(
         this: &AC,
         rscope: &RS,
         self_info: &SelfInfo) -> Option<ty::t>
@@ -690,7 +690,7 @@ fn transform_self_ty<AC:AstConv,RS:region_scope + Clone + 'static>(
     }
 }
 
-pub fn ty_of_closure<AC:AstConv,RS:region_scope + Clone + 'static>(
+pub fn ty_of_closure<AC:AstConv,RS:RegionScope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     sigil: ast::Sigil,
index 0b27a581a2aa4bc6cb4fc5bf041c147574b99964..3016d40729b671530fd8457005246da9a6ab1a3c 100644 (file)
 use middle::typeck::infer;
 use middle::typeck::rscope::bound_self_region;
 use middle::typeck::rscope::{RegionError};
-use middle::typeck::rscope::region_scope;
+use middle::typeck::rscope::RegionScope;
 use middle::typeck::{isr_alist, lookup_def_ccx};
 use middle::typeck::no_params;
 use middle::typeck::{require_same_types, method_map, vtable_map};
@@ -705,7 +705,7 @@ pub fn search_in_scope_regions(&self,
     }
 }
 
-impl region_scope for FnCtxt {
+impl RegionScope for FnCtxt {
     fn anon_region(&self, span: span) -> Result<ty::Region, RegionError> {
         result::Ok(self.infcx().next_region_var(infer::MiscVariable(span)))
     }
index 63317d4ca5c91bb04915e3cd9e734475684ea767..71a9a041fb5791656f1ba3891a371c2608d69953 100644 (file)
@@ -97,7 +97,7 @@ fn collect_intrinsic_type(ccx: &CrateCtxt,
 }
 
 pub trait ToTy {
-    fn to_ty<RS:region_scope + Clone + 'static>(
+    fn to_ty<RS:RegionScope + Clone + 'static>(
              &self,
              rs: &RS,
              ast_ty: &ast::Ty)
@@ -105,7 +105,7 @@ fn to_ty<RS:region_scope + Clone + 'static>(
 }
 
 impl ToTy for CrateCtxt {
-    fn to_ty<RS:region_scope + Clone + 'static>(
+    fn to_ty<RS:RegionScope + Clone + 'static>(
              &self,
              rs: &RS,
              ast_ty: &ast::Ty)
@@ -163,7 +163,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
         let result_ty;
         match variant.node.kind {
             ast::tuple_variant_kind(ref args) if args.len() > 0 => {
-                let rs = type_rscope(region_parameterization);
+                let rs = TypeRscope(region_parameterization);
                 let input_tys = args.map(|va| ccx.to_ty(&rs, &va.ty));
                 result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
             }
@@ -724,7 +724,7 @@ pub fn convert_field(ccx: &CrateCtxt,
                      generics: &ast::Generics) {
     let region_parameterization =
         RegionParameterization::from_variance_and_generics(rp, generics);
-    let tt = ccx.to_ty(&type_rscope(region_parameterization), &v.node.ty);
+    let tt = ccx.to_ty(&TypeRscope(region_parameterization), &v.node.ty);
     write_ty_to_tcx(ccx.tcx, v.node.id, tt);
     /* add the field to the tcache */
     ccx.tcx.tcache.insert(local_def(v.node.id),
@@ -863,7 +863,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
         let i_ty_generics = ty_generics(ccx, rp, generics, 0);
         let region_parameterization =
             RegionParameterization::from_variance_and_generics(rp, generics);
-        let selfty = ccx.to_ty(&type_rscope(region_parameterization), selfty);
+        let selfty = ccx.to_ty(&TypeRscope(region_parameterization), selfty);
         write_ty_to_tcx(tcx, it.id, selfty);
         tcx.tcache.insert(local_def(it.id),
                           ty_param_bounds_and_ty {
@@ -1024,7 +1024,7 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
 
     let rp = RegionParameterization::from_variance_and_generics(rp, generics);
 
-    let rscope = type_rscope(rp);
+    let rscope = TypeRscope(rp);
 
     match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
         ast::def_trait(trait_did) => {
@@ -1099,7 +1099,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item)
     let rp = tcx.region_paramd_items.find(&it.id).map_move(|x| *x);
     match it.node {
       ast::item_static(ref t, _, _) => {
-        let typ = ccx.to_ty(&empty_rscope, t);
+        let typ = ccx.to_ty(&EmptyRscope, t);
         let tpt = no_params(typ);
         tcx.tcache.insert(local_def(it.id), tpt);
         return tpt;
@@ -1108,7 +1108,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item)
         assert!(rp.is_none());
         let ty_generics = ty_generics(ccx, None, generics, 0);
         let tofd = astconv::ty_of_bare_fn(ccx,
-                                          &empty_rscope,
+                                          &EmptyRscope,
                                           purity,
                                           abi,
                                           &generics.lifetimes,
@@ -1137,7 +1137,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item)
         let region_parameterization =
             RegionParameterization::from_variance_and_generics(rp, generics);
         let tpt = {
-            let ty = ccx.to_ty(&type_rscope(region_parameterization), t);
+            let ty = ccx.to_ty(&TypeRscope(region_parameterization), t);
             ty_param_bounds_and_ty {
                 generics: ty_generics(ccx, rp, generics, 0),
                 ty: ty
@@ -1197,7 +1197,7 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
                     type_param_defs: @~[],
                     region_param: None,
                 },
-                ty: ast_ty_to_ty(ccx, &empty_rscope, t)
+                ty: ast_ty_to_ty(ccx, &EmptyRscope, t)
             }
         }
     }
@@ -1282,7 +1282,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
                           -> ty::ty_param_bounds_and_ty {
     let ty_generics = ty_generics(ccx, None, ast_generics, 0);
     let region_param_names = RegionParamNames::from_generics(ast_generics);
-    let rb = in_binding_rscope(&empty_rscope, region_param_names);
+    let rb = in_binding_rscope(&EmptyRscope, region_param_names);
     let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, a, None) );
     let output_ty = ast_ty_to_ty(ccx, &rb, &decl.output);
 
index c9e2b8dd37b9dfb02d6a3fdc83bccc19ea0b9cfa..a93ff9c5fd0fe734109d018074421309eff90bd0 100644 (file)
@@ -24,7 +24,7 @@ pub struct RegionError {
     replacement: ty::Region
 }
 
-pub trait region_scope {
+pub trait RegionScope {
     fn anon_region(&self, span: span) -> Result<ty::Region, RegionError>;
     fn self_region(&self, span: span) -> Result<ty::Region, RegionError>;
     fn named_region(&self, span: span, id: ast::ident)
@@ -32,8 +32,8 @@ fn named_region(&self, span: span, id: ast::ident)
 }
 
 #[deriving(Clone)]
-pub enum empty_rscope { empty_rscope }
-impl region_scope for empty_rscope {
+pub struct EmptyRscope;
+impl RegionScope for EmptyRscope {
     fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
         result::Err(RegionError {
             msg: ~"only 'static is allowed here",
@@ -175,7 +175,7 @@ pub fn region_param_names(&self) -> RegionParamNames {
     }
 }
 
-impl region_scope for MethodRscope {
+impl RegionScope for MethodRscope {
     fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
         result::Err(RegionError {
             msg: ~"anonymous lifetimes are not permitted here",
@@ -202,7 +202,7 @@ fn named_region(&self, span: span, id: ast::ident)
         if !self.region_param_names.has_ident(id) {
             return RegionParamNames::undeclared_name(None);
         }
-        do empty_rscope.named_region(span, id).chain_err |_e| {
+        do EmptyRscope.named_region(span, id).chain_err |_e| {
             result::Err(RegionError {
                 msg: ~"lifetime is not in scope",
                 replacement: ty::re_bound(ty::br_self)
@@ -212,9 +212,9 @@ fn named_region(&self, span: span, id: ast::ident)
 }
 
 #[deriving(Clone)]
-pub struct type_rscope(Option<RegionParameterization>);
+pub struct TypeRscope(Option<RegionParameterization>);
 
-impl type_rscope {
+impl TypeRscope {
     fn replacement(&self) -> ty::Region {
         if self.is_some() {
             ty::re_bound(ty::br_self)
@@ -223,7 +223,7 @@ fn replacement(&self) -> ty::Region {
         }
     }
 }
-impl region_scope for type_rscope {
+impl RegionScope for TypeRscope {
     fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
         result::Err(RegionError {
             msg: ~"anonymous lifetimes are not permitted here",
@@ -251,7 +251,7 @@ fn self_region(&self, _span: span) -> Result<ty::Region, RegionError> {
     }
     fn named_region(&self, span: span, id: ast::ident)
                       -> Result<ty::Region, RegionError> {
-        do empty_rscope.named_region(span, id).chain_err |_e| {
+        do EmptyRscope.named_region(span, id).chain_err |_e| {
             result::Err(RegionError {
                 msg: ~"only 'self is allowed as part of a type declaration",
                 replacement: self.replacement()
@@ -268,15 +268,15 @@ pub fn bound_self_region(rp: Option<ty::region_variance>)
     }
 }
 
-pub struct binding_rscope {
-    base: @region_scope,
+pub struct BindingRscope {
+    base: @RegionScope,
     anon_bindings: @mut uint,
     region_param_names: RegionParamNames,
 }
 
-impl Clone for binding_rscope {
-    fn clone(&self) -> binding_rscope {
-        binding_rscope {
+impl Clone for BindingRscope {
+    fn clone(&self) -> BindingRscope {
+        BindingRscope {
             base: self.base,
             anon_bindings: self.anon_bindings,
             region_param_names: self.region_param_names.clone(),
@@ -284,20 +284,20 @@ fn clone(&self) -> binding_rscope {
     }
 }
 
-pub fn in_binding_rscope<RS:region_scope + Clone + 'static>(
+pub fn in_binding_rscope<RS:RegionScope + Clone + 'static>(
         this: &RS,
         region_param_names: RegionParamNames)
-     -> binding_rscope {
+     -> BindingRscope {
     let base = @(*this).clone();
-    let base = base as @region_scope;
-    binding_rscope {
+    let base = base as @RegionScope;
+    BindingRscope {
         base: base,
         anon_bindings: @mut 0,
         region_param_names: region_param_names,
     }
 }
 
-impl region_scope for binding_rscope {
+impl RegionScope for BindingRscope {
     fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
         let idx = *self.anon_bindings;
         *self.anon_bindings += 1;
index 635d02196fe47fdbec14beed9bdad5a7ee624402..c13e85ea71659724ac3b46102a5b905125f458a2 100644 (file)
@@ -104,14 +104,14 @@ fn pandoc_writer(
     ];
 
     do generic_writer |markdown| {
+        use std::io::WriterUtil;
+
         debug!("pandoc cmd: %s", pandoc_cmd);
         debug!("pandoc args: %s", pandoc_args.connect(" "));
 
-        let proc = run::Process::new(pandoc_cmd, pandoc_args,
-                                     run::ProcessOptions::new());
-        let mut proc = proc.unwrap();
+        let mut proc = run::Process::new(pandoc_cmd, pandoc_args, run::ProcessOptions::new());
 
-        proc.input().write(markdown.as_bytes());
+        proc.input().write_str(markdown);
         let output = proc.finish_with_output();
 
         debug!("pandoc result: %i", output.status);
index 2da66baa412b57914b7d27e535ffac99d36505dd..dfe80674b7fa114bcbb457851c652a0c4d1f0b6f 100644 (file)
 /// Convenience functions intended for calling from pkg.rs
 
 fn default_ctxt(p: @Path) -> Ctx {
-    Ctx { sysroot_opt: Some(p), json: false, dep_cache: @mut HashMap::new() }
+    Ctx {
+        use_rust_path_hack: false,
+        sysroot_opt: Some(p),
+        json: false,
+        dep_cache: @mut HashMap::new()
+    }
 }
 
 pub fn build_lib(sysroot: @Path, root: Path, name: ~str, version: Version,
index 4f192fd1d92c105385286e17e6567a432cef54ca..785c635e08561a32e189d11d0743373578d9c366 100644 (file)
 condition! {
     no_rust_path: (~str) -> super::Path;
 }
+
+condition! {
+    not_a_workspace: (~str) -> super::Path;
+}
+
+condition! {
+    failed_to_create_temp_dir: (~str) -> super::Path;
+}
index 93e0789dcb0c9548d52822e0f8b4e7b07d2cd39d..4087fdd7ca5048820a19a567e89416985a349002 100644 (file)
 use std::os;
 
 pub struct Ctx {
+    // If use_rust_path_hack is true, rustpkg searches for sources
+    // in *package* directories that are in the RUST_PATH (for example,
+    // FOO/src/bar-0.1 instead of FOO). The flag doesn't affect where
+    // rustpkg stores build artifacts.
+    use_rust_path_hack: bool,
     // Sysroot -- if this is None, uses rustc filesearch's
     // idea of the default
     sysroot_opt: Option<@Path>,
index e3b3252587a082662f9258e33f98885a3302cfa1..2b56bb3885cdaf80f94bcf8b67a51aa9c75347f2 100644 (file)
@@ -37,11 +37,8 @@ pub struct PkgId {
 }
 
 impl Eq for PkgId {
-    fn eq(&self, p: &PkgId) -> bool {
-        p.path == self.path && p.version == self.version
-    }
-    fn ne(&self, p: &PkgId) -> bool {
-        !(self.eq(p))
+    fn eq(&self, other: &PkgId) -> bool {
+        self.path == other.path && self.version == other.version
     }
 }
 
index 42f33592aaaead2a5b7cb1f2174943969d398d4f..ae2083f1b22c12a3f3abea19e775e6995fd34e23 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+extern mod extra;
+
 use target::*;
 use package_id::PkgId;
 use std::path::Path;
@@ -16,8 +18,9 @@
 use crate::Crate;
 use messages::*;
 use source_control::{git_clone, git_clone_general};
-use path_util::pkgid_src_in_workspace;
+use path_util::{pkgid_src_in_workspace, find_dir_using_rust_path_hack, default_workspace};
 use util::compile_crate;
+use workspace::is_workspace;
 
 // An enumeration of the unpacked source of a package workspace.
 // This contains a list of files found in the source workspace.
@@ -48,7 +51,7 @@ pub fn new(src_dir: &Path, id: &PkgId) -> PkgSrc {
     }
 
 
-    fn check_dir(&self) -> Path {
+    fn check_dir(&self, cx: &Ctx) -> Path {
         use conditions::nonexistent_package::cond;
 
         debug!("Pushing onto root: %s | %s", self.id.path.to_str(), self.root.to_str());
@@ -59,12 +62,21 @@ fn check_dir(&self) -> Path {
 
         let dir = match path {
             Some(d) => (*d).clone(),
-            None => match self.fetch_git() {
-                Some(d) => d,
-                None => cond.raise((self.id.clone(), ~"supplied path for package dir does not \
-                                      exist, and couldn't interpret it as a URL fragment"))
+            None => {
+                match self.fetch_git() {
+                    Some(d) => d,
+                    None => {
+                        match find_dir_using_rust_path_hack(cx, &self.id) {
+                            Some(d) => d,
+                            None => cond.raise((self.id.clone(),
+                               ~"supplied path for package dir does not \
+                                 exist, and couldn't interpret it as a URL fragment"))
+                        }
+                    }
+                }
             }
         };
+        debug!("For package id %s, returning %s", self.id.to_str(), dir.to_str());
         if !os::path_is_dir(&dir) {
             cond.raise((self.id.clone(), ~"supplied path for package dir is a \
                                         non-directory"));
@@ -79,11 +91,19 @@ fn check_dir(&self) -> Path {
     /// refers to a git repo on the local version, also check it out.
     /// (right now we only support git)
     pub fn fetch_git(&self) -> Option<Path> {
+        use conditions::failed_to_create_temp_dir::cond;
+
+        // We use a temporary directory because if the git clone fails,
+        // it creates the target directory anyway and doesn't delete it
+
+        let scratch_dir = extra::tempfile::mkdtemp(&os::tmpdir(), "rustpkg");
+        let clone_target = match scratch_dir {
+            Some(d) => d.push("rustpkg_temp"),
+            None    => cond.raise(~"Failed to create temporary directory for fetching git sources")
+        };
 
         let mut local = self.root.push("src");
         local = local.push(self.id.to_str());
-        // Git can't clone into a non-empty directory
-        os::remove_dir_recursive(&local);
 
         debug!("Checking whether %s exists locally. Cwd = %s, does it? %?",
                self.id.path.to_str(),
@@ -93,15 +113,28 @@ pub fn fetch_git(&self) -> Option<Path> {
         if os::path_exists(&self.id.path) {
             debug!("%s exists locally! Cloning it into %s",
                    self.id.path.to_str(), local.to_str());
+            // Ok to use local here; we know it will succeed
             git_clone(&self.id.path, &local, &self.id.version);
             return Some(local);
         }
 
+        if (self.id.path.clone()).components().len() < 2 {
+            // If a non-URL, don't bother trying to fetch
+            return None;
+        }
+
         let url = fmt!("https://%s", self.id.path.to_str());
         note(fmt!("Fetching package: git clone %s %s [version=%s]",
-                  url, local.to_str(), self.id.version.to_str()));
-        if git_clone_general(url, &local, &self.id.version) {
-            Some(local)
+                  url, clone_target.to_str(), self.id.version.to_str()));
+
+        if git_clone_general(url, &clone_target, &self.id.version) {
+            // since the operation succeeded, move clone_target to local
+            if !os::rename_file(&clone_target, &local) {
+                 None
+            }
+            else {
+                 Some(local)
+            }
         }
         else {
             None
@@ -138,10 +171,10 @@ fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) {
 
     /// Infers crates to build. Called only in the case where there
     /// is no custom build logic
-    pub fn find_crates(&mut self) {
+    pub fn find_crates(&mut self, cx: &Ctx) {
         use conditions::missing_pkg_files::cond;
 
-        let dir = self.check_dir();
+        let dir = self.check_dir(cx);
         debug!("Called check_dir, I'm in %s", dir.to_str());
         let prefix = dir.components.len();
         debug!("Matching against %?", self.id.short_name);
@@ -183,6 +216,7 @@ pub fn find_crates(&mut self) {
     fn build_crates(&self,
                     ctx: &Ctx,
                     src_dir: &Path,
+                    destination_dir: &Path,
                     crates: &[Crate],
                     cfgs: &[~str],
                     what: OutputType) {
@@ -194,8 +228,8 @@ fn build_crates(&self,
             let result = compile_crate(ctx,
                                        &self.id,
                                        path,
-                                       // compile_crate wants the workspace
-                                       &self.root,
+                                       // compile_crate wants the destination workspace
+                                       destination_dir,
                                        crate.flags,
                                        crate.cfgs + cfgs,
                                        false,
@@ -209,15 +243,39 @@ fn build_crates(&self,
         }
     }
 
-    pub fn build(&self, ctx: &Ctx, cfgs: ~[~str]) {
-        let dir = self.check_dir();
-        debug!("Building libs in %s", dir.to_str());
-        self.build_crates(ctx, &dir, self.libs, cfgs, Lib);
+    pub fn build(&self, ctx: &Ctx, cfgs: ~[~str]) -> Path {
+        use conditions::not_a_workspace::cond;
+
+        // Determine the destination workspace (which depends on whether
+        // we're using the rust_path_hack)
+        let destination_workspace = if is_workspace(&self.root) {
+            debug!("%s is indeed a workspace", self.root.to_str());
+            self.root.clone()
+        }
+        else {
+            // It would be nice to have only one place in the code that checks
+            // for the use_rust_path_hack flag...
+            if ctx.use_rust_path_hack {
+                let rs = default_workspace();
+                debug!("Using hack: %s", rs.to_str());
+                rs
+            }
+            else {
+                cond.raise(fmt!("Package root %s is not a workspace; pass in --rust_path_hack \
+                                if you want to treat it as a package source", self.root.to_str()))
+            }
+        };
+
+        let dir = self.check_dir(ctx);
+        debug!("Building libs in %s, destination = %s", dir.to_str(),
+            destination_workspace.to_str());
+        self.build_crates(ctx, &dir, &destination_workspace, self.libs, cfgs, Lib);
         debug!("Building mains");
-        self.build_crates(ctx, &dir, self.mains, cfgs, Main);
+        self.build_crates(ctx, &dir, &destination_workspace, self.mains, cfgs, Main);
         debug!("Building tests");
-        self.build_crates(ctx, &dir, self.tests, cfgs, Test);
+        self.build_crates(ctx, &dir, &destination_workspace, self.tests, cfgs, Test);
         debug!("Building benches");
-        self.build_crates(ctx, &dir, self.benchs, cfgs, Bench);
+        self.build_crates(ctx, &dir, &destination_workspace, self.benchs, cfgs, Bench);
+        destination_workspace
     }
 }
index 467477ca479de6fe97e2aac3f2424a31c62f4ee7..af70a79f93d2be91ffdba46e606c0373175b16c4 100644 (file)
@@ -14,6 +14,7 @@
 pub use target::{OutputType, Main, Lib, Test, Bench, Target, Build, Install};
 pub use version::{Version, NoVersion, split_version_general, try_parsing_version};
 pub use rustc::metadata::filesearch::rust_path;
+use context::Ctx;
 
 use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
 use std::os::mkdir_recursive;
@@ -51,18 +52,23 @@ pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, U_RWX) }
 pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
     debug!("Checking in src dir of %s for %s",
            workspace.to_str(), pkgid.to_str());
+    workspace_contains_package_id_(pkgid, workspace, |p| { p.push("src") }).is_some()
+}
 
-    let src_dir = workspace.push("src");
+pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
+// Returns the directory it was actually found in
+             workspace_to_src_dir: &fn(&Path) -> Path) -> Option<Path> {
+    let src_dir = workspace_to_src_dir(workspace);
 
-    let mut found = false;
+    let mut found = None;
     do os::walk_dir(&src_dir) |p| {
         debug!("=> p = %s", p.to_str());
 
-        let was_found = os::path_is_dir(p) && {
+        if os::path_is_dir(p) {
             debug!("p = %s, path = %s [%s]", p.to_str(), pkgid.path.to_str(),
                    src_dir.push_rel(&pkgid.path).to_str());
 
-            *p == src_dir.push_rel(&pkgid.path) || {
+            if *p == src_dir.push_rel(&pkgid.path) || {
                 let pf = p.filename();
                 do pf.iter().any |pf| {
                     let g = pf.to_str();
@@ -76,16 +82,15 @@ pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
                         }
                     }
                 }
+            } {
+                found = Some(p.clone());
             }
-        };
 
-        if was_found {
-            found = true
-        }
+        };
         true
     };
 
-    debug!(if found { fmt!("Found %s in %s", pkgid.to_str(), workspace.to_str()) }
+    debug!(if found.is_some() { fmt!("Found %s in %s", pkgid.to_str(), workspace.to_str()) }
            else     { fmt!("Didn't find %s in %s", pkgid.to_str(), workspace.to_str()) });
     found
 }
@@ -123,8 +128,7 @@ pub fn built_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<
         Some(result)
     }
     else {
-        // This is not an error, but it's worth logging it
-        error!(fmt!("built_executable_in_workspace: %s does not exist", result.to_str()));
+        debug!("built_executable_in_workspace: %s does not exist", result.to_str());
         None
     }
 }
@@ -164,7 +168,7 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Pat
 
 /// Does the actual searching stuff
 pub fn installed_library_in_workspace(short_name: &str, workspace: &Path) -> Option<Path> {
-    // NOTE: this could break once we're handling multiple versions better... want a test for it
+    // This could break once we're handling multiple versions better -- I should add a test for it
     library_in_workspace(&Path(short_name), short_name, Install, workspace, "lib", &NoVersion)
 }
 
@@ -246,8 +250,8 @@ pub fn library_in_workspace(path: &Path, short_name: &str, where: Target,
     } // for
 
     if result_filename.is_none() {
-        warn(fmt!("library_in_workspace didn't find a library in %s for %s",
-                  dir_to_search.to_str(), short_name));
+        debug!("warning: library_in_workspace didn't find a library in %s for %s",
+                  dir_to_search.to_str(), short_name);
     }
 
     // Return the filename that matches, which we now know exists
@@ -392,3 +396,25 @@ pub fn uninstall_package_from(workspace: &Path, pkgid: &PkgId) {
     }
 
 }
+
+fn dir_has_file(dir: &Path, file: &str) -> bool {
+    assert!(dir.is_absolute());
+    os::path_exists(&dir.push(file))
+}
+
+pub fn find_dir_using_rust_path_hack(cx: &Ctx, p: &PkgId) -> Option<Path> {
+    if !cx.use_rust_path_hack {
+        return None;
+    }
+    let rp = rust_path();
+    for dir in rp.iter() {
+        debug!("In find_dir_using_rust_path_hack: checking dir %s", dir.to_str());
+        if dir_has_file(dir, "lib.rs") || dir_has_file(dir, "main.rs")
+            || dir_has_file(dir, "test.rs") || dir_has_file(dir, "bench.rs") {
+            debug!("Did find id %s in dir %s", p.to_str(), dir.to_str());
+            return Some(dir.clone());
+        }
+        debug!("Didn't find id %s in dir %s", p.to_str(), dir.to_str())
+    }
+    None
+}
index 79836bcc5554bf2819b7242f89dc6e761065f849..6a6e7569a6518577a4206a8fdde11e23dcccbddd 100644 (file)
 extern mod rustc;
 extern mod syntax;
 
-use std::result;
-use std::io;
-use std::os;
-use std::run;
-use std::str;
-
+use std::{io, os, result, run, str};
 pub use std::path::Path;
 use std::hashmap::HashMap;
 
@@ -173,7 +168,8 @@ fn hash(&self) -> ~str {
 pub trait CtxMethods {
     fn run(&self, cmd: &str, args: ~[~str]);
     fn do_cmd(&self, _cmd: &str, _pkgname: &str);
-    fn build(&self, workspace: &Path, pkgid: &PkgId);
+    /// Returns the destination workspace
+    fn build(&self, workspace: &Path, pkgid: &PkgId) -> Path;
     fn clean(&self, workspace: &Path, id: &PkgId);
     fn info(&self);
     fn install(&self, workspace: &Path, id: &PkgId);
@@ -191,15 +187,19 @@ fn run(&self, cmd: &str, args: ~[~str]) {
             "build" => {
                 if args.len() < 1 {
                     match cwd_to_workspace() {
-                        None => { usage::build(); return }
-                        Some((ws, pkgid)) => self.build(&ws, &pkgid)
+                        None if self.use_rust_path_hack => {
+                            let cwd = os::getcwd();
+                            self.build(&cwd, &PkgId::new(cwd.components[cwd.components.len() - 1]));
+                        }
+                        None => { usage::build(); return; }
+                        Some((ws, pkgid)) => { self.build(&ws, &pkgid); }
                     }
                 }
                 else {
                     // The package id is presumed to be the first command-line
                     // argument
                     let pkgid = PkgId::new(args[0].clone());
-                    do each_pkg_parent_workspace(&pkgid) |workspace| {
+                    do each_pkg_parent_workspace(self, &pkgid) |workspace| {
                         debug!("found pkg %s in workspace %s, trying to build",
                                pkgid.to_str(), workspace.to_str());
                         self.build(workspace, &pkgid);
@@ -238,15 +238,20 @@ fn run(&self, cmd: &str, args: ~[~str]) {
             "install" => {
                 if args.len() < 1 {
                     match cwd_to_workspace() {
-                        None => { usage::install(); return }
-                        Some((ws, pkgid)) => self.install(&ws, &pkgid)
-                    }
+                        None if self.use_rust_path_hack => {
+                            let cwd = os::getcwd();
+                            self.install(&cwd,
+                                &PkgId::new(cwd.components[cwd.components.len() - 1]));
+                        }
+                        None  => { usage::install(); return; }
+                        Some((ws, pkgid))                => self.install(&ws, &pkgid),
+                     }
                 }
                 else {
                     // The package id is presumed to be the first command-line
                     // argument
                     let pkgid = PkgId::new(args[0]);
-                    let workspaces = pkg_parent_workspaces(&pkgid);
+                    let workspaces = pkg_parent_workspaces(self, &pkgid);
                     debug!("package ID = %s, found it in %? workspaces",
                            pkgid.to_str(), workspaces.len());
                     if workspaces.is_empty() {
@@ -257,7 +262,7 @@ fn run(&self, cmd: &str, args: ~[~str]) {
                         self.install(&rp[0], &pkgid);
                     }
                     else {
-                        do each_pkg_parent_workspace(&pkgid) |workspace| {
+                        do each_pkg_parent_workspace(self, &pkgid) |workspace| {
                             self.install(workspace, &pkgid);
                             true
                         };
@@ -294,7 +299,7 @@ fn run(&self, cmd: &str, args: ~[~str]) {
                 else {
                     let rp = rust_path();
                     assert!(!rp.is_empty());
-                    do each_pkg_parent_workspace(&pkgid) |workspace| {
+                    do each_pkg_parent_workspace(self, &pkgid) |workspace| {
                         path_util::uninstall_package_from(workspace, &pkgid);
                         note(fmt!("Uninstalled package %s (was installed in %s)",
                                   pkgid.to_str(), workspace.to_str()));
@@ -318,7 +323,9 @@ fn do_cmd(&self, _cmd: &str, _pkgname: &str)  {
         fail!("`do` not yet implemented");
     }
 
-    fn build(&self, workspace: &Path, pkgid: &PkgId) {
+    /// Returns the destination workspace
+    /// In the case of a custom build, we don't know, so we just return the source workspace
+    fn build(&self, workspace: &Path, pkgid: &PkgId) -> Path {
         debug!("build: workspace = %s (in Rust path? %? is git dir? %? \
                 pkgid = %s", workspace.to_str(),
                in_rust_path(workspace), is_git_dir(&workspace.push_rel(&pkgid.path)),
@@ -374,9 +381,13 @@ fn build(&self, workspace: &Path, pkgid: &PkgId) {
         // the build already. Otherwise...
         if !custom {
             // Find crates inside the workspace
-            src.find_crates();
+            src.find_crates(self);
             // Build it!
-            src.build(self, cfgs);
+            src.build(self, cfgs)
+        }
+        else {
+            // Just return the source workspace
+            workspace.clone()
         }
     }
 
@@ -402,12 +413,15 @@ fn info(&self) {
     }
 
     fn install(&self, workspace: &Path, id: &PkgId)  {
-        // FIXME #7402: Use RUST_PATH to determine target dir
         // Also should use workcache to not build if not necessary.
-        self.build(workspace, id);
-        debug!("install: workspace = %s, id = %s", workspace.to_str(),
-               id.to_str());
-        self.install_no_build(workspace, id);
+        let destination_workspace = self.build(workspace, id);
+        // See #7402: This still isn't quite right yet; we want to
+        // install to the first workspace in the RUST_PATH if there's
+        // a non-default RUST_PATH. This code installs to the same
+        // workspace the package was built in.
+        debug!("install: destination workspace = %s, id = %s",
+               destination_workspace.to_str(), id.to_str());
+        self.install_no_build(&destination_workspace, id);
 
     }
 
@@ -473,7 +487,8 @@ pub fn main_args(args: &[~str]) {
     let opts = ~[getopts::optflag("h"), getopts::optflag("help"),
                  getopts::optflag("j"), getopts::optflag("json"),
                  getopts::optmulti("c"), getopts::optmulti("cfg"),
-                 getopts::optflag("v"), getopts::optflag("version")];
+                 getopts::optflag("v"), getopts::optflag("version"),
+                 getopts::optflag("r"), getopts::optflag("rust-path-hack")];
     let matches = &match getopts::getopts(args, opts) {
         result::Ok(m) => m,
         result::Err(f) => {
@@ -493,6 +508,9 @@ pub fn main_args(args: &[~str]) {
         return;
     }
 
+    let use_rust_path_hack = getopts::opt_present(matches, "r") ||
+                             getopts::opt_present(matches, "rust-path-hack");
+
     let mut args = matches.free.clone();
 
     args.shift();
@@ -501,33 +519,48 @@ pub fn main_args(args: &[~str]) {
         return usage::general();
     }
 
-    let cmd = args.shift();
-
-    if !util::is_cmd(cmd) {
-        return usage::general();
-    } else if help {
-        return match cmd {
-            ~"build" => usage::build(),
-            ~"clean" => usage::clean(),
-            ~"do" => usage::do_cmd(),
-            ~"info" => usage::info(),
-            ~"install" => usage::install(),
-            ~"list"    => usage::list(),
-            ~"prefer" => usage::prefer(),
-            ~"test" => usage::test(),
-            ~"uninstall" => usage::uninstall(),
-            ~"unprefer" => usage::unprefer(),
-            _ => usage::general()
-        };
+    let mut cmd_opt = None;
+    for a in args.iter() {
+        if util::is_cmd(*a) {
+            cmd_opt = Some(a);
+            break;
+        }
     }
+    let cmd = match cmd_opt {
+        None => return usage::general(),
+        Some(cmd) => if help {
+            return match *cmd {
+                ~"build" => usage::build(),
+                ~"clean" => usage::clean(),
+                ~"do" => usage::do_cmd(),
+                ~"info" => usage::info(),
+                ~"install" => usage::install(),
+                ~"list"    => usage::list(),
+                ~"prefer" => usage::prefer(),
+                ~"test" => usage::test(),
+                ~"uninstall" => usage::uninstall(),
+                ~"unprefer" => usage::unprefer(),
+                _ => usage::general()
+            };
+        }
+        else {
+            cmd
+        }
+    };
 
+    // Pop off all flags, plus the command
+    let remaining_args = args.iter().skip_while(|s| !util::is_cmd(**s));
+    // I had to add this type annotation to get the code to typecheck
+    let mut remaining_args: ~[~str] = remaining_args.map(|s| (*s).clone()).collect();
+    remaining_args.shift();
     let sroot = Some(@filesearch::get_or_default_sysroot());
     debug!("Using sysroot: %?", sroot);
     Ctx {
+        use_rust_path_hack: use_rust_path_hack,
         sysroot_opt: sroot, // Currently, only tests override this
         json: json,
         dep_cache: @mut HashMap::new()
-    }.run(cmd, args);
+    }.run(*cmd, remaining_args)
 }
 
 /**
index c67a81581393d977e5b5040fafbdc39237c89364..caa004a53b22879363807268745510a0926659bf 100644 (file)
@@ -89,7 +89,7 @@ pub fn git_clone_general(source: &str, target: &Path, v: &Version) -> bool {
 
 fn process_output_in_cwd(prog: &str, args: &[~str], cwd: &Path) -> ProcessOutput {
     let mut prog = Process::new(prog, args, ProcessOptions{ dir: Some(cwd)
-                                ,..ProcessOptions::new()}).unwrap();
+                                ,..ProcessOptions::new()});
     prog.finish_with_output()
 }
 
index b0d996ea0afa81d126c6644c0c888b6bbd98a374..4f8e80f56d5d7a1f89595f093d5c9e4b3d4ea6e1 100644 (file)
@@ -34,6 +34,7 @@ fn datestamp(p: &Path) -> Option<libc::time_t> {
 
 fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
     Ctx {
+        use_rust_path_hack: false,
         sysroot_opt: sysroot_opt,
         json: false,
         dep_cache: @mut HashMap::new()
@@ -70,8 +71,8 @@ fn writeFile(file_path: &Path, contents: &str) {
     out.write_line(contents);
 }
 
-fn mk_empty_workspace(short_name: &Path, version: &Version) -> Path {
-    let workspace_dir = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
+fn mk_empty_workspace(short_name: &Path, version: &Version, tag: &str) -> Path {
+    let workspace_dir = mkdtemp(&os::tmpdir(), tag).expect("couldn't create temp dir");
     mk_workspace(&workspace_dir, short_name, version);
     workspace_dir
 }
@@ -86,7 +87,7 @@ fn mk_workspace(workspace: &Path, short_name: &Path, version: &Version) -> Path
 
 fn mk_temp_workspace(short_name: &Path, version: &Version) -> Path {
     let package_dir = mk_empty_workspace(short_name,
-                                         version).push("src").push(fmt!("%s-%s",
+                          version, "temp_workspace").push("src").push(fmt!("%s-%s",
                                                             short_name.to_str(),
                                                             version.to_str()));
 
@@ -112,14 +113,13 @@ fn mk_temp_workspace(short_name: &Path, version: &Version) -> Path {
 
 fn run_git(args: &[~str], env: Option<~[(~str, ~str)]>, cwd: &Path, err_msg: &str) {
     let cwd = (*cwd).clone();
-    let prog = run::Process::new("git", args, run::ProcessOptions {
+    let mut prog = run::Process::new("git", args, run::ProcessOptions {
         env: env,
         dir: Some(&cwd),
         in_fd: None,
         out_fd: None,
         err_fd: None
     });
-    let mut prog = prog.unwrap();
     let rslt = prog.finish_with_output();
     if rslt.status != 0 {
         fail!("%s [git returned %?, output = %s, error = %s]", err_msg,
@@ -227,7 +227,7 @@ fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~s
         in_fd: None,
         out_fd: None,
         err_fd: None
-    }).unwrap();
+    });
     let output = prog.finish_with_output();
     debug!("Output from command %s with args %? was %s {%s}[%?]",
                     cmd, args, str::from_bytes(output.output),
@@ -305,29 +305,54 @@ fn create_local_package_with_custom_build_hook(pkgid: &PkgId,
 
 }
 
-fn assert_lib_exists(repo: &Path, short_name: &str, _v: Version) { // ??? version?
+fn assert_lib_exists(repo: &Path, short_name: &str, v: Version) {
+    assert!(lib_exists(repo, short_name, v));
+}
+
+fn lib_exists(repo: &Path, short_name: &str, _v: Version) -> bool { // ??? version?
     debug!("assert_lib_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
     let lib = installed_library_in_workspace(short_name, repo);
     debug!("assert_lib_exists: checking whether %? exists", lib);
-    assert!(lib.is_some());
-    let libname = lib.get_ref();
-    assert!(os::path_exists(libname));
-    assert!(is_rwx(libname));
+    lib.is_some() && {
+        let libname = lib.get_ref();
+        os::path_exists(libname) && is_rwx(libname)
+    }
 }
 
 fn assert_executable_exists(repo: &Path, short_name: &str) {
+    assert!(executable_exists(repo, short_name));
+}
+
+fn executable_exists(repo: &Path, short_name: &str) -> bool {
     debug!("assert_executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
     let exec = target_executable_in_workspace(&PkgId::new(short_name), repo);
-    assert!(os::path_exists(&exec));
-    assert!(is_rwx(&exec));
+    os::path_exists(&exec) && is_rwx(&exec)
 }
 
 fn assert_built_executable_exists(repo: &Path, short_name: &str) {
+    assert!(built_executable_exists(repo, short_name));
+}
+
+fn built_executable_exists(repo: &Path, short_name: &str) -> bool {
     debug!("assert_built_executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
-    let exec = built_executable_in_workspace(&PkgId::new(short_name),
-                                             repo).expect("assert_built_executable_exists failed");
-    assert!(os::path_exists(&exec));
-    assert!(is_rwx(&exec));
+    let exec = built_executable_in_workspace(&PkgId::new(short_name), repo);
+    exec.is_some() && {
+       let execname = exec.get_ref();
+       os::path_exists(execname) && is_rwx(execname)
+    }
+}
+
+fn assert_built_library_exists(repo: &Path, short_name: &str) {
+    assert!(built_library_exists(repo, short_name));
+}
+
+fn built_library_exists(repo: &Path, short_name: &str) -> bool {
+    debug!("assert_built_library_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
+    let lib = built_library_in_workspace(&PkgId::new(short_name), repo);
+    lib.is_some() && {
+        let libname = lib.get_ref();
+        os::path_exists(libname) && is_rwx(libname)
+    }
 }
 
 fn command_line_test_output(args: &[~str]) -> ~[~str] {
@@ -453,12 +478,14 @@ fn test_install_valid() {
 fn test_install_invalid() {
     use conditions::nonexistent_package::cond;
     use cond1 = conditions::missing_pkg_files::cond;
+    use cond2 = conditions::not_a_workspace::cond;
 
     let ctxt = fake_ctxt(None);
     let pkgid = fake_pkg();
     let temp_workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
     let mut error_occurred = false;
     let mut error1_occurred = false;
+    let mut error2_occurred = false;
     do cond1.trap(|_| {
         error1_occurred = true;
     }).inside {
@@ -466,10 +493,15 @@ fn test_install_invalid() {
             error_occurred = true;
             temp_workspace.clone()
         }).inside {
-            ctxt.install(&temp_workspace, &pkgid);
+            do cond2.trap(|_| {
+               error2_occurred = true;
+               temp_workspace.clone()
+            }).inside {
+                 ctxt.install(&temp_workspace, &pkgid);
+            }
         }
     }
-    assert!(error_occurred && error1_occurred);
+    assert!(error_occurred && error1_occurred && error2_occurred);
 }
 
 // Tests above should (maybe) be converted to shell out to rustpkg, too
@@ -1028,17 +1060,16 @@ fn test_extern_mod() {
                      test_sysroot().to_str(),
                      exec_file.to_str());
 
-    let prog = run::Process::new(rustc.to_str(), [main_file.to_str(),
-                                                  ~"--sysroot", test_sysroot().to_str(),
-                                                  ~"-o", exec_file.to_str()],
-                                 run::ProcessOptions {
+    let mut prog = run::Process::new(rustc.to_str(), [main_file.to_str(),
+                                                      ~"--sysroot", test_sysroot().to_str(),
+                                               ~"-o", exec_file.to_str()],
+                                     run::ProcessOptions {
         env: env,
         dir: Some(&dir),
         in_fd: None,
         out_fd: None,
         err_fd: None
     });
-    let mut prog = prog.unwrap();
     let outp = prog.finish_with_output();
     if outp.status != 0 {
         fail!("output was %s, error was %s",
@@ -1089,6 +1120,152 @@ fn multiple_workspaces() {
     command_line_test_with_env([~"install", ~"bar"], &c_loc, env);
 }
 
+fn rust_path_hack_test(hack_flag: bool) {
+/*
+      Make a workspace containing a pkg foo [A]
+      Make a second, empty workspace        [B]
+      Set RUST_PATH to B:A
+      rustpkg install foo
+      make sure built files for foo are in B
+      make sure nothing gets built into A or A/../build[lib,bin]
+*/
+   let p_id = PkgId::new("foo");
+   let workspace = create_local_package(&p_id);
+   let dest_workspace = mk_empty_workspace(&Path("bar"), &NoVersion, "dest_workspace");
+   let rust_path = Some(~[(~"RUST_PATH",
+       fmt!("%s:%s", dest_workspace.to_str(), workspace.push_many(["src", "foo-0.1"]).to_str()))]);
+   debug!("declare -x RUST_PATH=%s:%s",
+       dest_workspace.to_str(), workspace.push_many(["src", "foo-0.1"]).to_str());
+   command_line_test_with_env(~[~"install"] + if hack_flag { ~[~"--rust-path-hack"] } else { ~[] } +
+                               ~[~"foo"], &dest_workspace, rust_path);
+   assert_lib_exists(&dest_workspace, "foo", NoVersion);
+   assert_executable_exists(&dest_workspace, "foo");
+   assert_built_library_exists(&dest_workspace, "foo");
+   assert_built_executable_exists(&dest_workspace, "foo");
+   assert!(!lib_exists(&workspace, "foo", NoVersion));
+   assert!(!executable_exists(&workspace, "foo"));
+   assert!(!built_library_exists(&workspace, "foo"));
+   assert!(!built_executable_exists(&workspace, "foo"));
+}
+
+#[test]
+fn test_rust_path_can_contain_package_dirs_with_flag() {
+/*
+   Test that the temporary hack added for bootstrapping Servo builds
+   works. That is: if you add $FOO/src/some_pkg to the RUST_PATH,
+   it will find the sources in some_pkg, build them, and install them
+   into the first entry in the RUST_PATH.
+
+   When the hack is removed, we should change this to a should_fail test.
+*/
+   rust_path_hack_test(true);
+}
+
+#[test]
+#[should_fail]
+fn test_rust_path_can_contain_package_dirs_without_flag() {
+   rust_path_hack_test(false);
+}
+
+#[test]
+fn rust_path_hack_cwd() {
+   // Same as rust_path_hack_test, but the CWD is the dir to build out of
+   let cwd = mkdtemp(&os::tmpdir(), "pkg_files").expect("rust_path_hack_cwd");
+   writeFile(&cwd.push("lib.rs"), "pub fn f() { }");
+
+   let dest_workspace = mk_empty_workspace(&Path("bar"), &NoVersion, "dest_workspace");
+   let rust_path = Some(~[(~"RUST_PATH", dest_workspace.to_str())]);
+   debug!("declare -x RUST_PATH=%s", dest_workspace.to_str());
+   command_line_test_with_env([~"install", ~"--rust-path-hack", ~"foo"], &cwd, rust_path);
+   debug!("Checking that foo exists in %s", dest_workspace.to_str());
+   assert_lib_exists(&dest_workspace, "foo", NoVersion);
+   assert_built_library_exists(&dest_workspace, "foo");
+   assert!(!lib_exists(&cwd, "foo", NoVersion));
+   assert!(!built_library_exists(&cwd, "foo"));
+}
+
+#[test]
+fn rust_path_hack_multi_path() {
+   // Same as rust_path_hack_test, but with a more complex package ID
+   let cwd = mkdtemp(&os::tmpdir(), "pkg_files").expect("rust_path_hack_cwd");
+   let subdir = cwd.push_many([~"foo", ~"bar", ~"quux"]);
+   assert!(os::mkdir_recursive(&subdir, U_RWX));
+   writeFile(&subdir.push("lib.rs"), "pub fn f() { }");
+   let name = ~"foo/bar/quux";
+
+   let dest_workspace = mk_empty_workspace(&Path("bar"), &NoVersion, "dest_workspace");
+   let rust_path = Some(~[(~"RUST_PATH", dest_workspace.to_str())]);
+   debug!("declare -x RUST_PATH=%s", dest_workspace.to_str());
+   command_line_test_with_env([~"install", ~"--rust-path-hack", name.clone()], &subdir, rust_path);
+   debug!("Checking that %s exists in %s", name, dest_workspace.to_str());
+   assert_lib_exists(&dest_workspace, "quux", NoVersion);
+   assert_built_library_exists(&dest_workspace, name);
+   assert!(!lib_exists(&subdir, "quux", NoVersion));
+   assert!(!built_library_exists(&subdir, name));
+}
+
+#[test]
+fn rust_path_hack_install_no_arg() {
+   // Same as rust_path_hack_cwd, but making rustpkg infer the pkg id
+   let cwd = mkdtemp(&os::tmpdir(), "pkg_files").expect("rust_path_hack_install_no_arg");
+   let source_dir = cwd.push("foo");
+   assert!(make_dir_rwx(&source_dir));
+   writeFile(&source_dir.push("lib.rs"), "pub fn f() { }");
+
+   let dest_workspace = mk_empty_workspace(&Path("bar"), &NoVersion, "dest_workspace");
+   let rust_path = Some(~[(~"RUST_PATH", dest_workspace.to_str())]);
+   debug!("declare -x RUST_PATH=%s", dest_workspace.to_str());
+   command_line_test_with_env([~"install", ~"--rust-path-hack"], &source_dir, rust_path);
+   debug!("Checking that foo exists in %s", dest_workspace.to_str());
+   assert_lib_exists(&dest_workspace, "foo", NoVersion);
+   assert_built_library_exists(&dest_workspace, "foo");
+   assert!(!lib_exists(&source_dir, "foo", NoVersion));
+   assert!(!built_library_exists(&cwd, "foo"));
+}
+
+#[test]
+fn rust_path_hack_build_no_arg() {
+   // Same as rust_path_hack_install_no_arg, but building instead of installing
+   let cwd = mkdtemp(&os::tmpdir(), "pkg_files").expect("rust_path_hack_build_no_arg");
+   let source_dir = cwd.push("foo");
+   assert!(make_dir_rwx(&source_dir));
+   writeFile(&source_dir.push("lib.rs"), "pub fn f() { }");
+
+   let dest_workspace = mk_empty_workspace(&Path("bar"), &NoVersion, "dest_workspace");
+   let rust_path = Some(~[(~"RUST_PATH", dest_workspace.to_str())]);
+   debug!("declare -x RUST_PATH=%s", dest_workspace.to_str());
+   command_line_test_with_env([~"build", ~"--rust-path-hack"], &source_dir, rust_path);
+   debug!("Checking that foo exists in %s", dest_workspace.to_str());
+   assert_built_library_exists(&dest_workspace, "foo");
+   assert!(!built_library_exists(&source_dir, "foo"));
+}
+
+#[test]
+#[ignore (reason = "#7402 not yet implemented")]
+fn rust_path_install_target() {
+    let dir_for_path = mkdtemp(&os::tmpdir(),
+        "source_workspace").expect("rust_path_install_target failed");
+    let dir = mk_workspace(&dir_for_path, &Path("foo"), &NoVersion);
+    debug!("dir = %s", dir.to_str());
+    writeFile(&dir.push("main.rs"), "fn main() { let _x = (); }");
+    let dir_to_install_to = mkdtemp(&os::tmpdir(),
+        "dest_workspace").expect("rust_path_install_target failed");
+    let dir = dir.pop().pop();
+
+    let rust_path = Some(~[(~"RUST_PATH", fmt!("%s:%s", dir_to_install_to.to_str(),
+                                               dir.to_str()))]);
+    let cwd = os::getcwd();
+
+    debug!("RUST_PATH=%s:%s", dir_to_install_to.to_str(), dir.to_str());
+    command_line_test_with_env([~"install", ~"foo"],
+                               &cwd,
+                               rust_path);
+
+    assert_executable_exists(&dir_to_install_to, "foo");
+
+}
+
+
 /// Returns true if p exists and is executable
 fn is_executable(p: &Path) -> bool {
     use std::libc::consts::os::posix88::{S_IXUSR};
index 4bdb442c1e61920d98287fb985f3de1178e75dc8..958786b7cf4e20a4039e0528828f341ecf25ef9b 100644 (file)
@@ -452,6 +452,13 @@ fn test_is_cmd() {
 
 }
 
+pub fn option_to_vec<T>(x: Option<T>) -> ~[T] {
+    match x {
+       Some(y) => ~[y],
+       None    => ~[]
+    }
+}
+
 // tjc: cheesy
 fn debug_flags() -> ~[~str] { ~[] }
 // static DEBUG_FLAGS: ~[~str] = ~[~"-Z", ~"time-passes"];
index 4528a02db19785502de817c9483636c59d25f7c5..827bb415d407870be6810dec238edf1480e8dd0f 100644 (file)
@@ -40,9 +40,6 @@ fn eq(&self, other: &Version) -> bool {
             _ => false
         }
     }
-    fn ne(&self, other: &Version) -> bool {
-        !self.eq(other)
-    }
 }
 
 impl Ord for Version {
index 1afe5d513cc14e2496c84e94518200704cb9e66f..5ad2dfd6d2f4987157b9fa8202d0dbcdac36878a 100644 (file)
 
 use std::{os,util};
 use std::path::Path;
-use path_util::workspace_contains_package_id;
+use context::Ctx;
+use path_util::{workspace_contains_package_id, find_dir_using_rust_path_hack};
+use util::option_to_vec;
 use package_id::PkgId;
 
 use path_util::rust_path;
 
-pub fn each_pkg_parent_workspace(pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool {
+pub fn each_pkg_parent_workspace(cx: &Ctx, pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool {
     // Using the RUST_PATH, find workspaces that contain
     // this package ID
-    let workspaces = pkg_parent_workspaces(pkgid);
+    let workspaces = pkg_parent_workspaces(cx, pkgid);
     if workspaces.is_empty() {
         // tjc: make this a condition
         fail!("Package %s not found in any of \
@@ -36,10 +38,20 @@ pub fn each_pkg_parent_workspace(pkgid: &PkgId, action: &fn(&Path) -> bool) -> b
     return true;
 }
 
-pub fn pkg_parent_workspaces(pkgid: &PkgId) -> ~[Path] {
-    rust_path().move_iter()
+pub fn pkg_parent_workspaces(cx: &Ctx, pkgid: &PkgId) -> ~[Path] {
+    let rs: ~[Path] = rust_path().move_iter()
         .filter(|ws| workspace_contains_package_id(pkgid, ws))
-        .collect()
+        .collect();
+    if cx.use_rust_path_hack {
+        rs + option_to_vec(find_dir_using_rust_path_hack(cx, pkgid))
+    }
+    else {
+        rs
+    }
+}
+
+pub fn is_workspace(p: &Path) -> bool {
+    os::path_is_dir(&p.push("src"))
 }
 
 /// Construct a workspace and package-ID name based on the current directory.
index b8175e43fb6695cee0dab8d25799df390eaebe06..926e6e1f6b6e350212aef66d1bc01c5291da742f 100644 (file)
@@ -321,8 +321,6 @@ fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) }
 impl Eq for bool {
     #[inline]
     fn eq(&self, other: &bool) -> bool { (*self) == (*other) }
-    #[inline]
-    fn ne(&self, other: &bool) -> bool { (*self) != (*other) }
 }
 
 #[cfg(not(test))]
index e2612e0e09b46370c47b1bea5c4a917bc38c1fb6..fcfd54e814bb8a29a49788c95113cbf40a7ba38a 100644 (file)
@@ -397,8 +397,6 @@ fn encode_utf8<'a>(&self, dst: &'a mut [u8]) -> uint {
 impl Eq for char {
     #[inline]
     fn eq(&self, other: &char) -> bool { (*self) == (*other) }
-    #[inline]
-    fn ne(&self, other: &char) -> bool { (*self) != (*other) }
 }
 
 #[cfg(not(test))]
index 28d45abb6881f0dc8190c96f5a97865273f031f5..4bfcf2ce92dec7a8a77936278291a4eafa466840 100644 (file)
@@ -36,6 +36,8 @@
 #[lang="eq"]
 pub trait Eq {
     fn eq(&self, other: &Self) -> bool;
+
+    #[inline]
     fn ne(&self, other: &Self) -> bool { !self.eq(other) }
 }
 
index 6448896a489419c4ac601e6a9b3529c88feabaad..4bfa6b5afce3ec1fcdc41b41b930bef06ea2d46e 100644 (file)
@@ -595,7 +595,6 @@ fn integer(&mut self) -> Option<uint> {
 mod tests {
     use super::*;
     use prelude::*;
-    use realstd::fmt::{String};
 
     fn same(fmt: &'static str, p: ~[Piece<'static>]) {
         let mut parser = Parser::new(fmt);
index e3f88033bd06bc74296c46e91e9d7b9d97a571ee..25b94e1e45dcd902350aaf004099c63337bd1477 100644 (file)
@@ -619,7 +619,7 @@ pub trait ReaderUtil {
 
 impl<T:Reader> ReaderUtil for T {
 
-    fn read_bytes(&self,len: uint) -> ~[u8] {
+    fn read_bytes(&self, len: uint) -> ~[u8] {
         let mut bytes = vec::with_capacity(len);
         unsafe { vec::raw::set_len(&mut bytes, len); }
 
diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs
deleted file mode 100644 (file)
index ce528bc..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*! Times trait
-
-~~~ {.rust}
-use iter::Times;
-let ten = 10 as uint;
-let mut accum = 0;
-do ten.times { accum += 1; }
-~~~
-
-*/
-
-#[allow(missing_doc)]
-pub trait Times {
-    fn times(&self, it: &fn());
-}
-
index 215067ea729197c99e71c7e56609bc3a7304d277..a885a4f722789470cf9a6fe53e8c70b7f1a162ef 100644 (file)
@@ -41,16 +41,10 @@ pub fn console_off() {
 #[lang="log_type"]
 #[allow(missing_doc)]
 pub fn log_type<T>(_level: u32, object: &T) {
-    use io;
-    use repr;
-    use str;
-
-    let bytes = do io::with_bytes_writer |writer| {
-        repr::write_repr(writer, object);
-    };
+    use sys;
 
     // XXX: Bad allocation
-    let msg = str::from_bytes(bytes);
+    let msg = sys::log_str(object);
     newsched_log_str(msg);
 }
 
index 1c59eaf021969ea446b182f3723e5b8200409442..899d6236aaaaa109dc335c0f339a74c6c3ce4b7a 100644 (file)
@@ -171,8 +171,6 @@ impl Num for f32 {}
 impl Eq for f32 {
     #[inline]
     fn eq(&self, other: &f32) -> bool { (*self) == (*other) }
-    #[inline]
-    fn ne(&self, other: &f32) -> bool { (*self) != (*other) }
 }
 
 #[cfg(not(test))]
@@ -1142,6 +1140,10 @@ fn test_abs_sub() {
         assert_eq!(infinity.abs_sub(&1f32), infinity);
         assert_eq!(0f32.abs_sub(&neg_infinity), infinity);
         assert_eq!(0f32.abs_sub(&infinity), 0f32);
+    }
+
+    #[test] #[ignore(cfg(windows))] // FIXME #8663
+    fn test_abs_sub_nowin() {
         assert!(NaN.abs_sub(&-1f32).is_NaN());
         assert!(1f32.abs_sub(&NaN).is_NaN());
     }
@@ -1267,7 +1269,10 @@ fn test_frexp() {
 
         assert_eq!(0f32.frexp(), (0f32, 0));
         assert_eq!((-0f32).frexp(), (-0f32, 0));
+    }
 
+    #[test] #[ignore(cfg(windows))] // FIXME #8755
+    fn test_frexp_nowin() {
         let inf: f32 = Float::infinity();
         let neg_inf: f32 = Float::neg_infinity();
         let nan: f32 = Float::NaN();
index 8f5d6473aea2f4f3763de9c6f0790e9ed1ffb9fb..6ab8350a11544e9ea2299f3820015372c5571e75 100644 (file)
@@ -194,8 +194,6 @@ impl Num for f64 {}
 impl Eq for f64 {
     #[inline]
     fn eq(&self, other: &f64) -> bool { (*self) == (*other) }
-    #[inline]
-    fn ne(&self, other: &f64) -> bool { (*self) != (*other) }
 }
 
 #[cfg(not(test))]
@@ -1192,6 +1190,10 @@ fn test_abs_sub() {
         assert_eq!(infinity.abs_sub(&1f64), infinity);
         assert_eq!(0f64.abs_sub(&neg_infinity), infinity);
         assert_eq!(0f64.abs_sub(&infinity), 0f64);
+    }
+
+    #[test] #[ignore(cfg(windows))] // FIXME #8663
+    fn test_abs_sub_nowin() {
         assert!(NaN.abs_sub(&-1f64).is_NaN());
         assert!(1f64.abs_sub(&NaN).is_NaN());
     }
@@ -1316,7 +1318,10 @@ fn test_frexp() {
 
         assert_eq!(0f64.frexp(), (0f64, 0));
         assert_eq!((-0f64).frexp(), (-0f64, 0));
+    }
 
+    #[test] #[ignore(cfg(windows))] // FIXME #8755
+    fn test_frexp_nowin() {
         let inf: f64 = Float::infinity();
         let neg_inf: f64 = Float::neg_infinity();
         let nan: f64 = Float::NaN();
index d019de2468bdfa568699d8c76a0d8412da0ebd37..4dd6fd253333effafc654849e1ae0cb95d80c7bd 100644 (file)
@@ -331,8 +331,6 @@ impl Num for float {}
 impl Eq for float {
     #[inline]
     fn eq(&self, other: &float) -> bool { (*self) == (*other) }
-    #[inline]
-    fn ne(&self, other: &float) -> bool { (*self) != (*other) }
 }
 
 #[cfg(not(test))]
@@ -1163,6 +1161,10 @@ fn test_abs_sub() {
         assert_eq!(infinity.abs_sub(&1f), infinity);
         assert_eq!(0f.abs_sub(&neg_infinity), infinity);
         assert_eq!(0f.abs_sub(&infinity), 0f);
+    }
+
+    #[test] #[ignore(cfg(windows))] // FIXME #8663
+    fn test_abs_sub_nowin() {
         assert!(NaN.abs_sub(&-1f).is_NaN());
         assert!(1f.abs_sub(&NaN).is_NaN());
     }
@@ -1288,7 +1290,10 @@ fn test_frexp() {
 
         assert_eq!(0f.frexp(), (0f, 0));
         assert_eq!((-0f).frexp(), (-0f, 0));
+    }
 
+    #[test] #[ignore(cfg(windows))] // FIXME #8755
+    fn test_frexp_nowin() {
         let inf: float = Float::infinity();
         let neg_inf: float = Float::neg_infinity();
         let nan: float = Float::NaN();
index 6054d557fa5cd7547b556d36bd0d7fb979be2cd2..0131feda830628e698acfa36f57449079de9a1ce 100644 (file)
@@ -147,8 +147,6 @@ impl Ord for $T {
 impl Eq for $T {
     #[inline]
     fn eq(&self, other: &$T) -> bool { return (*self) == (*other); }
-    #[inline]
-    fn ne(&self, other: &$T) -> bool { return (*self) != (*other); }
 }
 
 impl Orderable for $T {
index 80ab0caac670ccdc911cabd92b808d8ad6da32ad..ac8f0022b95ec8fac04cf3986ddc6dd480898247 100644 (file)
@@ -80,6 +80,19 @@ pub trait Signed: Num
 
 pub trait Unsigned: Num {}
 
+/// Times trait
+///
+/// ~~~ {.rust}
+/// use num::Times;
+/// let ten = 10 as uint;
+/// let mut accum = 0;
+/// do ten.times { accum += 1; }
+/// ~~~
+///
+pub trait Times {
+    fn times(&self, it: &fn());
+}
+
 pub trait Integer: Num
                  + Orderable
                  + Div<Self,Self>
@@ -272,6 +285,7 @@ pub trait Primitive: Num
                    + Div<Self,Self>
                    + Rem<Self,Self> {
     // FIXME (#5527): These should be associated constants
+    // FIXME (#8888): Removing `unused_self` requires #8888 to be fixed.
     fn bits(unused_self: Option<Self>) -> uint;
     fn bytes(unused_self: Option<Self>) -> uint;
 }
@@ -314,6 +328,7 @@ pub trait Float: Real
     fn is_normal(&self) -> bool;
     fn classify(&self) -> FPCategory;
 
+    // FIXME (#8888): Removing `unused_self` requires #8888 to be fixed.
     fn mantissa_digits(unused_self: Option<Self>) -> uint;
     fn digits(unused_self: Option<Self>) -> uint;
     fn epsilon() -> Self;
index 86bc98e53fcb6605cca989137c733653f47326df..e23bdc576d36f4ffa62afad7c7f8b93dd55c0995 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Operations and constants for `uint`
 
-use iter;
+use num;
 use sys;
 
 pub use self::generated::*;
@@ -70,7 +70,7 @@ pub fn div_round(x: uint, y: uint) -> uint {
 ///
 pub fn div_floor(x: uint, y: uint) -> uint { return x / y; }
 
-impl iter::Times for uint {
+impl num::Times for uint {
     #[inline]
     ///
     /// A convenience form for basic repetition. Given a uint `x`,
@@ -162,7 +162,7 @@ fn test_div() {
 
 #[test]
 pub fn test_times() {
-    use iter::Times;
+    use num::Times;
     let ten = 10 as uint;
     let mut accum = 0;
     do ten.times { accum += 1; }
index 8ffaed22d01afd1b339030f81b29dc0115511620..1426142d46569d4f3542a6c150f9621e315ce9af 100644 (file)
@@ -148,8 +148,6 @@ fn lt(&self, other: &$T) -> bool { (*self) < (*other) }
 impl Eq for $T {
     #[inline]
     fn eq(&self, other: &$T) -> bool { return (*self) == (*other); }
-    #[inline]
-    fn ne(&self, other: &$T) -> bool { return (*self) != (*other); }
 }
 
 impl Orderable for $T {
index 7aae9425302255fdfaadac1a28a1612cdaf88096..914081627880731be515a1be690509c7459051b0 100644 (file)
@@ -1002,6 +1002,18 @@ fn unlink(p: &Path) -> bool {
     }
 }
 
+/// Renames an existing file or directory
+pub fn rename_file(old: &Path, new: &Path) -> bool {
+    #[fixed_stack_segment]; #[inline(never)];
+    unsafe {
+       do old.with_c_str |old_buf| {
+            do new.with_c_str |new_buf| {
+                libc::rename(old_buf, new_buf) == (0 as c_int)
+            }
+       }
+    }
+}
+
 #[cfg(unix)]
 /// Returns the platform-specific value of errno
 pub fn errno() -> int {
@@ -1418,12 +1430,12 @@ pub fn page_size() -> uint {
 pub fn page_size() -> uint {
     #[fixed_stack_segment]; #[inline(never)];
 
-  unsafe {
-    let mut info = libc::SYSTEM_INFO::new();
-    libc::GetSystemInfo(&mut info);
+    unsafe {
+        let mut info = libc::SYSTEM_INFO::new();
+        libc::GetSystemInfo(&mut info);
 
-    return info.dwPageSize as uint;
-  }
+        return info.dwPageSize as uint;
+    }
 }
 
 pub struct MemoryMap {
@@ -1458,7 +1470,6 @@ pub enum MapError {
     // Windows-specific errors
     ErrUnsupProt,
     ErrUnsupOffset,
-    ErrNeedRW,
     ErrAlreadyExists,
     ErrVirtualAlloc(uint),
     ErrCreateFileMappingW(uint),
@@ -1477,7 +1488,6 @@ fn to_str(&self) -> ~str {
             ErrUnknown(code) => fmt!("Unknown error=%?", code),
             ErrUnsupProt => ~"Protection mode unsupported",
             ErrUnsupOffset => ~"Offset in virtual memory mode is unsupported",
-            ErrNeedRW => ~"File mapping should be at least readable/writable",
             ErrAlreadyExists => ~"File mapping for specified file already exists",
             ErrVirtualAlloc(code) => fmt!("VirtualAlloc failure=%?", code),
             ErrCreateFileMappingW(code) => fmt!("CreateFileMappingW failure=%?", code),
@@ -1542,6 +1552,10 @@ pub fn new(min_len: uint, options: ~[MapOption]) -> Result<~MemoryMap, MapError>
             })
         }
     }
+
+    pub fn granularity() -> uint {
+        page_size()
+    }
 }
 
 #[cfg(unix)]
@@ -1617,21 +1631,21 @@ pub fn new(min_len: uint, options: ~[MapOption]) -> Result<~MemoryMap, MapError>
                 })
             }
         } else {
-            let dwDesiredAccess = match (readable, writable) {
-                (true, true) => libc::FILE_MAP_ALL_ACCESS,
-                (true, false) => libc::FILE_MAP_READ,
-                (false, true) => libc::FILE_MAP_WRITE,
-                _ => {
-                    return Err(ErrNeedRW);
-                }
+            let dwDesiredAccess = match (executable, readable, writable) {
+                (false, true, false) => libc::FILE_MAP_READ,
+                (false, true, true) => libc::FILE_MAP_WRITE,
+                (true, true, false) => libc::FILE_MAP_READ | libc::FILE_MAP_EXECUTE,
+                (true, true, true) => libc::FILE_MAP_WRITE | libc::FILE_MAP_EXECUTE,
+                _ => return Err(ErrUnsupProt) // Actually, because of the check above,
+                                              // we should never get here.
             };
             unsafe {
                 let hFile = libc::get_osfhandle(fd) as HANDLE;
                 let mapping = libc::CreateFileMappingW(hFile,
                                                        ptr::mut_null(),
                                                        flProtect,
-                                                       (len >> 32) as DWORD,
-                                                       (len & 0xffff_ffff) as DWORD,
+                                                       0,
+                                                       0,
                                                        ptr::null());
                 if mapping == ptr::mut_null() {
                     return Err(ErrCreateFileMappingW(errno()));
@@ -1641,7 +1655,7 @@ pub fn new(min_len: uint, options: ~[MapOption]) -> Result<~MemoryMap, MapError>
                 }
                 let r = libc::MapViewOfFile(mapping,
                                             dwDesiredAccess,
-                                            (offset >> 32) as DWORD,
+                                            ((len as u64) >> 32) as DWORD,
                                             (offset & 0xffff_ffff) as DWORD,
                                             0);
                 match r as uint {
@@ -1655,6 +1669,19 @@ pub fn new(min_len: uint, options: ~[MapOption]) -> Result<~MemoryMap, MapError>
             }
         }
     }
+
+    /// Granularity of MapAddr() and MapOffset() parameter values.
+    /// This may be greater than the value returned by page_size().
+    pub fn granularity() -> uint {
+        #[fixed_stack_segment]; #[inline(never)];
+
+        unsafe {
+            let mut info = libc::SYSTEM_INFO::new();
+            libc::GetSystemInfo(&mut info);
+
+            return info.dwAllocationGranularity as uint;
+        }
+    }
 }
 
 #[cfg(windows)]
@@ -1663,20 +1690,22 @@ fn drop(&self) {
         #[fixed_stack_segment]; #[inline(never)];
 
         use libc::types::os::arch::extra::{LPCVOID, HANDLE};
+        use libc::consts::os::extra::FALSE;
 
         unsafe {
             match self.kind {
-                MapVirtual => match libc::VirtualFree(self.data as *mut c_void,
-                                                      self.len,
-                                                      libc::MEM_RELEASE) {
-                    0 => error!(fmt!("VirtualFree failed: %?", errno())),
-                    _ => ()
+                MapVirtual => {
+                    if libc::VirtualFree(self.data as *mut c_void,
+                                         self.len,
+                                         libc::MEM_RELEASE) == FALSE {
+                        error!(fmt!("VirtualFree failed: %?", errno()));
+                    }
                 },
                 MapFile(mapping) => {
-                    if libc::UnmapViewOfFile(self.data as LPCVOID) != 0 {
+                    if libc::UnmapViewOfFile(self.data as LPCVOID) == FALSE {
                         error!(fmt!("UnmapViewOfFile failed: %?", errno()));
                     }
-                    if libc::CloseHandle(mapping as HANDLE) != 0 {
+                    if libc::CloseHandle(mapping as HANDLE) == FALSE {
                         error!(fmt!("CloseHandle failed: %?", errno()));
                     }
                 }
@@ -2108,7 +2137,7 @@ fn lseek_(fd: c_int, size: uint) {
         }
 
         let path = tmpdir().push("mmap_file.tmp");
-        let size = page_size() * 2;
+        let size = MemoryMap::granularity() * 2;
         remove_file(&path);
 
         let fd = unsafe {
index bfe5b498f8f1327e2edbb455bbb9f2f852e9767a..24b3dc20260b1f96edf24eb135238bc0610e9d9b 100644 (file)
@@ -49,7 +49,7 @@
 pub use char::Char;
 pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
 pub use hash::Hash;
-pub use iter::Times;
+pub use num::Times;
 pub use iterator::{FromIterator, Extendable};
 pub use iterator::{Iterator, DoubleEndedIterator, RandomAccessIterator, ClonableIterator};
 pub use iterator::{OrdIterator, MutableDoubleEndedIterator};
index 02469527b7af66a741181950c9e85c7ab0ec4ec6..38d8a244895e83cc2f8ab32edd4e46c1c7024726 100644 (file)
@@ -12,6 +12,7 @@
 
 use cast;
 use clone::Clone;
+#[cfg(not(test))]
 use cmp::Equiv;
 use iterator::{range, Iterator};
 use option::{Option, Some, None};
index 56e0f83e05cf0ea722ae87f93a52dd82f474da9a..724877db00a1763bebb0518da6ec7693f9e7be9c 100644 (file)
@@ -28,9 +28,9 @@
  * then build a MovePtrAdaptor wrapped around your struct.
  */
 pub trait MovePtr {
-    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void);
-    fn push_ptr(&self);
-    fn pop_ptr(&self);
+    fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void);
+    fn push_ptr(&mut self);
+    fn pop_ptr(&mut self);
 }
 
 /// Helper function for alignment calculation.
@@ -49,173 +49,173 @@ pub fn MovePtrAdaptor<V:TyVisitor + MovePtr>(v: V) -> MovePtrAdaptor<V> {
 
 impl<V:TyVisitor + MovePtr> MovePtrAdaptor<V> {
     #[inline]
-    pub fn bump(&self, sz: uint) {
+    pub fn bump(&mut self, sz: uint) {
         do self.inner.move_ptr() |p| {
             ((p as uint) + sz) as *c_void
         };
     }
 
     #[inline]
-    pub fn align(&self, a: uint) {
+    pub fn align(&mut self, a: uint) {
         do self.inner.move_ptr() |p| {
             align(p as uint, a) as *c_void
         };
     }
 
     #[inline]
-    pub fn align_to<T>(&self) {
+    pub fn align_to<T>(&mut self) {
         self.align(sys::min_align_of::<T>());
     }
 
     #[inline]
-    pub fn bump_past<T>(&self) {
+    pub fn bump_past<T>(&mut self) {
         self.bump(sys::size_of::<T>());
     }
 }
 
 /// Abstract type-directed pointer-movement using the MovePtr trait
 impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
-    fn visit_bot(&self) -> bool {
+    fn visit_bot(&mut self) -> bool {
         self.align_to::<()>();
         if ! self.inner.visit_bot() { return false; }
         self.bump_past::<()>();
         true
     }
 
-    fn visit_nil(&self) -> bool {
+    fn visit_nil(&mut self) -> bool {
         self.align_to::<()>();
         if ! self.inner.visit_nil() { return false; }
         self.bump_past::<()>();
         true
     }
 
-    fn visit_bool(&self) -> bool {
+    fn visit_bool(&mut self) -> bool {
         self.align_to::<bool>();
         if ! self.inner.visit_bool() { return false; }
         self.bump_past::<bool>();
         true
     }
 
-    fn visit_int(&self) -> bool {
+    fn visit_int(&mut self) -> bool {
         self.align_to::<int>();
         if ! self.inner.visit_int() { return false; }
         self.bump_past::<int>();
         true
     }
 
-    fn visit_i8(&self) -> bool {
+    fn visit_i8(&mut self) -> bool {
         self.align_to::<i8>();
         if ! self.inner.visit_i8() { return false; }
         self.bump_past::<i8>();
         true
     }
 
-    fn visit_i16(&self) -> bool {
+    fn visit_i16(&mut self) -> bool {
         self.align_to::<i16>();
         if ! self.inner.visit_i16() { return false; }
         self.bump_past::<i16>();
         true
     }
 
-    fn visit_i32(&self) -> bool {
+    fn visit_i32(&mut self) -> bool {
         self.align_to::<i32>();
         if ! self.inner.visit_i32() { return false; }
         self.bump_past::<i32>();
         true
     }
 
-    fn visit_i64(&self) -> bool {
+    fn visit_i64(&mut self) -> bool {
         self.align_to::<i64>();
         if ! self.inner.visit_i64() { return false; }
         self.bump_past::<i64>();
         true
     }
 
-    fn visit_uint(&self) -> bool {
+    fn visit_uint(&mut self) -> bool {
         self.align_to::<uint>();
         if ! self.inner.visit_uint() { return false; }
         self.bump_past::<uint>();
         true
     }
 
-    fn visit_u8(&self) -> bool {
+    fn visit_u8(&mut self) -> bool {
         self.align_to::<u8>();
         if ! self.inner.visit_u8() { return false; }
         self.bump_past::<u8>();
         true
     }
 
-    fn visit_u16(&self) -> bool {
+    fn visit_u16(&mut self) -> bool {
         self.align_to::<u16>();
         if ! self.inner.visit_u16() { return false; }
         self.bump_past::<u16>();
         true
     }
 
-    fn visit_u32(&self) -> bool {
+    fn visit_u32(&mut self) -> bool {
         self.align_to::<u32>();
         if ! self.inner.visit_u32() { return false; }
         self.bump_past::<u32>();
         true
     }
 
-    fn visit_u64(&self) -> bool {
+    fn visit_u64(&mut self) -> bool {
         self.align_to::<u64>();
         if ! self.inner.visit_u64() { return false; }
         self.bump_past::<u64>();
         true
     }
 
-    fn visit_float(&self) -> bool {
+    fn visit_float(&mut self) -> bool {
         self.align_to::<float>();
         if ! self.inner.visit_float() { return false; }
         self.bump_past::<float>();
         true
     }
 
-    fn visit_f32(&self) -> bool {
+    fn visit_f32(&mut self) -> bool {
         self.align_to::<f32>();
         if ! self.inner.visit_f32() { return false; }
         self.bump_past::<f32>();
         true
     }
 
-    fn visit_f64(&self) -> bool {
+    fn visit_f64(&mut self) -> bool {
         self.align_to::<f64>();
         if ! self.inner.visit_f64() { return false; }
         self.bump_past::<f64>();
         true
     }
 
-    fn visit_char(&self) -> bool {
+    fn visit_char(&mut self) -> bool {
         self.align_to::<char>();
         if ! self.inner.visit_char() { return false; }
         self.bump_past::<char>();
         true
     }
 
-    fn visit_estr_box(&self) -> bool {
+    fn visit_estr_box(&mut self) -> bool {
         self.align_to::<@str>();
         if ! self.inner.visit_estr_box() { return false; }
         self.bump_past::<@str>();
         true
     }
 
-    fn visit_estr_uniq(&self) -> bool {
+    fn visit_estr_uniq(&mut self) -> bool {
         self.align_to::<~str>();
         if ! self.inner.visit_estr_uniq() { return false; }
         self.bump_past::<~str>();
         true
     }
 
-    fn visit_estr_slice(&self) -> bool {
+    fn visit_estr_slice(&mut self) -> bool {
         self.align_to::<&'static str>();
         if ! self.inner.visit_estr_slice() { return false; }
         self.bump_past::<&'static str>();
         true
     }
 
-    fn visit_estr_fixed(&self, n: uint,
+    fn visit_estr_fixed(&mut self, n: uint,
                         sz: uint,
                         align: uint) -> bool {
         self.align(align);
@@ -224,83 +224,83 @@ fn visit_estr_fixed(&self, n: uint,
         true
     }
 
-    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<@u8>();
         if ! self.inner.visit_box(mtbl, inner) { return false; }
         self.bump_past::<@u8>();
         true
     }
 
-    fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~u8>();
         if ! self.inner.visit_uniq(mtbl, inner) { return false; }
         self.bump_past::<~u8>();
         true
     }
 
-    fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~u8>();
         if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
         self.bump_past::<~u8>();
         true
     }
 
-    fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<*u8>();
         if ! self.inner.visit_ptr(mtbl, inner) { return false; }
         self.bump_past::<*u8>();
         true
     }
 
-    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<&'static u8>();
         if ! self.inner.visit_rptr(mtbl, inner) { return false; }
         self.bump_past::<&'static u8>();
         true
     }
 
-    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<raw::Vec<()>>();
         if ! self.inner.visit_vec(mtbl, inner) { return false; }
         true
     }
 
-    fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~[u8]>();
         if ! self.inner.visit_vec(mtbl, inner) { return false; }
         self.bump_past::<~[u8]>();
         true
     }
 
-    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<@[u8]>();
         if ! self.inner.visit_evec_box(mtbl, inner) { return false; }
         self.bump_past::<@[u8]>();
         true
     }
 
-    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~[u8]>();
         if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; }
         self.bump_past::<~[u8]>();
         true
     }
 
-    fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~[@u8]>();
         if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; }
         self.bump_past::<~[@u8]>();
         true
     }
 
-    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<&'static [u8]>();
         if ! self.inner.visit_evec_slice(mtbl, inner) { return false; }
         self.bump_past::<&'static [u8]>();
         true
     }
 
-    fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
+    fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
                         mtbl: uint, inner: *TyDesc) -> bool {
         self.align(align);
         if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) {
@@ -310,13 +310,13 @@ fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
         true
     }
 
-    fn visit_enter_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+    fn visit_enter_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
         self.align(align);
         if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; }
         true
     }
 
-    fn visit_rec_field(&self, i: uint, name: &str,
+    fn visit_rec_field(&mut self, i: uint, name: &str,
                        mtbl: uint, inner: *TyDesc) -> bool {
         unsafe { self.align((*inner).align); }
         if ! self.inner.visit_rec_field(i, name, mtbl, inner) {
@@ -326,12 +326,12 @@ fn visit_rec_field(&self, i: uint, name: &str,
         true
     }
 
-    fn visit_leave_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+    fn visit_leave_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
         if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; }
         true
     }
 
-    fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint)
+    fn visit_enter_class(&mut self, n_fields: uint, sz: uint, align: uint)
                       -> bool {
         self.align(align);
         if ! self.inner.visit_enter_class(n_fields, sz, align) {
@@ -340,7 +340,7 @@ fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint)
         true
     }
 
-    fn visit_class_field(&self, i: uint, name: &str,
+    fn visit_class_field(&mut self, i: uint, name: &str,
                          mtbl: uint, inner: *TyDesc) -> bool {
         unsafe { self.align((*inner).align); }
         if ! self.inner.visit_class_field(i, name, mtbl, inner) {
@@ -350,7 +350,7 @@ fn visit_class_field(&self, i: uint, name: &str,
         true
     }
 
-    fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint)
+    fn visit_leave_class(&mut self, n_fields: uint, sz: uint, align: uint)
                       -> bool {
         if ! self.inner.visit_leave_class(n_fields, sz, align) {
             return false;
@@ -358,25 +358,25 @@ fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint)
         true
     }
 
-    fn visit_enter_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+    fn visit_enter_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
         self.align(align);
         if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; }
         true
     }
 
-    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool {
+    fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool {
         unsafe { self.align((*inner).align); }
         if ! self.inner.visit_tup_field(i, inner) { return false; }
         unsafe { self.bump((*inner).size); }
         true
     }
 
-    fn visit_leave_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+    fn visit_leave_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
         if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; }
         true
     }
 
-    fn visit_enter_fn(&self, purity: uint, proto: uint,
+    fn visit_enter_fn(&mut self, purity: uint, proto: uint,
                       n_inputs: uint, retstyle: uint) -> bool {
         if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) {
             return false
@@ -384,17 +384,17 @@ fn visit_enter_fn(&self, purity: uint, proto: uint,
         true
     }
 
-    fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool {
+    fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool {
         if ! self.inner.visit_fn_input(i, mode, inner) { return false; }
         true
     }
 
-    fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool {
+    fn visit_fn_output(&mut self, retstyle: uint, inner: *TyDesc) -> bool {
         if ! self.inner.visit_fn_output(retstyle, inner) { return false; }
         true
     }
 
-    fn visit_leave_fn(&self, purity: uint, proto: uint,
+    fn visit_leave_fn(&mut self, purity: uint, proto: uint,
                       n_inputs: uint, retstyle: uint) -> bool {
         if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) {
             return false;
@@ -402,7 +402,7 @@ fn visit_leave_fn(&self, purity: uint, proto: uint,
         true
     }
 
-    fn visit_enter_enum(&self, n_variants: uint,
+    fn visit_enter_enum(&mut self, n_variants: uint,
                         get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         sz: uint, align: uint)
                      -> bool {
@@ -413,7 +413,7 @@ fn visit_enter_enum(&self, n_variants: uint,
         true
     }
 
-    fn visit_enter_enum_variant(&self, variant: uint,
+    fn visit_enter_enum_variant(&mut self, variant: uint,
                                 disr_val: int,
                                 n_fields: uint,
                                 name: &str) -> bool {
@@ -424,7 +424,7 @@ fn visit_enter_enum_variant(&self, variant: uint,
         true
     }
 
-    fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool {
+    fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool {
         self.inner.push_ptr();
         self.bump(offset);
         if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; }
@@ -432,7 +432,7 @@ fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> boo
         true
     }
 
-    fn visit_leave_enum_variant(&self, variant: uint,
+    fn visit_leave_enum_variant(&mut self, variant: uint,
                                 disr_val: int,
                                 n_fields: uint,
                                 name: &str) -> bool {
@@ -443,7 +443,7 @@ fn visit_leave_enum_variant(&self, variant: uint,
         true
     }
 
-    fn visit_leave_enum(&self, n_variants: uint,
+    fn visit_leave_enum(&mut self, n_variants: uint,
                         get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         sz: uint, align: uint) -> bool {
         if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) {
@@ -453,38 +453,38 @@ fn visit_leave_enum(&self, n_variants: uint,
         true
     }
 
-    fn visit_trait(&self) -> bool {
+    fn visit_trait(&mut self) -> bool {
         self.align_to::<@TyVisitor>();
         if ! self.inner.visit_trait() { return false; }
         self.bump_past::<@TyVisitor>();
         true
     }
 
-    fn visit_param(&self, i: uint) -> bool {
+    fn visit_param(&mut self, i: uint) -> bool {
         if ! self.inner.visit_param(i) { return false; }
         true
     }
 
-    fn visit_self(&self) -> bool {
+    fn visit_self(&mut self) -> bool {
         self.align_to::<&'static u8>();
         if ! self.inner.visit_self() { return false; }
         self.align_to::<&'static u8>();
         true
     }
 
-    fn visit_type(&self) -> bool {
+    fn visit_type(&mut self) -> bool {
         if ! self.inner.visit_type() { return false; }
         true
     }
 
-    fn visit_opaque_box(&self) -> bool {
+    fn visit_opaque_box(&mut self) -> bool {
         self.align_to::<@u8>();
         if ! self.inner.visit_opaque_box() { return false; }
         self.bump_past::<@u8>();
         true
     }
 
-    fn visit_closure_ptr(&self, ck: uint) -> bool {
+    fn visit_closure_ptr(&mut self, ck: uint) -> bool {
         self.align_to::<@fn()>();
         if ! self.inner.visit_closure_ptr(ck) { return false; }
         self.bump_past::<@fn()>();
diff --git a/src/libstd/reflect_stage0.rs b/src/libstd/reflect_stage0.rs
new file mode 100644 (file)
index 0000000..56e0f83
--- /dev/null
@@ -0,0 +1,493 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+Runtime type reflection
+
+*/
+
+#[allow(missing_doc)];
+
+use unstable::intrinsics::{Opaque, TyDesc, TyVisitor};
+use libc::c_void;
+use sys;
+use unstable::raw;
+
+/**
+ * Trait for visitor that wishes to reflect on data. To use this, create a
+ * struct that encapsulates the set of pointers you wish to walk through a
+ * data structure, and implement both `MovePtr` for it as well as `TyVisitor`;
+ * then build a MovePtrAdaptor wrapped around your struct.
+ */
+pub trait MovePtr {
+    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void);
+    fn push_ptr(&self);
+    fn pop_ptr(&self);
+}
+
+/// Helper function for alignment calculation.
+#[inline]
+pub fn align(size: uint, align: uint) -> uint {
+    ((size + align) - 1u) & !(align - 1u)
+}
+
+/// Adaptor to wrap around visitors implementing MovePtr.
+pub struct MovePtrAdaptor<V> {
+    inner: V
+}
+pub fn MovePtrAdaptor<V:TyVisitor + MovePtr>(v: V) -> MovePtrAdaptor<V> {
+    MovePtrAdaptor { inner: v }
+}
+
+impl<V:TyVisitor + MovePtr> MovePtrAdaptor<V> {
+    #[inline]
+    pub fn bump(&self, sz: uint) {
+        do self.inner.move_ptr() |p| {
+            ((p as uint) + sz) as *c_void
+        };
+    }
+
+    #[inline]
+    pub fn align(&self, a: uint) {
+        do self.inner.move_ptr() |p| {
+            align(p as uint, a) as *c_void
+        };
+    }
+
+    #[inline]
+    pub fn align_to<T>(&self) {
+        self.align(sys::min_align_of::<T>());
+    }
+
+    #[inline]
+    pub fn bump_past<T>(&self) {
+        self.bump(sys::size_of::<T>());
+    }
+}
+
+/// Abstract type-directed pointer-movement using the MovePtr trait
+impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
+    fn visit_bot(&self) -> bool {
+        self.align_to::<()>();
+        if ! self.inner.visit_bot() { return false; }
+        self.bump_past::<()>();
+        true
+    }
+
+    fn visit_nil(&self) -> bool {
+        self.align_to::<()>();
+        if ! self.inner.visit_nil() { return false; }
+        self.bump_past::<()>();
+        true
+    }
+
+    fn visit_bool(&self) -> bool {
+        self.align_to::<bool>();
+        if ! self.inner.visit_bool() { return false; }
+        self.bump_past::<bool>();
+        true
+    }
+
+    fn visit_int(&self) -> bool {
+        self.align_to::<int>();
+        if ! self.inner.visit_int() { return false; }
+        self.bump_past::<int>();
+        true
+    }
+
+    fn visit_i8(&self) -> bool {
+        self.align_to::<i8>();
+        if ! self.inner.visit_i8() { return false; }
+        self.bump_past::<i8>();
+        true
+    }
+
+    fn visit_i16(&self) -> bool {
+        self.align_to::<i16>();
+        if ! self.inner.visit_i16() { return false; }
+        self.bump_past::<i16>();
+        true
+    }
+
+    fn visit_i32(&self) -> bool {
+        self.align_to::<i32>();
+        if ! self.inner.visit_i32() { return false; }
+        self.bump_past::<i32>();
+        true
+    }
+
+    fn visit_i64(&self) -> bool {
+        self.align_to::<i64>();
+        if ! self.inner.visit_i64() { return false; }
+        self.bump_past::<i64>();
+        true
+    }
+
+    fn visit_uint(&self) -> bool {
+        self.align_to::<uint>();
+        if ! self.inner.visit_uint() { return false; }
+        self.bump_past::<uint>();
+        true
+    }
+
+    fn visit_u8(&self) -> bool {
+        self.align_to::<u8>();
+        if ! self.inner.visit_u8() { return false; }
+        self.bump_past::<u8>();
+        true
+    }
+
+    fn visit_u16(&self) -> bool {
+        self.align_to::<u16>();
+        if ! self.inner.visit_u16() { return false; }
+        self.bump_past::<u16>();
+        true
+    }
+
+    fn visit_u32(&self) -> bool {
+        self.align_to::<u32>();
+        if ! self.inner.visit_u32() { return false; }
+        self.bump_past::<u32>();
+        true
+    }
+
+    fn visit_u64(&self) -> bool {
+        self.align_to::<u64>();
+        if ! self.inner.visit_u64() { return false; }
+        self.bump_past::<u64>();
+        true
+    }
+
+    fn visit_float(&self) -> bool {
+        self.align_to::<float>();
+        if ! self.inner.visit_float() { return false; }
+        self.bump_past::<float>();
+        true
+    }
+
+    fn visit_f32(&self) -> bool {
+        self.align_to::<f32>();
+        if ! self.inner.visit_f32() { return false; }
+        self.bump_past::<f32>();
+        true
+    }
+
+    fn visit_f64(&self) -> bool {
+        self.align_to::<f64>();
+        if ! self.inner.visit_f64() { return false; }
+        self.bump_past::<f64>();
+        true
+    }
+
+    fn visit_char(&self) -> bool {
+        self.align_to::<char>();
+        if ! self.inner.visit_char() { return false; }
+        self.bump_past::<char>();
+        true
+    }
+
+    fn visit_estr_box(&self) -> bool {
+        self.align_to::<@str>();
+        if ! self.inner.visit_estr_box() { return false; }
+        self.bump_past::<@str>();
+        true
+    }
+
+    fn visit_estr_uniq(&self) -> bool {
+        self.align_to::<~str>();
+        if ! self.inner.visit_estr_uniq() { return false; }
+        self.bump_past::<~str>();
+        true
+    }
+
+    fn visit_estr_slice(&self) -> bool {
+        self.align_to::<&'static str>();
+        if ! self.inner.visit_estr_slice() { return false; }
+        self.bump_past::<&'static str>();
+        true
+    }
+
+    fn visit_estr_fixed(&self, n: uint,
+                        sz: uint,
+                        align: uint) -> bool {
+        self.align(align);
+        if ! self.inner.visit_estr_fixed(n, sz, align) { return false; }
+        self.bump(sz);
+        true
+    }
+
+    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<@u8>();
+        if ! self.inner.visit_box(mtbl, inner) { return false; }
+        self.bump_past::<@u8>();
+        true
+    }
+
+    fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~u8>();
+        if ! self.inner.visit_uniq(mtbl, inner) { return false; }
+        self.bump_past::<~u8>();
+        true
+    }
+
+    fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~u8>();
+        if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
+        self.bump_past::<~u8>();
+        true
+    }
+
+    fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<*u8>();
+        if ! self.inner.visit_ptr(mtbl, inner) { return false; }
+        self.bump_past::<*u8>();
+        true
+    }
+
+    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<&'static u8>();
+        if ! self.inner.visit_rptr(mtbl, inner) { return false; }
+        self.bump_past::<&'static u8>();
+        true
+    }
+
+    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<raw::Vec<()>>();
+        if ! self.inner.visit_vec(mtbl, inner) { return false; }
+        true
+    }
+
+    fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~[u8]>();
+        if ! self.inner.visit_vec(mtbl, inner) { return false; }
+        self.bump_past::<~[u8]>();
+        true
+    }
+
+    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<@[u8]>();
+        if ! self.inner.visit_evec_box(mtbl, inner) { return false; }
+        self.bump_past::<@[u8]>();
+        true
+    }
+
+    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~[u8]>();
+        if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; }
+        self.bump_past::<~[u8]>();
+        true
+    }
+
+    fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~[@u8]>();
+        if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; }
+        self.bump_past::<~[@u8]>();
+        true
+    }
+
+    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<&'static [u8]>();
+        if ! self.inner.visit_evec_slice(mtbl, inner) { return false; }
+        self.bump_past::<&'static [u8]>();
+        true
+    }
+
+    fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
+                        mtbl: uint, inner: *TyDesc) -> bool {
+        self.align(align);
+        if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) {
+            return false;
+        }
+        self.bump(sz);
+        true
+    }
+
+    fn visit_enter_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+        self.align(align);
+        if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; }
+        true
+    }
+
+    fn visit_rec_field(&self, i: uint, name: &str,
+                       mtbl: uint, inner: *TyDesc) -> bool {
+        unsafe { self.align((*inner).align); }
+        if ! self.inner.visit_rec_field(i, name, mtbl, inner) {
+            return false;
+        }
+        unsafe { self.bump((*inner).size); }
+        true
+    }
+
+    fn visit_leave_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+        if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; }
+        true
+    }
+
+    fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint)
+                      -> bool {
+        self.align(align);
+        if ! self.inner.visit_enter_class(n_fields, sz, align) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_class_field(&self, i: uint, name: &str,
+                         mtbl: uint, inner: *TyDesc) -> bool {
+        unsafe { self.align((*inner).align); }
+        if ! self.inner.visit_class_field(i, name, mtbl, inner) {
+            return false;
+        }
+        unsafe { self.bump((*inner).size); }
+        true
+    }
+
+    fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint)
+                      -> bool {
+        if ! self.inner.visit_leave_class(n_fields, sz, align) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_enter_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+        self.align(align);
+        if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; }
+        true
+    }
+
+    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool {
+        unsafe { self.align((*inner).align); }
+        if ! self.inner.visit_tup_field(i, inner) { return false; }
+        unsafe { self.bump((*inner).size); }
+        true
+    }
+
+    fn visit_leave_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+        if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; }
+        true
+    }
+
+    fn visit_enter_fn(&self, purity: uint, proto: uint,
+                      n_inputs: uint, retstyle: uint) -> bool {
+        if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) {
+            return false
+        }
+        true
+    }
+
+    fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool {
+        if ! self.inner.visit_fn_input(i, mode, inner) { return false; }
+        true
+    }
+
+    fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool {
+        if ! self.inner.visit_fn_output(retstyle, inner) { return false; }
+        true
+    }
+
+    fn visit_leave_fn(&self, purity: uint, proto: uint,
+                      n_inputs: uint, retstyle: uint) -> bool {
+        if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_enter_enum(&self, n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        sz: uint, align: uint)
+                     -> bool {
+        self.align(align);
+        if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_enter_enum_variant(&self, variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool {
+        if ! self.inner.visit_enter_enum_variant(variant, disr_val,
+                                                 n_fields, name) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool {
+        self.inner.push_ptr();
+        self.bump(offset);
+        if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; }
+        self.inner.pop_ptr();
+        true
+    }
+
+    fn visit_leave_enum_variant(&self, variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool {
+        if ! self.inner.visit_leave_enum_variant(variant, disr_val,
+                                                 n_fields, name) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_leave_enum(&self, n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        sz: uint, align: uint) -> bool {
+        if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) {
+            return false;
+        }
+        self.bump(sz);
+        true
+    }
+
+    fn visit_trait(&self) -> bool {
+        self.align_to::<@TyVisitor>();
+        if ! self.inner.visit_trait() { return false; }
+        self.bump_past::<@TyVisitor>();
+        true
+    }
+
+    fn visit_param(&self, i: uint) -> bool {
+        if ! self.inner.visit_param(i) { return false; }
+        true
+    }
+
+    fn visit_self(&self) -> bool {
+        self.align_to::<&'static u8>();
+        if ! self.inner.visit_self() { return false; }
+        self.align_to::<&'static u8>();
+        true
+    }
+
+    fn visit_type(&self) -> bool {
+        if ! self.inner.visit_type() { return false; }
+        true
+    }
+
+    fn visit_opaque_box(&self) -> bool {
+        self.align_to::<@u8>();
+        if ! self.inner.visit_opaque_box() { return false; }
+        self.bump_past::<@u8>();
+        true
+    }
+
+    fn visit_closure_ptr(&self, ck: uint) -> bool {
+        self.align_to::<@fn()>();
+        if ! self.inner.visit_closure_ptr(ck) { return false; }
+        self.bump_past::<@fn()>();
+        true
+    }
+}
index 588010bd5b179f14a41a825d46090d055671568a..15f4c24060c0684b45731256436f39b4b887198d 100644 (file)
@@ -19,7 +19,7 @@
 use cast::transmute;
 use char;
 use container::Container;
-use io::{Writer, WriterUtil};
+use rt::io;
 use iterator::Iterator;
 use libc::c_void;
 use option::{Some, None};
 use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
 use unstable::raw;
 
-#[cfg(test)] use io;
-
-/// Helpers
-
-trait EscapedCharWriter {
-    fn write_escaped_char(&self, ch: char);
-}
-
-impl EscapedCharWriter for @Writer {
-    fn write_escaped_char(&self, ch: char) {
-        match ch {
-            '\t' => self.write_str("\\t"),
-            '\r' => self.write_str("\\r"),
-            '\n' => self.write_str("\\n"),
-            '\\' => self.write_str("\\\\"),
-            '\'' => self.write_str("\\'"),
-            '"' => self.write_str("\\\""),
-            '\x20'..'\x7e' => self.write_char(ch),
-            _ => {
-                do char::escape_unicode(ch) |c| {
-                    self.write_char(c);
-                }
-            }
-        }
-    }
-}
-
 /// Representations
 
 trait Repr {
-    fn write_repr(&self, writer: @Writer);
+    fn write_repr(&self, writer: &mut io::Writer);
 }
 
 impl Repr for () {
-    fn write_repr(&self, writer: @Writer) { writer.write_str("()"); }
+    fn write_repr(&self, writer: &mut io::Writer) {
+        writer.write("()".as_bytes());
+    }
 }
 
 impl Repr for bool {
-    fn write_repr(&self, writer: @Writer) {
-        writer.write_str(if *self { "true" } else { "false" })
+    fn write_repr(&self, writer: &mut io::Writer) {
+        let s = if *self { "true" } else { "false" };
+        writer.write(s.as_bytes())
     }
 }
 
 impl Repr for int {
-    fn write_repr(&self, writer: @Writer) {
+    fn write_repr(&self, writer: &mut io::Writer) {
         do ::int::to_str_bytes(*self, 10u) |bits| {
             writer.write(bits);
         }
@@ -84,7 +60,7 @@ fn write_repr(&self, writer: @Writer) {
 }
 
 macro_rules! int_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty {
-    fn write_repr(&self, writer: @Writer) {
+    fn write_repr(&self, writer: &mut io::Writer) {
         do ::$ty::to_str_bytes(*self, 10u) |bits| {
             writer.write(bits);
             writer.write(bytes!($suffix));
@@ -103,14 +79,14 @@ fn write_repr(&self, writer: @Writer) {
 int_repr!(u64, "u64")
 
 impl Repr for float {
-    fn write_repr(&self, writer: @Writer) {
+    fn write_repr(&self, writer: &mut io::Writer) {
         let s = self.to_str();
         writer.write(s.as_bytes());
     }
 }
 
 macro_rules! num_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty {
-    fn write_repr(&self, writer: @Writer) {
+    fn write_repr(&self, writer: &mut io::Writer) {
         let s = self.to_str();
         writer.write(s.as_bytes());
         writer.write(bytes!($suffix));
@@ -128,87 +104,97 @@ enum VariantState {
     AlreadyFound
 }
 
-pub struct ReprVisitor {
-    ptr: @mut *c_void,
-    ptr_stk: @mut ~[*c_void],
-    var_stk: @mut ~[VariantState],
-    writer: @Writer
+pub struct ReprVisitor<'self> {
+    ptr: *c_void,
+    ptr_stk: ~[*c_void],
+    var_stk: ~[VariantState],
+    writer: &'self mut io::Writer
 }
-pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor {
+
+pub fn ReprVisitor<'a>(ptr: *c_void,
+                       writer: &'a mut io::Writer) -> ReprVisitor<'a> {
     ReprVisitor {
-        ptr: @mut ptr,
-        ptr_stk: @mut ~[],
-        var_stk: @mut ~[],
+        ptr: ptr,
+        ptr_stk: ~[],
+        var_stk: ~[],
         writer: writer,
     }
 }
 
-impl MovePtr for ReprVisitor {
+impl<'self> MovePtr for ReprVisitor<'self> {
     #[inline]
-    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) {
-        *self.ptr = adjustment(*self.ptr);
+    fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void) {
+        self.ptr = adjustment(self.ptr);
     }
-    fn push_ptr(&self) {
-        self.ptr_stk.push(*self.ptr);
+    fn push_ptr(&mut self) {
+        self.ptr_stk.push(self.ptr);
     }
-    fn pop_ptr(&self) {
-        *self.ptr = self.ptr_stk.pop();
+    fn pop_ptr(&mut self) {
+        self.ptr = self.ptr_stk.pop();
     }
 }
 
-impl ReprVisitor {
+impl<'self> ReprVisitor<'self> {
     // Various helpers for the TyVisitor impl
 
     #[inline]
-    pub fn get<T>(&self, f: &fn(&T)) -> bool {
+    pub fn get<T>(&mut self, f: &fn(&mut ReprVisitor, &T)) -> bool {
         unsafe {
-            f(transmute::<*c_void,&T>(*self.ptr));
+            f(self, transmute::<*c_void,&T>(self.ptr));
         }
         true
     }
 
     #[inline]
-    pub fn visit_inner(&self, inner: *TyDesc) -> bool {
-        self.visit_ptr_inner(*self.ptr, inner)
+    pub fn visit_inner(&mut self, inner: *TyDesc) -> bool {
+        self.visit_ptr_inner(self.ptr, inner)
     }
 
     #[inline]
-    pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
+    pub fn visit_ptr_inner(&mut self, ptr: *c_void, inner: *TyDesc) -> bool {
         unsafe {
-            let u = ReprVisitor(ptr, self.writer);
-            let v = reflect::MovePtrAdaptor(u);
-            visit_tydesc(inner, &v as &TyVisitor);
+            // This should call the constructor up above, but due to limiting
+            // issues we have to recreate it here.
+            let u = ReprVisitor {
+                ptr: ptr,
+                ptr_stk: ~[],
+                var_stk: ~[],
+                writer: ::cast::transmute_copy(&self.writer),
+            };
+            let mut v = reflect::MovePtrAdaptor(u);
+            // Obviously this should not be a thing, but blame #8401 for now
+            visit_tydesc(inner, &mut v as &mut TyVisitor);
             true
         }
     }
 
     #[inline]
-    pub fn write<T:Repr>(&self) -> bool {
-        do self.get |v:&T| {
-            v.write_repr(self.writer);
+    pub fn write<T:Repr>(&mut self) -> bool {
+        do self.get |this, v:&T| {
+            v.write_repr(unsafe { ::cast::transmute_copy(&this.writer) });
         }
     }
 
-    pub fn write_escaped_slice(&self, slice: &str) {
-        self.writer.write_char('"');
+    pub fn write_escaped_slice(&mut self, slice: &str) {
+        self.writer.write(['"' as u8]);
         for ch in slice.iter() {
-            self.writer.write_escaped_char(ch);
+            self.write_escaped_char(ch);
         }
-        self.writer.write_char('"');
+        self.writer.write(['"' as u8]);
     }
 
-    pub fn write_mut_qualifier(&self, mtbl: uint) {
+    pub fn write_mut_qualifier(&mut self, mtbl: uint) {
         if mtbl == 0 {
-            self.writer.write_str("mut ");
+            self.writer.write("mut ".as_bytes());
         } else if mtbl == 1 {
             // skip, this is ast::m_imm
         } else {
             assert_eq!(mtbl, 2);
-            self.writer.write_str("const ");
+            self.writer.write("const ".as_bytes());
         }
     }
 
-    pub fn write_vec_range(&self,
+    pub fn write_vec_range(&mut self,
                            _mtbl: uint,
                            ptr: *(),
                            len: uint,
@@ -216,7 +202,7 @@ pub fn write_vec_range(&self,
                            -> bool {
         let mut p = ptr as *u8;
         let (sz, al) = unsafe { ((*inner).size, (*inner).align) };
-        self.writer.write_char('[');
+        self.writer.write(['[' as u8]);
         let mut first = true;
         let mut left = len;
         // unit structs have 0 size, and don't loop forever.
@@ -225,17 +211,17 @@ pub fn write_vec_range(&self,
             if first {
                 first = false;
             } else {
-                self.writer.write_str(", ");
+                self.writer.write(", ".as_bytes());
             }
             self.visit_ptr_inner(p as *c_void, inner);
             p = align(unsafe { ptr::offset(p, sz as int) as uint }, al) as *u8;
             left -= dec;
         }
-        self.writer.write_char(']');
+        self.writer.write([']' as u8]);
         true
     }
 
-    pub fn write_unboxed_vec_repr(&self,
+    pub fn write_unboxed_vec_repr(&mut self,
                                   mtbl: uint,
                                   v: &raw::Vec<()>,
                                   inner: *TyDesc)
@@ -243,239 +229,246 @@ pub fn write_unboxed_vec_repr(&self,
         self.write_vec_range(mtbl, ptr::to_unsafe_ptr(&v.data),
                              v.fill, inner)
     }
+
+    fn write_escaped_char(&mut self, ch: char) {
+        match ch {
+            '\t' => self.writer.write("\\t".as_bytes()),
+            '\r' => self.writer.write("\\r".as_bytes()),
+            '\n' => self.writer.write("\\n".as_bytes()),
+            '\\' => self.writer.write("\\\\".as_bytes()),
+            '\'' => self.writer.write("\\'".as_bytes()),
+            '"' => self.writer.write("\\\"".as_bytes()),
+            '\x20'..'\x7e' => self.writer.write([ch as u8]),
+            _ => {
+                do char::escape_unicode(ch) |c| {
+                    self.writer.write([c as u8]);
+                }
+            }
+        }
+    }
 }
 
-impl TyVisitor for ReprVisitor {
-    fn visit_bot(&self) -> bool {
-        self.writer.write_str("!");
+impl<'self> TyVisitor for ReprVisitor<'self> {
+    fn visit_bot(&mut self) -> bool {
+        self.writer.write("!".as_bytes());
         true
     }
-    fn visit_nil(&self) -> bool { self.write::<()>() }
-    fn visit_bool(&self) -> bool { self.write::<bool>() }
-    fn visit_int(&self) -> bool { self.write::<int>() }
-    fn visit_i8(&self) -> bool { self.write::<i8>() }
-    fn visit_i16(&self) -> bool { self.write::<i16>() }
-    fn visit_i32(&self) -> bool { self.write::<i32>()  }
-    fn visit_i64(&self) -> bool { self.write::<i64>() }
+    fn visit_nil(&mut self) -> bool { self.write::<()>() }
+    fn visit_bool(&mut self) -> bool { self.write::<bool>() }
+    fn visit_int(&mut self) -> bool { self.write::<int>() }
+    fn visit_i8(&mut self) -> bool { self.write::<i8>() }
+    fn visit_i16(&mut self) -> bool { self.write::<i16>() }
+    fn visit_i32(&mut self) -> bool { self.write::<i32>()  }
+    fn visit_i64(&mut self) -> bool { self.write::<i64>() }
 
-    fn visit_uint(&self) -> bool { self.write::<uint>() }
-    fn visit_u8(&self) -> bool { self.write::<u8>() }
-    fn visit_u16(&self) -> bool { self.write::<u16>() }
-    fn visit_u32(&self) -> bool { self.write::<u32>() }
-    fn visit_u64(&self) -> bool { self.write::<u64>() }
+    fn visit_uint(&mut self) -> bool { self.write::<uint>() }
+    fn visit_u8(&mut self) -> bool { self.write::<u8>() }
+    fn visit_u16(&mut self) -> bool { self.write::<u16>() }
+    fn visit_u32(&mut self) -> bool { self.write::<u32>() }
+    fn visit_u64(&mut self) -> bool { self.write::<u64>() }
 
-    fn visit_float(&self) -> bool { self.write::<float>() }
-    fn visit_f32(&self) -> bool { self.write::<f32>() }
-    fn visit_f64(&self) -> bool { self.write::<f64>() }
+    fn visit_float(&mut self) -> bool { self.write::<float>() }
+    fn visit_f32(&mut self) -> bool { self.write::<f32>() }
+    fn visit_f64(&mut self) -> bool { self.write::<f64>() }
 
-    fn visit_char(&self) -> bool {
-        do self.get::<char> |&ch| {
-            self.writer.write_char('\'');
-            self.writer.write_escaped_char(ch);
-            self.writer.write_char('\'');
+    fn visit_char(&mut self) -> bool {
+        do self.get::<char> |this, &ch| {
+            this.writer.write(['\'' as u8]);
+            this.write_escaped_char(ch);
+            this.writer.write(['\'' as u8]);
         }
     }
 
-    fn visit_estr_box(&self) -> bool {
-        do self.get::<@str> |s| {
-            self.writer.write_char('@');
-            self.write_escaped_slice(*s);
+    fn visit_estr_box(&mut self) -> bool {
+        do self.get::<@str> |this, s| {
+            this.writer.write(['@' as u8]);
+            this.write_escaped_slice(*s);
         }
     }
 
-    fn visit_estr_uniq(&self) -> bool {
-        do self.get::<~str> |s| {
-            self.writer.write_char('~');
-            self.write_escaped_slice(*s);
+    fn visit_estr_uniq(&mut self) -> bool {
+        do self.get::<~str> |this, s| {
+            this.writer.write(['~' as u8]);
+            this.write_escaped_slice(*s);
         }
     }
 
-    fn visit_estr_slice(&self) -> bool {
-        do self.get::<&str> |s| {
-            self.write_escaped_slice(*s);
+    fn visit_estr_slice(&mut self) -> bool {
+        do self.get::<&str> |this, s| {
+            this.write_escaped_slice(*s);
         }
     }
 
     // Type no longer exists, vestigial function.
-    fn visit_estr_fixed(&self, _n: uint, _sz: uint,
+    fn visit_estr_fixed(&mut self, _n: uint, _sz: uint,
                         _align: uint) -> bool { fail!(); }
 
-    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.writer.write_char('@');
+    fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write(['@' as u8]);
         self.write_mut_qualifier(mtbl);
-        do self.get::<&raw::Box<()>> |b| {
+        do self.get::<&raw::Box<()>> |this, b| {
             let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
-            self.visit_ptr_inner(p, inner);
+            this.visit_ptr_inner(p, inner);
         }
     }
 
-    fn visit_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool {
-        self.writer.write_char('~');
-        do self.get::<*c_void> |b| {
-            self.visit_ptr_inner(*b, inner);
+    fn visit_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write(['~' as u8]);
+        do self.get::<*c_void> |this, b| {
+            this.visit_ptr_inner(*b, inner);
         }
     }
 
-    fn visit_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool {
-        self.writer.write_char('~');
-        do self.get::<&raw::Box<()>> |b| {
+    fn visit_uniq_managed(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write(['~' as u8]);
+        do self.get::<&raw::Box<()>> |this, b| {
             let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
-            self.visit_ptr_inner(p, inner);
+            this.visit_ptr_inner(p, inner);
         }
     }
 
-    #[cfg(stage0)]
-    fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool {
-        do self.get::<*c_void> |p| {
-            self.writer.write_str(fmt!("(0x%x as *())",
-                                       *p as uint));
+    fn visit_ptr(&mut self, mtbl: uint, _inner: *TyDesc) -> bool {
+        do self.get::<*c_void> |this, p| {
+            write!(this.writer, "({} as *", *p);
+            this.write_mut_qualifier(mtbl);
+            this.writer.write("())".as_bytes());
         }
     }
 
-    #[cfg(not(stage0))]
-    fn visit_ptr(&self, mtbl: uint, _inner: *TyDesc) -> bool {
-        do self.get::<*c_void> |p| {
-            self.writer.write_str(fmt!("(0x%x as *", *p as uint));
-            self.write_mut_qualifier(mtbl);
-            self.writer.write_str("())");
-        }
-    }
-
-    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.writer.write_char('&');
+    fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write(['&' as u8]);
         self.write_mut_qualifier(mtbl);
-        do self.get::<*c_void> |p| {
-            self.visit_ptr_inner(*p, inner);
+        do self.get::<*c_void> |this, p| {
+            this.visit_ptr_inner(*p, inner);
         }
     }
 
     // Type no longer exists, vestigial function.
-    fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { fail!(); }
+    fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { fail!(); }
 
 
-    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<raw::Vec<()>> |b| {
-            self.write_unboxed_vec_repr(mtbl, b, inner);
+    fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<raw::Vec<()>> |this, b| {
+            this.write_unboxed_vec_repr(mtbl, b, inner);
         }
     }
 
-    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<&raw::Box<raw::Vec<()>>> |b| {
-            self.writer.write_char('@');
-            self.write_mut_qualifier(mtbl);
-            self.write_unboxed_vec_repr(mtbl, &b.data, inner);
+    fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<&raw::Box<raw::Vec<()>>> |this, b| {
+            this.writer.write(['@' as u8]);
+            this.write_mut_qualifier(mtbl);
+            this.write_unboxed_vec_repr(mtbl, &b.data, inner);
         }
     }
 
-    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<&raw::Vec<()>> |b| {
-            self.writer.write_char('~');
-            self.write_unboxed_vec_repr(mtbl, *b, inner);
+    fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<&raw::Vec<()>> |this, b| {
+            this.writer.write(['~' as u8]);
+            this.write_unboxed_vec_repr(mtbl, *b, inner);
         }
     }
 
-    fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<&raw::Box<raw::Vec<()>>> |b| {
-            self.writer.write_char('~');
-            self.write_unboxed_vec_repr(mtbl, &b.data, inner);
+    fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<&raw::Box<raw::Vec<()>>> |this, b| {
+            this.writer.write(['~' as u8]);
+            this.write_unboxed_vec_repr(mtbl, &b.data, inner);
         }
     }
 
-    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<raw::Slice<()>> |s| {
-            self.writer.write_char('&');
-            self.write_vec_range(mtbl, s.data, s.len, inner);
+    fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<raw::Slice<()>> |this, s| {
+            this.writer.write(['&' as u8]);
+            this.write_vec_range(mtbl, s.data, s.len, inner);
         }
     }
 
-    fn visit_evec_fixed(&self, _n: uint, sz: uint, _align: uint,
+    fn visit_evec_fixed(&mut self, _n: uint, sz: uint, _align: uint,
                         mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<()> |b| {
-            self.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), sz, inner);
+        do self.get::<()> |this, b| {
+            this.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), sz, inner);
         }
     }
 
-    fn visit_enter_rec(&self, _n_fields: uint,
+    fn visit_enter_rec(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('{');
+        self.writer.write(['{' as u8]);
         true
     }
 
-    fn visit_rec_field(&self, i: uint, name: &str,
+    fn visit_rec_field(&mut self, i: uint, name: &str,
                        mtbl: uint, inner: *TyDesc) -> bool {
         if i != 0 {
-            self.writer.write_str(", ");
+            self.writer.write(", ".as_bytes());
         }
         self.write_mut_qualifier(mtbl);
-        self.writer.write_str(name);
-        self.writer.write_str(": ");
+        self.writer.write(name.as_bytes());
+        self.writer.write(": ".as_bytes());
         self.visit_inner(inner);
         true
     }
 
-    fn visit_leave_rec(&self, _n_fields: uint,
+    fn visit_leave_rec(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('}');
+        self.writer.write(['}' as u8]);
         true
     }
 
-    fn visit_enter_class(&self, _n_fields: uint,
+    fn visit_enter_class(&mut self, _n_fields: uint,
                          _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('{');
+        self.writer.write(['{' as u8]);
         true
     }
-    fn visit_class_field(&self, i: uint, name: &str,
+    fn visit_class_field(&mut self, i: uint, name: &str,
                          mtbl: uint, inner: *TyDesc) -> bool {
         if i != 0 {
-            self.writer.write_str(", ");
+            self.writer.write(", ".as_bytes());
         }
         self.write_mut_qualifier(mtbl);
-        self.writer.write_str(name);
-        self.writer.write_str(": ");
+        self.writer.write(name.as_bytes());
+        self.writer.write(": ".as_bytes());
         self.visit_inner(inner);
         true
     }
-    fn visit_leave_class(&self, _n_fields: uint,
+    fn visit_leave_class(&mut self, _n_fields: uint,
                          _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('}');
+        self.writer.write(['}' as u8]);
         true
     }
 
-    fn visit_enter_tup(&self, _n_fields: uint,
+    fn visit_enter_tup(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('(');
+        self.writer.write(['(' as u8]);
         true
     }
-    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool {
+    fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool {
         if i != 0 {
-            self.writer.write_str(", ");
+            self.writer.write(", ".as_bytes());
         }
         self.visit_inner(inner);
         true
     }
-    fn visit_leave_tup(&self, _n_fields: uint,
+    fn visit_leave_tup(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool {
         if _n_fields == 1 {
-            self.writer.write_char(',');
+            self.writer.write([',' as u8]);
         }
-        self.writer.write_char(')');
+        self.writer.write([')' as u8]);
         true
     }
 
-    fn visit_enter_enum(&self,
+    fn visit_enter_enum(&mut self,
                         _n_variants: uint,
                         get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         _sz: uint,
                         _align: uint) -> bool {
-        let var_stk: &mut ~[VariantState] = self.var_stk;
         let disr = unsafe {
-            get_disr(transmute(*self.ptr))
+            get_disr(transmute(self.ptr))
         };
-        var_stk.push(SearchingFor(disr));
+        self.var_stk.push(SearchingFor(disr));
         true
     }
 
-    fn visit_enter_enum_variant(&self, _variant: uint,
+    fn visit_enter_enum_variant(&mut self, _variant: uint,
                                 disr_val: int,
                                 n_fields: uint,
                                 name: &str) -> bool {
@@ -495,15 +488,15 @@ fn visit_enter_enum_variant(&self, _variant: uint,
         }
 
         if write {
-            self.writer.write_str(name);
+            self.writer.write(name.as_bytes());
             if n_fields > 0 {
-                self.writer.write_char('(');
+                self.writer.write(['(' as u8]);
             }
         }
         true
     }
 
-    fn visit_enum_variant_field(&self,
+    fn visit_enum_variant_field(&mut self,
                                 i: uint,
                                 _offset: uint,
                                 inner: *TyDesc)
@@ -511,7 +504,7 @@ fn visit_enum_variant_field(&self,
         match self.var_stk[self.var_stk.len() - 1] {
             Matched => {
                 if i != 0 {
-                    self.writer.write_str(", ");
+                    self.writer.write(", ".as_bytes());
                 }
                 if ! self.visit_inner(inner) {
                     return false;
@@ -522,14 +515,14 @@ fn visit_enum_variant_field(&self,
         true
     }
 
-    fn visit_leave_enum_variant(&self, _variant: uint,
+    fn visit_leave_enum_variant(&mut self, _variant: uint,
                                 _disr_val: int,
                                 n_fields: uint,
                                 _name: &str) -> bool {
         match self.var_stk[self.var_stk.len() - 1] {
             Matched => {
                 if n_fields > 0 {
-                    self.writer.write_char(')');
+                    self.writer.write([')' as u8]);
                 }
             }
             _ => ()
@@ -537,54 +530,53 @@ fn visit_leave_enum_variant(&self, _variant: uint,
         true
     }
 
-    fn visit_leave_enum(&self,
+    fn visit_leave_enum(&mut self,
                         _n_variants: uint,
                         _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         _sz: uint,
                         _align: uint)
                         -> bool {
-        let var_stk: &mut ~[VariantState] = self.var_stk;
-        match var_stk.pop() {
+        match self.var_stk.pop() {
             SearchingFor(*) => fail!("enum value matched no variant"),
             _ => true
         }
     }
 
-    fn visit_enter_fn(&self, _purity: uint, _proto: uint,
+    fn visit_enter_fn(&mut self, _purity: uint, _proto: uint,
                       _n_inputs: uint, _retstyle: uint) -> bool { true }
-    fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool {
+    fn visit_fn_input(&mut self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool {
         true
     }
-    fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool {
+    fn visit_fn_output(&mut self, _retstyle: uint, _inner: *TyDesc) -> bool {
         true
     }
-    fn visit_leave_fn(&self, _purity: uint, _proto: uint,
+    fn visit_leave_fn(&mut self, _purity: uint, _proto: uint,
                       _n_inputs: uint, _retstyle: uint) -> bool { true }
 
 
-    fn visit_trait(&self) -> bool { true }
-    fn visit_param(&self, _i: uint) -> bool { true }
-    fn visit_self(&self) -> bool { true }
-    fn visit_type(&self) -> bool { true }
+    fn visit_trait(&mut self) -> bool { true }
+    fn visit_param(&mut self, _i: uint) -> bool { true }
+    fn visit_self(&mut self) -> bool { true }
+    fn visit_type(&mut self) -> bool { true }
 
-    fn visit_opaque_box(&self) -> bool {
-        self.writer.write_char('@');
-        do self.get::<&raw::Box<()>> |b| {
+    fn visit_opaque_box(&mut self) -> bool {
+        self.writer.write(['@' as u8]);
+        do self.get::<&raw::Box<()>> |this, b| {
             let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
-            self.visit_ptr_inner(p, b.type_desc);
+            this.visit_ptr_inner(p, b.type_desc);
         }
     }
 
-    fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
+    fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true }
 }
 
-pub fn write_repr<T>(writer: @Writer, object: &T) {
+pub fn write_repr<T>(writer: &mut io::Writer, object: &T) {
     unsafe {
         let ptr = ptr::to_unsafe_ptr(object) as *c_void;
         let tydesc = get_tydesc::<T>();
         let u = ReprVisitor(ptr, writer);
-        let v = reflect::MovePtrAdaptor(u);
-        visit_tydesc(tydesc, &v as &TyVisitor)
+        let mut v = reflect::MovePtrAdaptor(u);
+        visit_tydesc(tydesc, &mut v as &mut TyVisitor);
     }
 }
 
@@ -593,14 +585,15 @@ struct P {a: int, b: float}
 
 #[test]
 fn test_repr() {
+    use str;
+    use str::Str;
+    use rt::io::Decorator;
 
     fn exact_test<T>(t: &T, e:&str) {
-        let s : &str = io::with_str_writer(|w| write_repr(w, t));
-        if s != e {
-            error!("expected '%s', got '%s'",
-                   e, s);
-        }
-        assert_eq!(s, e);
+        let mut m = io::mem::MemWriter::new();
+        write_repr(&mut m as &mut io::Writer, t);
+        let s = str::from_bytes_owned(m.inner());
+        assert_eq!(s.as_slice(), e);
     }
 
     exact_test(&10, "10");
diff --git a/src/libstd/repr_stage0.rs b/src/libstd/repr_stage0.rs
new file mode 100644 (file)
index 0000000..4e580d9
--- /dev/null
@@ -0,0 +1,626 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+More runtime type reflection
+
+*/
+
+#[allow(missing_doc)];
+
+use cast::transmute;
+use char;
+use container::Container;
+use io::{Writer, WriterUtil};
+use iterator::Iterator;
+use libc::c_void;
+use option::{Some, None};
+use ptr;
+use reflect;
+use reflect::{MovePtr, align};
+use str::StrSlice;
+use to_str::ToStr;
+use vec::OwnedVector;
+use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
+use unstable::raw;
+
+#[cfg(test)] use io;
+
+/// Helpers
+
+trait EscapedCharWriter {
+    fn write_escaped_char(&self, ch: char);
+}
+
+impl EscapedCharWriter for @Writer {
+    fn write_escaped_char(&self, ch: char) {
+        match ch {
+            '\t' => self.write_str("\\t"),
+            '\r' => self.write_str("\\r"),
+            '\n' => self.write_str("\\n"),
+            '\\' => self.write_str("\\\\"),
+            '\'' => self.write_str("\\'"),
+            '"' => self.write_str("\\\""),
+            '\x20'..'\x7e' => self.write_char(ch),
+            _ => {
+                do char::escape_unicode(ch) |c| {
+                    self.write_char(c);
+                }
+            }
+        }
+    }
+}
+
+/// Representations
+
+trait Repr {
+    fn write_repr(&self, writer: @Writer);
+}
+
+impl Repr for () {
+    fn write_repr(&self, writer: @Writer) { writer.write_str("()"); }
+}
+
+impl Repr for bool {
+    fn write_repr(&self, writer: @Writer) {
+        writer.write_str(if *self { "true" } else { "false" })
+    }
+}
+
+macro_rules! int_repr(($ty:ident) => (impl Repr for $ty {
+    fn write_repr(&self, writer: @Writer) {
+        do ::$ty::to_str_bytes(*self, 10u) |bits| {
+            writer.write(bits);
+        }
+    }
+}))
+
+int_repr!(int)
+int_repr!(i8)
+int_repr!(i16)
+int_repr!(i32)
+int_repr!(i64)
+int_repr!(uint)
+int_repr!(u8)
+int_repr!(u16)
+int_repr!(u32)
+int_repr!(u64)
+
+macro_rules! num_repr(($ty:ident) => (impl Repr for $ty {
+    fn write_repr(&self, writer: @Writer) {
+        let s = self.to_str();
+        writer.write(s.as_bytes());
+    }
+}))
+
+num_repr!(float)
+num_repr!(f32)
+num_repr!(f64)
+
+// New implementation using reflect::MovePtr
+
+enum VariantState {
+    SearchingFor(int),
+    Matched,
+    AlreadyFound
+}
+
+pub struct ReprVisitor {
+    ptr: @mut *c_void,
+    ptr_stk: @mut ~[*c_void],
+    var_stk: @mut ~[VariantState],
+    writer: @Writer
+}
+pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor {
+    ReprVisitor {
+        ptr: @mut ptr,
+        ptr_stk: @mut ~[],
+        var_stk: @mut ~[],
+        writer: writer,
+    }
+}
+
+impl MovePtr for ReprVisitor {
+    #[inline]
+    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) {
+        *self.ptr = adjustment(*self.ptr);
+    }
+    fn push_ptr(&self) {
+        self.ptr_stk.push(*self.ptr);
+    }
+    fn pop_ptr(&self) {
+        *self.ptr = self.ptr_stk.pop();
+    }
+}
+
+impl ReprVisitor {
+    // Various helpers for the TyVisitor impl
+
+    #[inline]
+    pub fn get<T>(&self, f: &fn(&T)) -> bool {
+        unsafe {
+            f(transmute::<*c_void,&T>(*self.ptr));
+        }
+        true
+    }
+
+    #[inline]
+    pub fn visit_inner(&self, inner: *TyDesc) -> bool {
+        self.visit_ptr_inner(*self.ptr, inner)
+    }
+
+    #[inline]
+    pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
+        unsafe {
+            let u = ReprVisitor(ptr, self.writer);
+            let v = reflect::MovePtrAdaptor(u);
+            visit_tydesc(inner, @v as @TyVisitor);
+            true
+        }
+    }
+
+    #[inline]
+    pub fn write<T:Repr>(&self) -> bool {
+        do self.get |v:&T| {
+            v.write_repr(self.writer);
+        }
+    }
+
+    pub fn write_escaped_slice(&self, slice: &str) {
+        self.writer.write_char('"');
+        for ch in slice.iter() {
+            self.writer.write_escaped_char(ch);
+        }
+        self.writer.write_char('"');
+    }
+
+    pub fn write_mut_qualifier(&self, mtbl: uint) {
+        if mtbl == 0 {
+            self.writer.write_str("mut ");
+        } else if mtbl == 1 {
+            // skip, this is ast::m_imm
+        } else {
+            assert_eq!(mtbl, 2);
+            self.writer.write_str("const ");
+        }
+    }
+
+    pub fn write_vec_range(&self,
+                           _mtbl: uint,
+                           ptr: *(),
+                           len: uint,
+                           inner: *TyDesc)
+                           -> bool {
+        let mut p = ptr as *u8;
+        let (sz, al) = unsafe { ((*inner).size, (*inner).align) };
+        self.writer.write_char('[');
+        let mut first = true;
+        let mut left = len;
+        // unit structs have 0 size, and don't loop forever.
+        let dec = if sz == 0 {1} else {sz};
+        while left > 0 {
+            if first {
+                first = false;
+            } else {
+                self.writer.write_str(", ");
+            }
+            self.visit_ptr_inner(p as *c_void, inner);
+            unsafe {
+                p = align(ptr::offset(p, sz as int) as uint, al) as *u8;
+            }
+            left -= dec;
+        }
+        self.writer.write_char(']');
+        true
+    }
+
+    pub fn write_unboxed_vec_repr(&self,
+                                  mtbl: uint,
+                                  v: &raw::Vec<()>,
+                                  inner: *TyDesc)
+                                  -> bool {
+        self.write_vec_range(mtbl, ptr::to_unsafe_ptr(&v.data),
+                             v.fill, inner)
+    }
+}
+
+impl TyVisitor for ReprVisitor {
+    fn visit_bot(&self) -> bool {
+        self.writer.write_str("!");
+        true
+    }
+    fn visit_nil(&self) -> bool { self.write::<()>() }
+    fn visit_bool(&self) -> bool { self.write::<bool>() }
+    fn visit_int(&self) -> bool { self.write::<int>() }
+    fn visit_i8(&self) -> bool { self.write::<i8>() }
+    fn visit_i16(&self) -> bool { self.write::<i16>() }
+    fn visit_i32(&self) -> bool { self.write::<i32>()  }
+    fn visit_i64(&self) -> bool { self.write::<i64>() }
+
+    fn visit_uint(&self) -> bool { self.write::<uint>() }
+    fn visit_u8(&self) -> bool { self.write::<u8>() }
+    fn visit_u16(&self) -> bool { self.write::<u16>() }
+    fn visit_u32(&self) -> bool { self.write::<u32>() }
+    fn visit_u64(&self) -> bool { self.write::<u64>() }
+
+    fn visit_float(&self) -> bool { self.write::<float>() }
+    fn visit_f32(&self) -> bool { self.write::<f32>() }
+    fn visit_f64(&self) -> bool { self.write::<f64>() }
+
+    fn visit_char(&self) -> bool {
+        do self.get::<char> |&ch| {
+            self.writer.write_char('\'');
+            self.writer.write_escaped_char(ch);
+            self.writer.write_char('\'');
+        }
+    }
+
+    fn visit_estr_box(&self) -> bool {
+        do self.get::<@str> |s| {
+            self.writer.write_char('@');
+            self.write_escaped_slice(*s);
+        }
+    }
+    fn visit_estr_uniq(&self) -> bool {
+        do self.get::<~str> |s| {
+            self.writer.write_char('~');
+            self.write_escaped_slice(*s);
+        }
+    }
+    fn visit_estr_slice(&self) -> bool {
+        do self.get::<&str> |s| {
+            self.write_escaped_slice(*s);
+        }
+    }
+
+    // Type no longer exists, vestigial function.
+    fn visit_estr_fixed(&self, _n: uint, _sz: uint,
+                        _align: uint) -> bool { fail!(); }
+
+    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write_char('@');
+        self.write_mut_qualifier(mtbl);
+        do self.get::<&raw::Box<()>> |b| {
+            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
+            self.visit_ptr_inner(p, inner);
+        }
+    }
+
+    fn visit_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write_char('~');
+        do self.get::<*c_void> |b| {
+            self.visit_ptr_inner(*b, inner);
+        }
+    }
+
+    fn visit_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write_char('~');
+        do self.get::<&raw::Box<()>> |b| {
+            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
+            self.visit_ptr_inner(p, inner);
+        }
+    }
+
+    fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool {
+        do self.get::<*c_void> |p| {
+            self.writer.write_str(fmt!("(0x%x as *())",
+                                       *p as uint));
+        }
+    }
+
+    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write_char('&');
+        self.write_mut_qualifier(mtbl);
+        do self.get::<*c_void> |p| {
+            self.visit_ptr_inner(*p, inner);
+        }
+    }
+
+    // Type no longer exists, vestigial function.
+    fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { fail!(); }
+
+
+    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<raw::Vec<()>> |b| {
+            self.write_unboxed_vec_repr(mtbl, b, inner);
+        }
+    }
+
+    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<&raw::Box<raw::Vec<()>>> |b| {
+            self.writer.write_char('@');
+            self.write_mut_qualifier(mtbl);
+            self.write_unboxed_vec_repr(mtbl, &b.data, inner);
+        }
+    }
+
+    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<&raw::Vec<()>> |b| {
+            self.writer.write_char('~');
+            self.write_unboxed_vec_repr(mtbl, *b, inner);
+        }
+    }
+
+    fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<&raw::Box<raw::Vec<()>>> |b| {
+            self.writer.write_char('~');
+            self.write_unboxed_vec_repr(mtbl, &b.data, inner);
+        }
+    }
+
+    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<raw::Slice<()>> |s| {
+            self.writer.write_char('&');
+            self.write_vec_range(mtbl, s.data, s.len, inner);
+        }
+    }
+
+    fn visit_evec_fixed(&self, _n: uint, sz: uint, _align: uint,
+                        mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<()> |b| {
+            self.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), sz, inner);
+        }
+    }
+
+    fn visit_enter_rec(&self, _n_fields: uint,
+                       _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('{');
+        true
+    }
+
+    fn visit_rec_field(&self, i: uint, name: &str,
+                       mtbl: uint, inner: *TyDesc) -> bool {
+        if i != 0 {
+            self.writer.write_str(", ");
+        }
+        self.write_mut_qualifier(mtbl);
+        self.writer.write_str(name);
+        self.writer.write_str(": ");
+        self.visit_inner(inner);
+        true
+    }
+
+    fn visit_leave_rec(&self, _n_fields: uint,
+                       _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('}');
+        true
+    }
+
+    fn visit_enter_class(&self, _n_fields: uint,
+                         _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('{');
+        true
+    }
+    fn visit_class_field(&self, i: uint, name: &str,
+                         mtbl: uint, inner: *TyDesc) -> bool {
+        if i != 0 {
+            self.writer.write_str(", ");
+        }
+        self.write_mut_qualifier(mtbl);
+        self.writer.write_str(name);
+        self.writer.write_str(": ");
+        self.visit_inner(inner);
+        true
+    }
+    fn visit_leave_class(&self, _n_fields: uint,
+                         _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('}');
+        true
+    }
+
+    fn visit_enter_tup(&self, _n_fields: uint,
+                       _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('(');
+        true
+    }
+    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool {
+        if i != 0 {
+            self.writer.write_str(", ");
+        }
+        self.visit_inner(inner);
+        true
+    }
+    fn visit_leave_tup(&self, _n_fields: uint,
+                       _sz: uint, _align: uint) -> bool {
+        if _n_fields == 1 {
+            self.writer.write_char(',');
+        }
+        self.writer.write_char(')');
+        true
+    }
+
+    fn visit_enter_enum(&self,
+                        _n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        _sz: uint,
+                        _align: uint) -> bool {
+        let var_stk: &mut ~[VariantState] = self.var_stk;
+        let disr = unsafe {
+            get_disr(transmute(*self.ptr))
+        };
+        var_stk.push(SearchingFor(disr));
+        true
+    }
+
+    fn visit_enter_enum_variant(&self, _variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool {
+        let mut write = false;
+        match self.var_stk.pop() {
+            SearchingFor(sought) => {
+                if disr_val == sought {
+                    self.var_stk.push(Matched);
+                    write = true;
+                } else {
+                    self.var_stk.push(SearchingFor(sought));
+                }
+            }
+            Matched | AlreadyFound => {
+                self.var_stk.push(AlreadyFound);
+            }
+        }
+
+        if write {
+            self.writer.write_str(name);
+            if n_fields > 0 {
+                self.writer.write_char('(');
+            }
+        }
+        true
+    }
+
+    fn visit_enum_variant_field(&self,
+                                i: uint,
+                                _offset: uint,
+                                inner: *TyDesc)
+                                -> bool {
+        match self.var_stk[self.var_stk.len() - 1] {
+            Matched => {
+                if i != 0 {
+                    self.writer.write_str(", ");
+                }
+                if ! self.visit_inner(inner) {
+                    return false;
+                }
+            }
+            _ => ()
+        }
+        true
+    }
+
+    fn visit_leave_enum_variant(&self, _variant: uint,
+                                _disr_val: int,
+                                n_fields: uint,
+                                _name: &str) -> bool {
+        match self.var_stk[self.var_stk.len() - 1] {
+            Matched => {
+                if n_fields > 0 {
+                    self.writer.write_char(')');
+                }
+            }
+            _ => ()
+        }
+        true
+    }
+
+    fn visit_leave_enum(&self,
+                        _n_variants: uint,
+                        _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        _sz: uint,
+                        _align: uint)
+                        -> bool {
+        let var_stk: &mut ~[VariantState] = self.var_stk;
+        match var_stk.pop() {
+            SearchingFor(*) => fail!("enum value matched no variant"),
+            _ => true
+        }
+    }
+
+    fn visit_enter_fn(&self, _purity: uint, _proto: uint,
+                      _n_inputs: uint, _retstyle: uint) -> bool { true }
+    fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool {
+        true
+    }
+    fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool {
+        true
+    }
+    fn visit_leave_fn(&self, _purity: uint, _proto: uint,
+                      _n_inputs: uint, _retstyle: uint) -> bool { true }
+
+
+    fn visit_trait(&self) -> bool { true }
+    fn visit_param(&self, _i: uint) -> bool { true }
+    fn visit_self(&self) -> bool { true }
+    fn visit_type(&self) -> bool { true }
+
+    fn visit_opaque_box(&self) -> bool {
+        self.writer.write_char('@');
+        do self.get::<&raw::Box<()>> |b| {
+            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
+            self.visit_ptr_inner(p, b.type_desc);
+        }
+    }
+
+    fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
+}
+
+pub fn write_repr<T>(writer: @Writer, object: &T) {
+    unsafe {
+        let ptr = ptr::to_unsafe_ptr(object) as *c_void;
+        let tydesc = get_tydesc::<T>();
+        let u = ReprVisitor(ptr, writer);
+        let v = reflect::MovePtrAdaptor(u);
+        visit_tydesc(tydesc, @v as @TyVisitor)
+    }
+}
+
+#[cfg(test)]
+struct P {a: int, b: float}
+
+#[test]
+fn test_repr() {
+
+    fn exact_test<T>(t: &T, e:&str) {
+        let s : &str = io::with_str_writer(|w| write_repr(w, t));
+        if s != e {
+            error!("expected '%s', got '%s'",
+                   e, s);
+        }
+        assert_eq!(s, e);
+    }
+
+    exact_test(&10, "10");
+    exact_test(&true, "true");
+    exact_test(&false, "false");
+    exact_test(&1.234, "1.234");
+    exact_test(&(&"hello"), "\"hello\"");
+    exact_test(&(@"hello"), "@\"hello\"");
+    exact_test(&(~"he\u10f3llo"), "~\"he\\u10f3llo\"");
+
+    exact_test(&(@10), "@10");
+    exact_test(&(@mut 10), "@10"); // FIXME: #4210: incorrect
+    exact_test(&((@mut 10, 2)), "(@mut 10, 2)");
+    exact_test(&(~10), "~10");
+    exact_test(&(&10), "&10");
+    let mut x = 10;
+    exact_test(&(&mut x), "&mut 10");
+    exact_test(&(@mut [1, 2]), "@mut [1, 2]");
+
+    exact_test(&(1,), "(1,)");
+    exact_test(&(@[1,2,3,4,5,6,7,8]),
+               "@[1, 2, 3, 4, 5, 6, 7, 8]");
+    exact_test(&(@[1u8,2u8,3u8,4u8]),
+               "@[1, 2, 3, 4]");
+    exact_test(&(@["hi", "there"]),
+               "@[\"hi\", \"there\"]");
+    exact_test(&(~["hi", "there"]),
+               "~[\"hi\", \"there\"]");
+    exact_test(&(&["hi", "there"]),
+               "&[\"hi\", \"there\"]");
+    exact_test(&(P{a:10, b:1.234}),
+               "{a: 10, b: 1.234}");
+    exact_test(&(@P{a:10, b:1.234}),
+               "@{a: 10, b: 1.234}");
+    exact_test(&(~P{a:10, b:1.234}),
+               "~{a: 10, b: 1.234}");
+    exact_test(&(10_u8, ~"hello"),
+               "(10, ~\"hello\")");
+    exact_test(&(10_u16, ~"hello"),
+               "(10, ~\"hello\")");
+    exact_test(&(10_u32, ~"hello"),
+               "(10, ~\"hello\")");
+    exact_test(&(10_u64, ~"hello"),
+               "(10, ~\"hello\")");
+
+    struct Foo;
+    exact_test(&(~[Foo, Foo, Foo]), "~[{}, {}, {}]");
+}
index baaf3d44e79d3b22231985f60255dd6ec6d5afdd..e5075f8818a0b38f7d525c06e6205186743027d8 100644 (file)
@@ -55,10 +55,11 @@ pub fn clone() -> Option<~[~str]> {
 mod imp {
     use libc;
     use option::{Option, Some, None};
-    use iterator::{Iterator, range};
+    use iterator::Iterator;
     use str;
     use unstable::finally::Finally;
     use util;
+    use vec;
 
     pub unsafe fn init(argc: int, argv: **u8) {
         let args = load_argc_and_argv(argc, argv);
@@ -111,11 +112,9 @@ fn get_global_ptr() -> *mut Option<~~[~str]> {
 
     // Copied from `os`.
     unsafe fn load_argc_and_argv(argc: int, argv: **u8) -> ~[~str] {
-        let mut args = ~[];
-        for i in range(0u, argc as uint) {
-            args.push(str::raw::from_c_str(*(argv as **libc::c_char).offset(i as int)));
+        do vec::from_fn(argc as uint) |i| {
+            str::raw::from_c_str(*(argv as **libc::c_char).offset(i as int))
         }
-        args
     }
 
     #[cfg(stage0)]
index 4b1881409f44f54e35f002342ee9bf23350e5411..4f5f26513b4c6fcf558cd52ab22bbac382a7f2d3 100644 (file)
@@ -718,7 +718,7 @@ mod test {
     use option::*;
     use rt::test::*;
     use cell::Cell;
-    use iter::Times;
+    use num::Times;
     use rt::util;
 
     #[test]
index 534e308a1a6e8dc65e0414560617070abe56aaa7..3fb0072040664c52e834a64baa48e5cff237a1ee 100644 (file)
@@ -71,6 +71,9 @@ pub struct FileStream {
     last_nread: int,
 }
 
+impl FileStream {
+}
+
 impl Reader for FileStream {
     fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
         match self.fd.read(buf) {
@@ -165,6 +168,7 @@ fn file_test_smoke_test_impl() {
 }
 
 #[test]
+#[ignore(cfg(windows))] // FIXME #8810
 fn file_test_io_smoke_test() {
     file_test_smoke_test_impl();
 }
@@ -232,6 +236,7 @@ fn file_test_io_non_positional_read_impl() {
 }
 
 #[test]
+#[ignore(cfg(windows))] // FIXME #8810
 fn file_test_io_non_positional_read() {
     file_test_io_non_positional_read_impl();
 }
@@ -264,6 +269,7 @@ fn file_test_io_seeking_impl() {
     }
 }
 #[test]
+#[ignore(cfg(windows))] // FIXME #8810
 fn file_test_io_seek_and_tell_smoke_test() {
     file_test_io_seeking_impl();
 }
@@ -295,6 +301,7 @@ fn file_test_io_seek_and_write_impl() {
     }
 }
 #[test]
+#[ignore(cfg(windows))] // FIXME #8810
 fn file_test_io_seek_and_write() {
     file_test_io_seek_and_write_impl();
 }
@@ -334,6 +341,7 @@ fn file_test_io_seek_shakedown_impl() {
     }
 }
 #[test]
+#[ignore(cfg(windows))] // FIXME #8810
 fn file_test_io_seek_shakedown() {
     file_test_io_seek_shakedown_impl();
 }
index 038fca9a1ade441c2e0a867ee1cf3eb89ae3a71f..116d240308a36c9cabf988df7d4bfe93c6762f53 100644 (file)
 /// Synchronous, non-blocking file I/O.
 pub mod file;
 
-/// Synchronous, in-memory I/O.
-pub mod pipe;
-
 /// Synchronous, non-blocking network I/O.
 pub mod net {
     pub mod tcp;
index dc7135f4a61ecb2bea11351b4a6b67fc3e6c9d52..ce66cd0de59c2e656281bcea1875126553024d59 100644 (file)
@@ -16,7 +16,7 @@
 use rt::rtio::{IoFactory, IoFactoryObject,
                RtioSocket, RtioTcpListener,
                RtioTcpListenerObject, RtioTcpStream,
-               RtioTcpStreamObject, RtioStream};
+               RtioTcpStreamObject};
 use rt::local::Local;
 
 pub struct TcpStream(~RtioTcpStreamObject);
@@ -69,7 +69,7 @@ pub fn socket_name(&mut self) -> Option<SocketAddr> {
 
 impl Reader for TcpStream {
     fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        match (***self).read(buf) {
+        match (**self).read(buf) {
             Ok(read) => Some(read),
             Err(ioerr) => {
                 // EOF is indicated by returning None
@@ -86,7 +86,7 @@ fn eof(&mut self) -> bool { fail!() }
 
 impl Writer for TcpStream {
     fn write(&mut self, buf: &[u8]) {
-        match (***self).write(buf) {
+        match (**self).write(buf) {
             Ok(_) => (),
             Err(ioerr) => io_error::cond.raise(ioerr),
         }
@@ -162,11 +162,12 @@ fn bind_error() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8811
     fn connect_error() {
         do run_in_newsched_task {
             let mut called = false;
             do io_error::cond.trap(|e| {
-                assert_eq!(e.kind, ConnectionRefused);
+                assert!(e.kind == ConnectionRefused);
                 called = true;
             }).inside {
                 let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
@@ -258,6 +259,7 @@ fn read_eof_ip6() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8811
     fn read_eof_twice_ip4() {
         do run_in_newsched_task {
             let addr = next_test_ip4();
@@ -280,6 +282,7 @@ fn read_eof_twice_ip4() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8811
     fn read_eof_twice_ip6() {
         do run_in_newsched_task {
             let addr = next_test_ip6();
@@ -302,6 +305,7 @@ fn read_eof_twice_ip6() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8811
     fn write_close_ip4() {
         do run_in_newsched_task {
             let addr = next_test_ip4();
@@ -331,6 +335,7 @@ fn write_close_ip4() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8811
     fn write_close_ip6() {
         do run_in_newsched_task {
             let addr = next_test_ip6();
diff --git a/src/libstd/rt/io/pipe.rs b/src/libstd/rt/io/pipe.rs
deleted file mode 100644 (file)
index 02b3d0f..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Synchronous, in-memory pipes.
-//!
-//! Currently these aren't particularly useful, there only exists bindings
-//! enough so that pipes can be created to child processes.
-
-use prelude::*;
-use super::{Reader, Writer};
-use rt::io::{io_error, read_error, EndOfFile};
-use rt::local::Local;
-use rt::rtio::{RtioPipeObject, RtioStream, IoFactoryObject, IoFactory};
-use rt::uv::pipe;
-
-pub struct PipeStream(~RtioPipeObject);
-
-impl PipeStream {
-    /// Creates a new pipe initialized, but not bound to any particular
-    /// source/destination
-    pub fn new() -> Option<PipeStream> {
-        let pipe = unsafe {
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
-            (*io).pipe_init(false)
-        };
-        match pipe {
-            Ok(p) => Some(PipeStream(p)),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-
-    /// Extracts the underlying libuv pipe to be bound to another source.
-    pub fn uv_pipe(&self) -> pipe::Pipe {
-        // Did someone say multiple layers of indirection?
-        (**self).uv_pipe()
-    }
-}
-
-impl Reader for PipeStream {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        match (***self).read(buf) {
-            Ok(read) => Some(read),
-            Err(ioerr) => {
-                // EOF is indicated by returning None
-                if ioerr.kind != EndOfFile {
-                    read_error::cond.raise(ioerr);
-                }
-                return None;
-            }
-        }
-    }
-
-    fn eof(&mut self) -> bool { fail!() }
-}
-
-impl Writer for PipeStream {
-    fn write(&mut self, buf: &[u8]) {
-        match (***self).write(buf) {
-            Ok(_) => (),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-            }
-        }
-    }
-
-    fn flush(&mut self) { fail!() }
-}
index 7bace5d6df2ccfdba1cfe7538ab05cbed10da6cb..afbff77f9883226e03e4985eb696c06de631e2a1 100644 (file)
@@ -33,6 +33,7 @@ mod test {
     use super::PathLike;
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8812
     fn path_like_smoke_test() {
         let expected = "/home";
         let path = Path(expected);
index e843fd1adef07aa6e258ac16cc52c628b1b374f7..3f9b7fc83df9822b618ff658f97db38f4cad4999 100644 (file)
@@ -121,27 +121,20 @@ pub unsafe fn borrow<T>(f: &fn(&mut T)) {
 /// For the Scheduler pointer to be aliased
 pub unsafe fn unsafe_borrow<T>() -> *mut T {
     let key = tls_key();
-    let mut void_ptr: *mut c_void = tls::get(key);
+    let void_ptr = tls::get(key);
     if void_ptr.is_null() {
         rtabort!("thread-local pointer is null. bogus!");
     }
-    let ptr: *mut *mut c_void = &mut void_ptr;
-    let ptr: *mut ~T = ptr as *mut ~T;
-    let ptr: *mut T = &mut **ptr;
-    return ptr;
+    void_ptr as *mut T
 }
 
 pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
     let key = tls_key();
-    let mut void_ptr: *mut c_void = tls::get(key);
+    let void_ptr = tls::get(key);
     if void_ptr.is_null() {
-        return None;
-    }
-    {
-        let ptr: *mut *mut c_void = &mut void_ptr;
-        let ptr: *mut ~T = ptr as *mut ~T;
-        let ptr: *mut T = &mut **ptr;
-        return Some(ptr);
+        None
+    } else {
+        Some(void_ptr as *mut T)
     }
 }
 
index 7728a388c658a689c023f7b583acb00093684ee0..14ff1fd58044f56b3b7717e556ddbbe056a4abbd 100644 (file)
@@ -59,7 +59,7 @@
 use cell::Cell;
 use clone::Clone;
 use container::Container;
-use iterator::{Iterator, range};
+use iterator::Iterator;
 use option::{Option, None, Some};
 use ptr::RawPtr;
 use rt::local::Local;
@@ -71,7 +71,8 @@
 use rt::uv::uvio::UvEventLoop;
 use unstable::atomics::{AtomicInt, SeqCst};
 use unstable::sync::UnsafeArc;
-use vec::{OwnedVector, MutableVector};
+use vec;
+use vec::{OwnedVector, MutableVector, ImmutableVector};
 
 /// The global (exchange) heap.
 pub mod global_heap;
@@ -251,11 +252,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
 
     // Create a work queue for each scheduler, ntimes. Create an extra
     // for the main thread if that flag is set. We won't steal from it.
-    let mut work_queues = ~[];
-    for _ in range(0u, nscheds) {
-        let work_queue: WorkQueue<~Task> = WorkQueue::new();
-        work_queues.push(work_queue);
-    }
+    let work_queues: ~[WorkQueue<~Task>] = vec::from_fn(nscheds, |_| WorkQueue::new());
 
     // The schedulers.
     let mut scheds = ~[];
@@ -263,13 +260,13 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
     // sent the Shutdown message to terminate the schedulers.
     let mut handles = ~[];
 
-    for i in range(0u, nscheds) {
+    for work_queue in work_queues.iter() {
         rtdebug!("inserting a regular scheduler");
 
         // Every scheduler is driven by an I/O event loop.
         let loop_ = ~UvEventLoop::new();
         let mut sched = ~Scheduler::new(loop_,
-                                        work_queues[i].clone(),
+                                        work_queue.clone(),
                                         work_queues.clone(),
                                         sleepers.clone());
         let handle = sched.make_handle();
@@ -358,9 +355,8 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
     }
 
     // Run each remaining scheduler in a thread.
-    while !scheds.is_empty() {
+    for sched in scheds.move_rev_iter() {
         rtdebug!("creating regular schedulers");
-        let sched = scheds.pop();
         let sched_cell = Cell::new(sched);
         let thread = do Thread::start {
             let mut sched = sched_cell.take();
index 1a7ef6ea309b9ac78c4f781298b782a93b131c93..1788b7a04e33446c3e8c04b77671481eed5bea29 100644 (file)
@@ -8,14 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use libc;
 use option::*;
 use result::*;
 use libc::c_int;
 
 use rt::io::IoError;
 use super::io::net::ip::{IpAddr, SocketAddr};
-use rt::uv;
 use rt::uv::uvio;
 use path::Path;
 use super::io::support::PathLike;
@@ -32,9 +30,6 @@
 pub type RtioUdpSocketObject = uvio::UvUdpSocket;
 pub type RtioTimerObject = uvio::UvTimer;
 pub type PausibleIdleCallback = uvio::UvPausibleIdleCallback;
-pub type RtioPipeObject = uvio::UvPipeStream;
-pub type RtioProcessObject = uvio::UvProcess;
-pub type RtioProcessConfig<'self> = uv::process::Config<'self>;
 
 pub trait EventLoop {
     fn run(&mut self);
@@ -77,13 +72,6 @@ pub trait IoFactory {
     fn fs_open<P: PathLike>(&mut self, path: &P, fm: FileMode, fa: FileAccess)
         -> Result<~RtioFileStream, IoError>;
     fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
-    fn pipe_init(&mut self, ipc: bool) -> Result<~RtioPipeObject, IoError>;
-    fn spawn(&mut self, config: &RtioProcessConfig) -> Result<~RtioProcessObject, IoError>;
-}
-
-pub trait RtioStream {
-    fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError>;
-    fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
 }
 
 pub trait RtioTcpListener : RtioSocket {
@@ -92,7 +80,9 @@ pub trait RtioTcpListener : RtioSocket {
     fn dont_accept_simultaneously(&mut self) -> Result<(), IoError>;
 }
 
-pub trait RtioTcpStream : RtioSocket + RtioStream {
+pub trait RtioTcpStream : RtioSocket {
+    fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError>;
+    fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
     fn peer_name(&mut self) -> Result<SocketAddr, IoError>;
     fn control_congestion(&mut self) -> Result<(), IoError>;
     fn nodelay(&mut self) -> Result<(), IoError>;
@@ -134,9 +124,3 @@ pub trait RtioFileStream {
     fn tell(&self) -> Result<u64, IoError>;
     fn flush(&mut self) -> Result<(), IoError>;
 }
-
-pub trait RtioProcess {
-    fn id(&self) -> libc::pid_t;
-    fn kill(&mut self, signal: int) -> Result<(), IoError>;
-    fn wait(&mut self) -> int;
-}
index b393832871dd7dae2074f028d5fafea4c8fa612c..6aa66a6ab6bcd886d00b23aed6093c2e7e0d221a 100644 (file)
@@ -1114,7 +1114,7 @@ fn no_missed_messages() {
     #[test]
     fn multithreading() {
         use rt::comm::*;
-        use iter::Times;
+        use num::Times;
         use vec::OwnedVector;
         use container::Container;
 
index 9113f03ffee1cd9402574ea4db971ffbd30be56c..6f39cbbade3d47265aa7e4201bf7c32860b5012c 100644 (file)
@@ -11,7 +11,7 @@
 use container::Container;
 use from_str::FromStr;
 use libc;
-use option::{Some, None};
+use option::{Some, None, Option};
 use os;
 use str::StrSlice;
 use unstable::atomics::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
@@ -57,7 +57,13 @@ pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool {
 /// either `RUST_THREADS` or `num_cpus`.
 pub fn default_sched_threads() -> uint {
     match os::getenv("RUST_THREADS") {
-        Some(nstr) => FromStr::from_str(nstr).unwrap(),
+        Some(nstr) => {
+            let opt_n: Option<uint> = FromStr::from_str(nstr);
+            match opt_n {
+                Some(n) if n > 0 => n,
+                _ => rtabort!("`RUST_THREADS` is `%s`, should be a positive integer", nstr)
+            }
+        }
         None => {
             if limit_thread_creation_due_to_osx_and_valgrind() {
                 1
index ff7bb9dd03abcf8403fd40a0d703e44c2c339618..d0ca38317cbededd13675b41c17ad764ee7f982b 100644 (file)
@@ -34,7 +34,7 @@ pub fn new(loop_: &mut Loop, cb: AsyncCallback) -> AsyncWatcher {
 
         extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
             let mut watcher: AsyncWatcher = NativeHandle::from_native_handle(handle);
-            let status = status_to_maybe_uv_error(status);
+            let status = status_to_maybe_uv_error(watcher, status);
             let data = watcher.get_watcher_data();
             let cb = data.async_cb.get_ref();
             (*cb)(watcher, status);
index 5c77181d7eb83a7098a3cb194a85ee89c6157fa8..eaf7024244040cca6790a997e4147f435817d7b2 100644 (file)
@@ -11,8 +11,8 @@
 use prelude::*;
 use ptr::null;
 use libc::c_void;
-use rt::uv::{Request, NativeHandle, Loop, FsCallback, Buf, UvError};
-use rt::uv::status_to_maybe_uv_error;
+use rt::uv::{Request, NativeHandle, Loop, FsCallback, Buf,
+             status_to_maybe_uv_error_with_loop, UvError};
 use rt::uv::uvll;
 use rt::uv::uvll::*;
 use super::super::io::support::PathLike;
@@ -62,7 +62,7 @@ pub fn open<P: PathLike>(loop_: &Loop, path: &P, flags: int, mode: int,
     pub fn open_sync<P: PathLike>(loop_: &Loop, path: &P, flags: int, mode: int)
           -> Result<int, UvError> {
         let result = FsRequest::open_common(loop_, path, flags, mode, None);
-        sync_cleanup(result)
+        sync_cleanup(loop_, result)
     }
 
     fn unlink_common<P: PathLike>(loop_: &Loop, path: &P, cb: Option<FsCallback>) -> int {
@@ -83,11 +83,11 @@ fn unlink_common<P: PathLike>(loop_: &Loop, path: &P, cb: Option<FsCallback>) ->
     }
     pub fn unlink<P: PathLike>(loop_: &Loop, path: &P, cb: FsCallback) {
         let result = FsRequest::unlink_common(loop_, path, Some(cb));
-        sync_cleanup(result);
+        sync_cleanup(loop_, result);
     }
     pub fn unlink_sync<P: PathLike>(loop_: &Loop, path: &P) -> Result<int, UvError> {
         let result = FsRequest::unlink_common(loop_, path, None);
-        sync_cleanup(result)
+        sync_cleanup(loop_, result)
     }
 
     pub fn install_req_data(&self, cb: Option<FsCallback>) {
@@ -139,8 +139,9 @@ fn native_handle(&self) -> *uvll::uv_fs_t {
         match self { &FsRequest(ptr) => ptr }
     }
 }
-    fn sync_cleanup(result: int) -> Result<int, UvError> {
-        match status_to_maybe_uv_error(result as i32) {
+    fn sync_cleanup(loop_: &Loop, result: int)
+          -> Result<int, UvError> {
+        match status_to_maybe_uv_error_with_loop(loop_.native_handle(), result as i32) {
             Some(err) => Err(err),
             None => Ok(result)
         }
@@ -183,7 +184,7 @@ pub fn write(&mut self, loop_: &Loop, buf: Buf, offset: i64, cb: FsCallback) {
     pub fn write_sync(&mut self, loop_: &Loop, buf: Buf, offset: i64)
           -> Result<int, UvError> {
         let result = self.write_common(loop_, buf, offset, None);
-        sync_cleanup(result)
+        sync_cleanup(loop_, result)
     }
 
     fn read_common(&mut self, loop_: &Loop, buf: Buf,
@@ -211,7 +212,7 @@ pub fn read(&mut self, loop_: &Loop, buf: Buf, offset: i64, cb: FsCallback) {
     pub fn read_sync(&mut self, loop_: &Loop, buf: Buf, offset: i64)
           -> Result<int, UvError> {
         let result = self.read_common(loop_, buf, offset, None);
-        sync_cleanup(result)
+        sync_cleanup(loop_, result)
     }
 
     fn close_common(self, loop_: &Loop, cb: Option<FsCallback>) -> int {
@@ -233,11 +234,12 @@ pub fn close(self, loop_: &Loop, cb: FsCallback) {
     }
     pub fn close_sync(self, loop_: &Loop) -> Result<int, UvError> {
         let result = self.close_common(loop_, None);
-        sync_cleanup(result)
+        sync_cleanup(loop_, result)
     }
 }
 extern fn compl_cb(req: *uv_fs_t) {
     let mut req: FsRequest = NativeHandle::from_native_handle(req);
+    let loop_ = req.get_loop();
     // pull the user cb out of the req data
     let cb = {
         let data = req.get_req_data();
@@ -248,7 +250,8 @@ pub fn close_sync(self, loop_: &Loop) -> Result<int, UvError> {
     // in uv_fs_open calls, the result will be the fd in the
     // case of success, otherwise it's -1 indicating an error
     let result = req.get_result();
-    let status = status_to_maybe_uv_error(result);
+    let status = status_to_maybe_uv_error_with_loop(
+        loop_.native_handle(), result);
     // we have a req and status, call the user cb..
     // only giving the user a ref to the FsRequest, as we
     // have to clean it up, afterwards (and they aren't really
@@ -405,11 +408,13 @@ fn file_test_full_simple_impl_sync() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8814
     fn file_test_full_simple() {
         file_test_full_simple_impl();
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8814
     fn file_test_full_simple_sync() {
         file_test_full_simple_impl_sync();
     }
index 8cbcd7b77c0824fdea0b1df2e1234cdc0a412b3c..a21146620ca823ec8643adfdb84c00f31a391b38 100644 (file)
@@ -43,7 +43,7 @@ pub fn start(&mut self, cb: IdleCallback) {
             let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
             let data = idle_watcher.get_watcher_data();
             let cb: &IdleCallback = data.idle_cb.get_ref();
-            let status = status_to_maybe_uv_error(status);
+            let status = status_to_maybe_uv_error(idle_watcher, status);
             (*cb)(idle_watcher, status);
         }
     }
@@ -57,7 +57,7 @@ pub fn restart(&mut self) {
             let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
             let data = idle_watcher.get_watcher_data();
             let cb: &IdleCallback = data.idle_cb.get_ref();
-            let status = status_to_maybe_uv_error(status);
+            let status = status_to_maybe_uv_error(idle_watcher, status);
             (*cb)(idle_watcher, status);
         }
     }
index 700b80c7398b53675416cb92cbbc8a168c6d9b57..75b9a5ac553e8eff77d5d096730081f2e12cd902 100644 (file)
@@ -58,8 +58,6 @@
 pub use self::idle::IdleWatcher;
 pub use self::timer::TimerWatcher;
 pub use self::async::AsyncWatcher;
-pub use self::process::Process;
-pub use self::pipe::Pipe;
 
 /// The implementation of `rtio` for libuv
 pub mod uvio;
@@ -72,8 +70,6 @@
 pub mod idle;
 pub mod timer;
 pub mod async;
-pub mod process;
-pub mod pipe;
 
 /// XXX: Loop(*handle) is buggy with destructors. Normal structs
 /// with dtors may not be destructured, but tuple structs can,
@@ -130,8 +126,6 @@ fn native_handle(&self) -> *uvll::uv_loop_t {
 pub type IdleCallback = ~fn(IdleWatcher, Option<UvError>);
 pub type ConnectionCallback = ~fn(StreamWatcher, Option<UvError>);
 pub type FsCallback = ~fn(&mut FsRequest, Option<UvError>);
-// first int is exit_status, second is term_signal
-pub type ExitCallback = ~fn(Process, int, int, Option<UvError>);
 pub type TimerCallback = ~fn(TimerWatcher, Option<UvError>);
 pub type AsyncCallback = ~fn(AsyncWatcher, Option<UvError>);
 pub type UdpReceiveCallback = ~fn(UdpWatcher, int, Buf, SocketAddr, uint, Option<UvError>);
@@ -149,8 +143,7 @@ struct WatcherData {
     timer_cb: Option<TimerCallback>,
     async_cb: Option<AsyncCallback>,
     udp_recv_cb: Option<UdpReceiveCallback>,
-    udp_send_cb: Option<UdpSendCallback>,
-    exit_cb: Option<ExitCallback>,
+    udp_send_cb: Option<UdpSendCallback>
 }
 
 pub trait WatcherInterop {
@@ -182,8 +175,7 @@ fn install_watcher_data(&mut self) {
                 timer_cb: None,
                 async_cb: None,
                 udp_recv_cb: None,
-                udp_send_cb: None,
-                exit_cb: None,
+                udp_send_cb: None
             };
             let data = transmute::<~WatcherData, *c_void>(data);
             uvll::set_data_for_uv_handle(self.native_handle(), data);
@@ -210,12 +202,12 @@ fn drop_watcher_data(&mut self) {
 // XXX: Need to define the error constants like EOF so they can be
 // compared to the UvError type
 
-pub struct UvError(c_int);
+pub struct UvError(uvll::uv_err_t);
 
 impl UvError {
     pub fn name(&self) -> ~str {
         unsafe {
-            let inner = match self { &UvError(a) => a };
+            let inner = match self { &UvError(ref a) => a };
             let name_str = uvll::err_name(inner);
             assert!(name_str.is_not_null());
             from_c_str(name_str)
@@ -224,7 +216,7 @@ pub fn name(&self) -> ~str {
 
     pub fn desc(&self) -> ~str {
         unsafe {
-            let inner = match self { &UvError(a) => a };
+            let inner = match self { &UvError(ref a) => a };
             let desc_str = uvll::strerror(inner);
             assert!(desc_str.is_not_null());
             from_c_str(desc_str)
@@ -232,7 +224,7 @@ pub fn desc(&self) -> ~str {
     }
 
     pub fn is_eof(&self) -> bool {
-        **self == uvll::EOF
+        self.code == uvll::EOF
     }
 }
 
@@ -244,10 +236,18 @@ fn to_str(&self) -> ~str {
 
 #[test]
 fn error_smoke_test() {
-    let err: UvError = UvError(uvll::EOF);
+    let err = uvll::uv_err_t { code: 1, sys_errno_: 1 };
+    let err: UvError = UvError(err);
     assert_eq!(err.to_str(), ~"EOF: end of file");
 }
 
+pub fn last_uv_error<H, W: Watcher + NativeHandle<*H>>(watcher: &W) -> UvError {
+    unsafe {
+        let loop_ = watcher.event_loop();
+        UvError(uvll::last_error(loop_.native_handle()))
+    }
+}
+
 pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
     unsafe {
         // Importing error constants
@@ -255,10 +255,10 @@ pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
         use rt::io::*;
 
         // uv error descriptions are static
-        let c_desc = uvll::strerror(*uverr);
+        let c_desc = uvll::strerror(&*uverr);
         let desc = str::raw::c_str_to_static_slice(c_desc);
 
-        let kind = match *uverr {
+        let kind = match uverr.code {
             UNKNOWN => OtherIoError,
             OK => OtherIoError,
             EOF => EndOfFile,
@@ -266,8 +266,8 @@ pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
             ECONNREFUSED => ConnectionRefused,
             ECONNRESET => ConnectionReset,
             EPIPE => BrokenPipe,
-            err => {
-                rtdebug!("uverr.code %d", err as int);
+            _ => {
+                rtdebug!("uverr.code %u", uverr.code as uint);
                 // XXX: Need to map remaining uv error types
                 OtherIoError
             }
@@ -281,12 +281,31 @@ pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
     }
 }
 
-/// Convert a callback status to a UvError
-pub fn status_to_maybe_uv_error(status: c_int) -> Option<UvError> {
-    if status >= 0 {
+/// Given a uv handle, convert a callback status to a UvError
+pub fn status_to_maybe_uv_error_with_loop(
+    loop_: *uvll::uv_loop_t,
+    status: c_int) -> Option<UvError> {
+    if status != -1 {
+        None
+    } else {
+        unsafe {
+            rtdebug!("loop: %x", loop_ as uint);
+            let err = uvll::last_error(loop_);
+            Some(UvError(err))
+        }
+    }
+}
+/// Given a uv handle, convert a callback status to a UvError
+pub fn status_to_maybe_uv_error<T, U: Watcher + NativeHandle<*T>>(handle: U,
+                                                                 status: c_int) -> Option<UvError> {
+    if status != -1 {
         None
     } else {
-        Some(UvError(status))
+        unsafe {
+            rtdebug!("handle: %x", handle.native_handle() as uint);
+            let loop_ = uvll::get_loop_for_uv_handle(handle.native_handle());
+            status_to_maybe_uv_error_with_loop(loop_, status)
+        }
     }
 }
 
index 1581b0170878fb0f7276c732860d7e6e2ef65df1..3ff6e90e32d2998c25fd96fc65136a8a83135a76 100644 (file)
@@ -16,6 +16,7 @@
 use rt::uv::{Loop, Watcher, Request, UvError, Buf, NativeHandle, NullCallback,
              status_to_maybe_uv_error};
 use rt::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
+use rt::uv::last_uv_error;
 use vec;
 use str;
 use from_str::{FromStr};
@@ -136,7 +137,7 @@ pub fn read_start(&mut self, alloc: AllocCallback, cb: ReadCallback) {
             rtdebug!("buf len: %d", buf.len as int);
             let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(stream);
             let cb = stream_watcher.get_watcher_data().read_cb.get_ref();
-            let status = status_to_maybe_uv_error(nread as c_int);
+            let status = status_to_maybe_uv_error(stream_watcher, nread as c_int);
             (*cb)(stream_watcher, nread as int, buf, status);
         }
     }
@@ -166,7 +167,7 @@ pub fn write(&mut self, buf: Buf, cb: ConnectionCallback) {
             let mut stream_watcher = write_request.stream();
             write_request.delete();
             let cb = stream_watcher.get_watcher_data().write_cb.take_unwrap();
-            let status = status_to_maybe_uv_error(status);
+            let status = status_to_maybe_uv_error(stream_watcher, status);
             cb(stream_watcher, status);
         }
     }
@@ -231,7 +232,7 @@ pub fn bind(&mut self, address: SocketAddr) -> Result<(), UvError> {
             };
             match result {
                 0 => Ok(()),
-                _ => Err(UvError(result)),
+                _ => Err(last_uv_error(self)),
             }
         }
     }
@@ -259,7 +260,7 @@ pub fn connect(&mut self, address: SocketAddr, cb: ConnectionCallback) {
                 let mut stream_watcher = connect_request.stream();
                 connect_request.delete();
                 let cb = stream_watcher.get_watcher_data().connect_cb.take_unwrap();
-                let status = status_to_maybe_uv_error(status);
+                let status = status_to_maybe_uv_error(stream_watcher, status);
                 cb(stream_watcher, status);
             }
         }
@@ -282,7 +283,7 @@ pub fn listen(&mut self, cb: ConnectionCallback) {
             rtdebug!("connection_cb");
             let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(handle);
             let cb = stream_watcher.get_watcher_data().connect_cb.get_ref();
-            let status = status_to_maybe_uv_error(status);
+            let status = status_to_maybe_uv_error(stream_watcher, status);
             (*cb)(stream_watcher, status);
         }
     }
@@ -326,7 +327,7 @@ pub fn bind(&mut self, address: SocketAddr) -> Result<(), UvError> {
             };
             match result {
                 0 => Ok(()),
-                _ => Err(UvError(result)),
+                _ => Err(last_uv_error(self)),
             }
         }
     }
@@ -359,7 +360,7 @@ pub fn recv_start(&mut self, alloc: AllocCallback, cb: UdpReceiveCallback) {
             rtdebug!("buf len: %d", buf.len as int);
             let mut udp_watcher: UdpWatcher = NativeHandle::from_native_handle(handle);
             let cb = udp_watcher.get_watcher_data().udp_recv_cb.get_ref();
-            let status = status_to_maybe_uv_error(nread as c_int);
+            let status = status_to_maybe_uv_error(udp_watcher, nread as c_int);
             let addr = uv_socket_addr_to_socket_addr(sockaddr_to_UvSocketAddr(addr));
             (*cb)(udp_watcher, nread as int, buf, addr, flags as uint, status);
         }
@@ -394,7 +395,7 @@ pub fn send(&mut self, buf: Buf, address: SocketAddr, cb: UdpSendCallback) {
             let mut udp_watcher = send_request.handle();
             send_request.delete();
             let cb = udp_watcher.get_watcher_data().udp_send_cb.take_unwrap();
-            let status = status_to_maybe_uv_error(status);
+            let status = status_to_maybe_uv_error(udp_watcher, status);
             cb(udp_watcher, status);
         }
     }
@@ -600,6 +601,7 @@ fn udp_bind_close_ip6() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8815
     fn listen_ip4() {
         do run_in_bare_thread() {
             static MAX: int = 10;
@@ -674,6 +676,7 @@ fn listen_ip4() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8815
     fn listen_ip6() {
         do run_in_bare_thread() {
             static MAX: int = 10;
@@ -750,6 +753,7 @@ fn listen_ip6() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8815
     fn udp_recv_ip4() {
         do run_in_bare_thread() {
             static MAX: int = 10;
@@ -810,6 +814,7 @@ fn udp_recv_ip4() {
     }
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8815
     fn udp_recv_ip6() {
         do run_in_bare_thread() {
             static MAX: int = 10;
diff --git a/src/libstd/rt/uv/pipe.rs b/src/libstd/rt/uv/pipe.rs
deleted file mode 100644 (file)
index 1147c73..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use prelude::*;
-use libc;
-
-use rt::uv;
-use rt::uv::net;
-use rt::uv::uvll;
-
-pub struct Pipe(*uvll::uv_pipe_t);
-
-impl uv::Watcher for Pipe {}
-
-impl Pipe {
-    pub fn new(loop_: &uv::Loop, ipc: bool) -> Pipe {
-        unsafe {
-            let handle = uvll::malloc_handle(uvll::UV_NAMED_PIPE);
-            assert!(handle.is_not_null());
-            let ipc = ipc as libc::c_int;
-            assert_eq!(uvll::pipe_init(loop_.native_handle(), handle, ipc), 0);
-            let mut ret: Pipe =
-                    uv::NativeHandle::from_native_handle(handle);
-            ret.install_watcher_data();
-            ret
-        }
-    }
-
-    pub fn as_stream(&self) -> net::StreamWatcher {
-        net::StreamWatcher(**self as *uvll::uv_stream_t)
-    }
-
-    pub fn close(self, cb: uv::NullCallback) {
-        {
-            let mut this = self;
-            let data = this.get_watcher_data();
-            assert!(data.close_cb.is_none());
-            data.close_cb = Some(cb);
-        }
-
-        unsafe { uvll::close(self.native_handle(), close_cb); }
-
-        extern fn close_cb(handle: *uvll::uv_pipe_t) {
-            let mut process: Pipe = uv::NativeHandle::from_native_handle(handle);
-            process.get_watcher_data().close_cb.take_unwrap()();
-            process.drop_watcher_data();
-            unsafe { uvll::free_handle(handle as *libc::c_void) }
-        }
-    }
-}
-
-impl uv::NativeHandle<*uvll::uv_pipe_t> for Pipe {
-    fn from_native_handle(handle: *uvll::uv_pipe_t) -> Pipe {
-        Pipe(handle)
-    }
-    fn native_handle(&self) -> *uvll::uv_pipe_t {
-        match self { &Pipe(ptr) => ptr }
-    }
-}
diff --git a/src/libstd/rt/uv/process.rs b/src/libstd/rt/uv/process.rs
deleted file mode 100644 (file)
index a02cf67..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use prelude::*;
-use libc;
-use ptr;
-use vec;
-use cell::Cell;
-
-use rt::uv;
-use rt::uv::net;
-use rt::uv::pipe;
-use rt::uv::uvll;
-
-/// A process wraps the handle of the underlying uv_process_t.
-pub struct Process(*uvll::uv_process_t);
-
-/// This configuration describes how a new process should be spawned. This is
-/// translated to libuv's own configuration
-pub struct Config<'self> {
-    /// Path to the program to run
-    program: &'self str,
-
-    /// Arguments to pass to the program (doesn't include the program itself)
-    args: &'self [~str],
-
-    /// Optional environment to specify for the program. If this is None, then
-    /// it will inherit the current process's environment.
-    env: Option<&'self [(~str, ~str)]>,
-
-    /// Optional working directory for the new process. If this is None, then
-    /// the current directory of the running process is inherited.
-    cwd: Option<&'self str>,
-
-    /// Any number of streams/file descriptors/pipes may be attached to this
-    /// process. This list enumerates the file descriptors and such for the
-    /// process to be spawned, and the file descriptors inherited will start at
-    /// 0 and go to the length of this array.
-    ///
-    /// Standard file descriptors are:
-    ///
-    ///     0 - stdin
-    ///     1 - stdout
-    ///     2 - stderr
-    io: &'self [StdioContainer]
-}
-
-/// Describes what to do with a standard io stream for a child process.
-pub enum StdioContainer {
-    /// This stream will be ignored. This is the equivalent of attaching the
-    /// stream to `/dev/null`
-    Ignored,
-
-    /// The specified file descriptor is inherited for the stream which it is
-    /// specified for.
-    InheritFd(libc::c_int),
-
-    /// The specified libuv stream is inherited for the corresponding file
-    /// descriptor it is assigned to.
-    InheritStream(net::StreamWatcher),
-
-    /// Creates a pipe for the specified file descriptor which will be directed
-    /// into the previously-initialized pipe passed in.
-    ///
-    /// The first boolean argument is whether the pipe is readable, and the
-    /// second is whether it is writable. These properties are from the view of
-    /// the *child* process, not the parent process.
-    CreatePipe(pipe::Pipe, bool /* readable */, bool /* writable */),
-}
-
-impl uv::Watcher for Process {}
-
-impl Process {
-    /// Creates a new process, ready to spawn inside an event loop
-    pub fn new() -> Process {
-        let handle = unsafe { uvll::malloc_handle(uvll::UV_PROCESS) };
-        assert!(handle.is_not_null());
-        let mut ret: Process = uv::NativeHandle::from_native_handle(handle);
-        ret.install_watcher_data();
-        return ret;
-    }
-
-    /// Spawn a new process inside the specified event loop.
-    ///
-    /// The `config` variable will be passed down to libuv, and the `exit_cb`
-    /// will be run only once, when the process exits.
-    ///
-    /// Returns either the corresponding process object or an error which
-    /// occurred.
-    pub fn spawn(&mut self, loop_: &uv::Loop, config: &Config,
-                 exit_cb: uv::ExitCallback) -> Result<(), uv::UvError> {
-        let cwd = config.cwd.map_move(|s| s.to_c_str());
-
-        extern fn on_exit(p: *uvll::uv_process_t,
-                          exit_status: libc::c_int,
-                          term_signal: libc::c_int) {
-            let mut p: Process = uv::NativeHandle::from_native_handle(p);
-            let err = match exit_status {
-                0 => None,
-                _ => uv::status_to_maybe_uv_error(-1)
-            };
-            p.get_watcher_data().exit_cb.take_unwrap()(p,
-                                                       exit_status as int,
-                                                       term_signal as int,
-                                                       err);
-        }
-
-        let mut stdio = vec::with_capacity::<uvll::uv_stdio_container_t>(
-                                config.io.len());
-        unsafe {
-            vec::raw::set_len(&mut stdio, config.io.len());
-            for (slot, &other) in stdio.iter().zip(config.io.iter()) {
-                set_stdio(slot as *uvll::uv_stdio_container_t, other);
-            }
-        }
-
-        let exit_cb = Cell::new(exit_cb);
-        do with_argv(config.program, config.args) |argv| {
-            do with_env(config.env) |envp| {
-                let options = uvll::uv_process_options_t {
-                    exit_cb: on_exit,
-                    file: unsafe { *argv },
-                    args: argv,
-                    env: envp,
-                    cwd: match cwd {
-                        Some(ref cwd) => cwd.with_ref(|p| p),
-                        None => ptr::null(),
-                    },
-                    flags: 0,
-                    stdio_count: stdio.len() as libc::c_int,
-                    stdio: stdio.as_imm_buf(|p, _| p),
-                    uid: 0,
-                    gid: 0,
-                };
-
-                match unsafe {
-                    uvll::spawn(loop_.native_handle(), **self, options)
-                } {
-                    0 => {
-                        (*self).get_watcher_data().exit_cb = Some(exit_cb.take());
-                        Ok(())
-                    }
-                    err => Err(uv::UvError(err))
-                }
-            }
-        }
-    }
-
-    /// Sends a signal to this process.
-    ///
-    /// This is a wrapper around `uv_process_kill`
-    pub fn kill(&self, signum: int) -> Result<(), uv::UvError> {
-        match unsafe {
-            uvll::process_kill(self.native_handle(), signum as libc::c_int)
-        } {
-            0 => Ok(()),
-            err => Err(uv::UvError(err))
-        }
-    }
-
-    /// Returns the process id of a spawned process
-    pub fn pid(&self) -> libc::pid_t {
-        unsafe { uvll::process_pid(**self) as libc::pid_t }
-    }
-
-    /// Closes this handle, invoking the specified callback once closed
-    pub fn close(self, cb: uv::NullCallback) {
-        {
-            let mut this = self;
-            let data = this.get_watcher_data();
-            assert!(data.close_cb.is_none());
-            data.close_cb = Some(cb);
-        }
-
-        unsafe { uvll::close(self.native_handle(), close_cb); }
-
-        extern fn close_cb(handle: *uvll::uv_process_t) {
-            let mut process: Process = uv::NativeHandle::from_native_handle(handle);
-            process.get_watcher_data().close_cb.take_unwrap()();
-            process.drop_watcher_data();
-            unsafe { uvll::free_handle(handle as *libc::c_void) }
-        }
-    }
-}
-
-unsafe fn set_stdio(dst: *uvll::uv_stdio_container_t, io: StdioContainer) {
-    match io {
-        Ignored => { uvll::set_stdio_container_flags(dst, uvll::STDIO_IGNORE); }
-        InheritFd(fd) => {
-            uvll::set_stdio_container_flags(dst, uvll::STDIO_INHERIT_FD);
-            uvll::set_stdio_container_fd(dst, fd);
-        }
-        InheritStream(stream) => {
-            uvll::set_stdio_container_flags(dst, uvll::STDIO_INHERIT_STREAM);
-            uvll::set_stdio_container_stream(dst, stream.native_handle());
-        }
-        CreatePipe(pipe, readable, writable) => {
-            let mut flags = uvll::STDIO_CREATE_PIPE as libc::c_int;
-            if readable {
-                flags |= uvll::STDIO_READABLE_PIPE as libc::c_int;
-            }
-            if writable {
-                flags |= uvll::STDIO_WRITABLE_PIPE as libc::c_int;
-            }
-            uvll::set_stdio_container_flags(dst, flags);
-            uvll::set_stdio_container_stream(dst,
-                                             pipe.as_stream().native_handle());
-        }
-    }
-}
-
-/// Converts the program and arguments to the argv array expected by libuv
-fn with_argv<T>(prog: &str, args: &[~str], f: &fn(**libc::c_char) -> T) -> T {
-    // First, allocation space to put all the C-strings (we need to have
-    // ownership of them somewhere
-    let mut c_strs = vec::with_capacity(args.len() + 1);
-    c_strs.push(prog.to_c_str());
-    for arg in args.iter() {
-        c_strs.push(arg.to_c_str());
-    }
-
-    // Next, create the char** array
-    let mut c_args = vec::with_capacity(c_strs.len() + 1);
-    for s in c_strs.iter() {
-        c_args.push(s.with_ref(|p| p));
-    }
-    c_args.push(ptr::null());
-    c_args.as_imm_buf(|buf, _| f(buf))
-}
-
-/// Converts the environment to the env array expected by libuv
-fn with_env<T>(env: Option<&[(~str, ~str)]>, f: &fn(**libc::c_char) -> T) -> T {
-    let env = match env {
-        Some(s) => s,
-        None => { return f(ptr::null()); }
-    };
-    // As with argv, create some temporary storage and then the actual array
-    let mut envp = vec::with_capacity(env.len());
-    for &(ref key, ref value) in env.iter() {
-        envp.push(fmt!("%s=%s", *key, *value).to_c_str());
-    }
-    let mut c_envp = vec::with_capacity(envp.len() + 1);
-    for s in envp.iter() {
-        c_envp.push(s.with_ref(|p| p));
-    }
-    c_envp.push(ptr::null());
-    c_envp.as_imm_buf(|buf, _| f(buf))
-}
-
-impl uv::NativeHandle<*uvll::uv_process_t> for Process {
-    fn from_native_handle(handle: *uvll::uv_process_t) -> Process {
-        Process(handle)
-    }
-    fn native_handle(&self) -> *uvll::uv_process_t {
-        match self { &Process(ptr) => ptr }
-    }
-}
index 7b09cf2eb0e3ab058f4c2cf2d65526585964e758..eaa5e77a6da2fe71b3a67a11105dc5acee18c4f5 100644 (file)
@@ -43,7 +43,7 @@ pub fn start(&mut self, timeout: u64, repeat: u64, cb: TimerCallback) {
             let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
             let data = watcher.get_watcher_data();
             let cb = data.timer_cb.get_ref();
-            let status = status_to_maybe_uv_error(status);
+            let status = status_to_maybe_uv_error(watcher, status);
             (*cb)(watcher, status);
         }
     }
index c771f93cef5e0de13b9b80e62b47fad4411662c2..f282432dcb5063cfd5c665acda282e6c417c3310 100644 (file)
@@ -13,7 +13,7 @@
 use cast;
 use cell::Cell;
 use clone::Clone;
-use libc::{c_int, c_uint, c_void, pid_t};
+use libc::{c_int, c_uint, c_void};
 use ops::Drop;
 use option::*;
 use ptr;
@@ -22,7 +22,6 @@
 use rt::io::IoError;
 use rt::io::net::ip::{SocketAddr, IpAddr};
 use rt::io::{standard_error, OtherIoError, SeekStyle, SeekSet, SeekCur, SeekEnd};
-use rt::kill::BlockedTask;
 use rt::local::Local;
 use rt::rtio::*;
 use rt::sched::{Scheduler, SchedHandle};
@@ -149,7 +148,7 @@ fn socket_name<T, U: Watcher + NativeHandle<*T>>(sk: SocketNameKind,
     };
 
     if r != 0 {
-        let status = status_to_maybe_uv_error(r);
+        let status = status_to_maybe_uv_error(handle, r);
         return Err(uv_error_to_io_error(status.unwrap()));
     }
 
@@ -592,63 +591,6 @@ fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
         assert!(!result_cell.is_empty());
         return result_cell.take();
     }
-
-    fn pipe_init(&mut self, ipc: bool) -> Result<~RtioPipeObject, IoError> {
-        let home = get_handle_to_current_scheduler!();
-        Ok(~UvPipeStream { pipe: Pipe::new(self.uv_loop(), ipc), home: home })
-    }
-
-    fn spawn(&mut self,
-             config: &process::Config) -> Result<~RtioProcessObject, IoError> {
-        // Sadly, we must create the UvProcess before we actually call uv_spawn
-        // so that the exit_cb can close over it and notify it when the process
-        // has exited.
-        let mut ret = ~UvProcess {
-            process: Process::new(),
-            home: None,
-            exit_status: None,
-            term_signal: None,
-            exit_error: None,
-            descheduled: None,
-        };
-        let ret_ptr = unsafe {
-            *cast::transmute::<&~UvProcess, &*mut UvProcess>(&ret)
-        };
-
-        // The purpose of this exit callback is to record the data about the
-        // exit and then wake up the task which may be waiting for the process
-        // to exit. This is all performed in the current io-loop, and the
-        // implementation of UvProcess ensures that reading these fields always
-        // occurs on the current io-loop.
-        let exit_cb: ExitCallback = |_, exit_status, term_signal, error| {
-            unsafe {
-                assert!((*ret_ptr).exit_status.is_none());
-                (*ret_ptr).exit_status = Some(exit_status);
-                (*ret_ptr).term_signal = Some(term_signal);
-                (*ret_ptr).exit_error = error;
-                match (*ret_ptr).descheduled.take() {
-                    Some(task) => {
-                        let scheduler: ~Scheduler = Local::take();
-                        scheduler.resume_blocked_task_immediately(task);
-                    }
-                    None => {}
-                }
-            }
-        };
-
-        match ret.process.spawn(self.uv_loop(), config, exit_cb) {
-            Ok(()) => {
-                // Only now do we actually get a handle to this scheduler.
-                ret.home = Some(get_handle_to_current_scheduler!());
-                Ok(ret)
-            }
-            Err(uverr) => {
-                // We still need to close the process handle we created, but
-                // that's taken care for us in the destructor of UvProcess
-                Err(uv_error_to_io_error(uverr))
-            }
-        }
-    }
 }
 
 pub struct UvTcpListener {
@@ -737,7 +679,7 @@ fn accept_simultaneously(&mut self) -> Result<(), IoError> {
                 uvll::tcp_simultaneous_accepts(self_.watcher().native_handle(), 1 as c_int)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher(), r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -750,7 +692,7 @@ fn dont_accept_simultaneously(&mut self) -> Result<(), IoError> {
                 uvll::tcp_simultaneous_accepts(self_.watcher().native_handle(), 0 as c_int)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher(), r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -758,15 +700,40 @@ fn dont_accept_simultaneously(&mut self) -> Result<(), IoError> {
     }
 }
 
-trait UvStream: HomingIO {
-    fn as_stream(&mut self) -> StreamWatcher;
+pub struct UvTcpStream {
+    watcher: TcpWatcher,
+    home: SchedHandle,
+}
+
+impl HomingIO for UvTcpStream {
+    fn home<'r>(&'r mut self) -> &'r mut SchedHandle { &mut self.home }
 }
 
-// FIXME(#3429) I would rather this be `impl<T: UvStream> RtioStream for T` but
-//              that has conflicts with other traits that also have methods
-//              called `read` and `write`
-macro_rules! rtiostream(($t:ident) => {
-impl RtioStream for $t {
+impl Drop for UvTcpStream {
+    fn drop(&self) {
+        // XXX need mutable finalizer
+        let this = unsafe { transmute::<&UvTcpStream, &mut UvTcpStream>(self) };
+        do this.home_for_io_with_sched |self_, scheduler| {
+            do scheduler.deschedule_running_task_and_then |_, task| {
+                let task_cell = Cell::new(task);
+                do self_.watcher.as_stream().close {
+                    let scheduler: ~Scheduler = Local::take();
+                    scheduler.resume_blocked_task_immediately(task_cell.take());
+                }
+            }
+        }
+    }
+}
+
+impl RtioSocket for UvTcpStream {
+    fn socket_name(&mut self) -> Result<SocketAddr, IoError> {
+        do self.home_for_io |self_| {
+            socket_name(Tcp, self_.watcher)
+        }
+    }
+}
+
+impl RtioTcpStream for UvTcpStream {
     fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
         do self.home_for_io_with_sched |self_, scheduler| {
             let result_cell = Cell::new_empty();
@@ -780,7 +747,7 @@ fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
                 let alloc: AllocCallback = |_| unsafe {
                     slice_to_uv_buf(*buf_ptr)
                 };
-                let mut watcher = self_.as_stream();
+                let mut watcher = self_.watcher.as_stream();
                 do watcher.read_start(alloc) |mut watcher, nread, _buf, status| {
 
                     // Stop reading so that no read callbacks are
@@ -816,7 +783,7 @@ fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task_cell = Cell::new(task);
                 let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
-                let mut watcher = self_.as_stream();
+                let mut watcher = self_.watcher.as_stream();
                 do watcher.write(buf) |_watcher, status| {
                     let result = if status.is_none() {
                         Ok(())
@@ -835,85 +802,7 @@ fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
             result_cell.take()
         }
     }
-}
-})
-
-rtiostream!(UvPipeStream)
-rtiostream!(UvTcpStream)
-
-pub struct UvPipeStream {
-    pipe: Pipe,
-    home: SchedHandle,
-}
-
-impl UvStream for UvPipeStream {
-    fn as_stream(&mut self) -> StreamWatcher { self.pipe.as_stream() }
-}
-
-impl HomingIO for UvPipeStream {
-    fn home<'r>(&'r mut self) -> &'r mut SchedHandle { &mut self.home }
-}
-
-impl Drop for UvPipeStream {
-    fn drop(&self) {
-        // FIXME(#4330): should not need a transmute
-        let this = unsafe { cast::transmute_mut(self) };
-        do this.home_for_io |self_| {
-            let scheduler: ~Scheduler = Local::take();
-            do scheduler.deschedule_running_task_and_then |_, task| {
-                let task_cell = Cell::new(task);
-                do self_.pipe.close {
-                    let scheduler: ~Scheduler = Local::take();
-                    scheduler.resume_blocked_task_immediately(task_cell.take());
-                }
-            }
-        }
-    }
-}
-
-impl UvPipeStream {
-    pub fn uv_pipe(&self) -> Pipe { self.pipe }
-}
 
-pub struct UvTcpStream {
-    watcher: TcpWatcher,
-    home: SchedHandle,
-}
-
-impl HomingIO for UvTcpStream {
-    fn home<'r>(&'r mut self) -> &'r mut SchedHandle { &mut self.home }
-}
-
-impl Drop for UvTcpStream {
-    fn drop(&self) {
-        // FIXME(#4330): should not need a transmute
-        let this = unsafe { cast::transmute_mut(self) };
-        do this.home_for_io |self_| {
-            let scheduler: ~Scheduler = Local::take();
-            do scheduler.deschedule_running_task_and_then |_, task| {
-                let task_cell = Cell::new(task);
-                do self_.watcher.as_stream().close {
-                    let scheduler: ~Scheduler = Local::take();
-                    scheduler.resume_blocked_task_immediately(task_cell.take());
-                }
-            }
-        }
-    }
-}
-
-impl UvStream for UvTcpStream {
-    fn as_stream(&mut self) -> StreamWatcher { self.watcher.as_stream() }
-}
-
-impl RtioSocket for UvTcpStream {
-    fn socket_name(&mut self) -> Result<SocketAddr, IoError> {
-        do self.home_for_io |self_| {
-            socket_name(Tcp, self_.watcher)
-        }
-    }
-}
-
-impl RtioTcpStream for UvTcpStream {
     fn peer_name(&mut self) -> Result<SocketAddr, IoError> {
         do self.home_for_io |self_| {
             socket_name(TcpPeer, self_.watcher)
@@ -924,7 +813,7 @@ fn control_congestion(&mut self) -> Result<(), IoError> {
         do self.home_for_io |self_| {
             let r = unsafe { uvll::tcp_nodelay(self_.watcher.native_handle(), 0 as c_int) };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -935,7 +824,7 @@ fn nodelay(&mut self) -> Result<(), IoError> {
         do self.home_for_io |self_| {
             let r = unsafe { uvll::tcp_nodelay(self_.watcher.native_handle(), 1 as c_int) };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -949,7 +838,7 @@ fn keepalive(&mut self, delay_in_seconds: uint) -> Result<(), IoError> {
                                     delay_in_seconds as c_uint)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -962,7 +851,7 @@ fn letdie(&mut self) -> Result<(), IoError> {
                 uvll::tcp_keepalive(self_.watcher.native_handle(), 0 as c_int, 0 as c_uint)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -1074,7 +963,7 @@ fn join_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> {
                 }
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -1090,7 +979,7 @@ fn leave_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> {
                 }
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -1104,7 +993,7 @@ fn loop_multicast_locally(&mut self) -> Result<(), IoError> {
                 uvll::udp_set_multicast_loop(self_.watcher.native_handle(), 1 as c_int)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -1118,7 +1007,7 @@ fn dont_loop_multicast_locally(&mut self) -> Result<(), IoError> {
                 uvll::udp_set_multicast_loop(self_.watcher.native_handle(), 0 as c_int)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -1132,7 +1021,7 @@ fn multicast_time_to_live(&mut self, ttl: int) -> Result<(), IoError> {
                 uvll::udp_set_multicast_ttl(self_.watcher.native_handle(), ttl as c_int)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -1146,7 +1035,7 @@ fn time_to_live(&mut self, ttl: int) -> Result<(), IoError> {
                 uvll::udp_set_ttl(self_.watcher.native_handle(), ttl as c_int)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -1160,7 +1049,7 @@ fn hear_broadcasts(&mut self) -> Result<(), IoError> {
                 uvll::udp_set_broadcast(self_.watcher.native_handle(), 1 as c_int)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -1174,7 +1063,7 @@ fn ignore_broadcasts(&mut self) -> Result<(), IoError> {
                 uvll::udp_set_broadcast(self_.watcher.native_handle(), 0 as c_int)
             };
 
-            match status_to_maybe_uv_error(r) {
+            match status_to_maybe_uv_error(self_.watcher, r) {
                 Some(err) => Err(uv_error_to_io_error(err)),
                 None => Ok(())
             }
@@ -1361,89 +1250,6 @@ fn flush(&mut self) -> Result<(), IoError> {
     }
 }
 
-pub struct UvProcess {
-    process: process::Process,
-
-    // Sadly, this structure must be created before we return it, so in that
-    // brief interim the `home` is None.
-    home: Option<SchedHandle>,
-
-    // All None until the process exits (exit_error may stay None)
-    priv exit_status: Option<int>,
-    priv term_signal: Option<int>,
-    priv exit_error: Option<UvError>,
-
-    // Used to store which task to wake up from the exit_cb
-    priv descheduled: Option<BlockedTask>,
-}
-
-impl HomingIO for UvProcess {
-    fn home<'r>(&'r mut self) -> &'r mut SchedHandle { self.home.get_mut_ref() }
-}
-
-impl Drop for UvProcess {
-    fn drop(&self) {
-        // FIXME(#4330): should not need a transmute
-        let this = unsafe { cast::transmute_mut(self) };
-
-        let close = |self_: &mut UvProcess| {
-            let scheduler: ~Scheduler = Local::take();
-            do scheduler.deschedule_running_task_and_then |_, task| {
-                let task = Cell::new(task);
-                do self_.process.close {
-                    let scheduler: ~Scheduler = Local::take();
-                    scheduler.resume_blocked_task_immediately(task.take());
-                }
-            }
-        };
-
-        // If home is none, then this process never actually successfully
-        // spawned, so there's no need to switch event loops
-        if this.home.is_none() {
-            close(this)
-        } else {
-            this.home_for_io(close)
-        }
-    }
-}
-
-impl RtioProcess for UvProcess {
-    fn id(&self) -> pid_t {
-        self.process.pid()
-    }
-
-    fn kill(&mut self, signal: int) -> Result<(), IoError> {
-        do self.home_for_io |self_| {
-            match self_.process.kill(signal) {
-                Ok(()) => Ok(()),
-                Err(uverr) => Err(uv_error_to_io_error(uverr))
-            }
-        }
-    }
-
-    fn wait(&mut self) -> int {
-        // Make sure (on the home scheduler) that we have an exit status listed
-        do self.home_for_io |self_| {
-            match self_.exit_status {
-                Some(*) => {}
-                None => {
-                    // If there's no exit code previously listed, then the
-                    // process's exit callback has yet to be invoked. We just
-                    // need to deschedule ourselves and wait to be reawoken.
-                    let scheduler: ~Scheduler = Local::take();
-                    do scheduler.deschedule_running_task_and_then |_, task| {
-                        assert!(self_.descheduled.is_none());
-                        self_.descheduled = Some(task);
-                    }
-                    assert!(self_.exit_status.is_some());
-                }
-            }
-        }
-
-        self.exit_status.unwrap()
-    }
-}
-
 #[test]
 fn test_simple_io_no_connect() {
     do run_in_newsched_task {
@@ -1860,6 +1666,7 @@ fn test_read_read_read() {
 }
 
 #[test]
+#[ignore(cfg(windows))] // FIXME #8816
 fn test_udp_twice() {
     do run_in_newsched_task {
         let server_addr = next_test_ip4();
@@ -1994,6 +1801,7 @@ fn file_test_uvio_full_simple_impl() {
 }
 
 #[test]
+#[ignore(cfg(windows))] // FIXME #8816
 fn file_test_uvio_full_simple() {
     do run_in_newsched_task {
         file_test_uvio_full_simple_impl();
index 24e070ca239d1bfbc855dfb799fae2c08dffabaa..d2e3b4176f96150dc443248e10d44bd6ba0e8f33 100644 (file)
 use libc;
 use prelude::*;
 use ptr;
+use str;
 use vec;
 
-pub use self::errors::*;
-
+pub static UNKNOWN: c_int = -1;
 pub static OK: c_int = 0;
-pub static EOF: c_int = -4095;
-pub static UNKNOWN: c_int = -4094;
-
-// uv-errno.h redefines error codes for windows, but not for unix...
-
-#[cfg(windows)]
-pub mod errors {
-    use libc::c_int;
+pub static EOF: c_int = 1;
+pub static EADDRINFO: c_int = 2;
+pub static EACCES: c_int = 3;
+pub static ECONNREFUSED: c_int = 12;
+pub static ECONNRESET: c_int = 13;
+pub static EPIPE: c_int = 36;
 
-    pub static EACCES: c_int = -4093;
-    pub static ECONNREFUSED: c_int = -4079;
-    pub static ECONNRESET: c_int = -4078;
-    pub static EPIPE: c_int = -4048;
+pub struct uv_err_t {
+    code: c_int,
+    sys_errno_: c_int
 }
-#[cfg(not(windows))]
-pub mod errors {
-    use libc;
-    use libc::c_int;
-
-    pub static EACCES: c_int = -libc::EACCES;
-    pub static ECONNREFUSED: c_int = -libc::ECONNREFUSED;
-    pub static ECONNRESET: c_int = -libc::ECONNRESET;
-    pub static EPIPE: c_int = -libc::EPIPE;
-}
-
-pub static PROCESS_SETUID: c_int = 1 << 0;
-pub static PROCESS_SETGID: c_int = 1 << 1;
-pub static PROCESS_WINDOWS_VERBATIM_ARGUMENTS: c_int = 1 << 2;
-pub static PROCESS_DETACHED: c_int = 1 << 3;
-pub static PROCESS_WINDOWS_HIDE: c_int = 1 << 4;
-
-pub static STDIO_IGNORE: c_int = 0x00;
-pub static STDIO_CREATE_PIPE: c_int = 0x01;
-pub static STDIO_INHERIT_FD: c_int = 0x02;
-pub static STDIO_INHERIT_STREAM: c_int = 0x04;
-pub static STDIO_READABLE_PIPE: c_int = 0x10;
-pub static STDIO_WRITABLE_PIPE: c_int = 0x20;
 
 pub struct uv_buf_t {
     base: *u8,
     len: libc::size_t,
 }
 
-pub struct uv_process_options_t {
-    exit_cb: uv_exit_cb,
-    file: *libc::c_char,
-    args: **libc::c_char,
-    env: **libc::c_char,
-    cwd: *libc::c_char,
-    flags: libc::c_uint,
-    stdio_count: libc::c_int,
-    stdio: *uv_stdio_container_t,
-    uid: uv_uid_t,
-    gid: uv_gid_t,
-}
-
-// These fields are private because they must be interfaced with through the
-// functions below.
-pub struct uv_stdio_container_t {
-    priv flags: libc::c_int,
-    priv stream: *uv_stream_t,
-}
-
 pub type uv_handle_t = c_void;
 pub type uv_loop_t = c_void;
 pub type uv_idle_t = c_void;
@@ -118,8 +72,6 @@ pub struct uv_stdio_container_t {
 pub type uv_stream_t = c_void;
 pub type uv_fs_t = c_void;
 pub type uv_udp_send_t = c_void;
-pub type uv_process_t = c_void;
-pub type uv_pipe_t = c_void;
 
 #[cfg(stage0)]
 pub type uv_idle_cb = *u8;
@@ -145,8 +97,6 @@ pub struct uv_stdio_container_t {
 pub type uv_timer_cb = *u8;
 #[cfg(stage0)]
 pub type uv_write_cb = *u8;
-#[cfg(stage0)]
-pub type uv_exit_cb = *u8;
 
 #[cfg(not(stage0))]
 pub type uv_idle_cb = extern "C" fn(handle: *uv_idle_t,
@@ -187,21 +137,12 @@ pub struct uv_stdio_container_t {
 #[cfg(not(stage0))]
 pub type uv_write_cb = extern "C" fn(handle: *uv_write_t,
                                      status: c_int);
-#[cfg(not(stage0))]
-pub type uv_exit_cb = extern "C" fn(handle: *uv_process_t,
-                                    exit_status: c_int,
-                                    term_signal: c_int);
 
 pub type sockaddr = c_void;
 pub type sockaddr_in = c_void;
 pub type sockaddr_in6 = c_void;
 pub type sockaddr_storage = c_void;
 
-#[cfg(unix)] pub type uv_uid_t = libc::types::os::arch::posix88::uid_t;
-#[cfg(unix)] pub type uv_gid_t = libc::types::os::arch::posix88::gid_t;
-#[cfg(windows)] pub type uv_uid_t = libc::c_uchar;
-#[cfg(windows)] pub type uv_gid_t = libc::c_uchar;
-
 #[deriving(Eq)]
 pub enum uv_handle_type {
     UV_UNKNOWN_HANDLE,
@@ -286,6 +227,7 @@ fn handle_sanity_check() {
 }
 
 #[test]
+#[ignore(cfg(windows))] // FIXME #8817
 #[fixed_stack_segment]
 #[inline(never)]
 fn request_sanity_check() {
@@ -546,12 +488,20 @@ pub unsafe fn read_stop(stream: *uv_stream_t) -> c_int {
     return rust_uv_read_stop(stream as *c_void);
 }
 
-pub unsafe fn strerror(err: c_int) -> *c_char {
+pub unsafe fn last_error(loop_handle: *c_void) -> uv_err_t {
     #[fixed_stack_segment]; #[inline(never)];
+
+    return rust_uv_last_error(loop_handle);
+}
+
+pub unsafe fn strerror(err: *uv_err_t) -> *c_char {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_strerror(err);
 }
-pub unsafe fn err_name(err: c_int) -> *c_char {
+pub unsafe fn err_name(err: *uv_err_t) -> *c_char {
     #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_err_name(err);
 }
 
@@ -705,45 +655,6 @@ pub unsafe fn fs_req_cleanup(req: *uv_fs_t) {
     rust_uv_fs_req_cleanup(req);
 }
 
-pub unsafe fn spawn(loop_ptr: *c_void, result: *uv_process_t,
-                    options: uv_process_options_t) -> c_int {
-    #[fixed_stack_segment]; #[inline(never)];
-    return rust_uv_spawn(loop_ptr, result, options);
-}
-
-pub unsafe fn process_kill(p: *uv_process_t, signum: c_int) -> c_int {
-    #[fixed_stack_segment]; #[inline(never)];
-    return rust_uv_process_kill(p, signum);
-}
-
-pub unsafe fn process_pid(p: *uv_process_t) -> c_int {
-    #[fixed_stack_segment]; #[inline(never)];
-    return rust_uv_process_pid(p);
-}
-
-pub unsafe fn set_stdio_container_flags(c: *uv_stdio_container_t,
-                                        flags: libc::c_int) {
-    #[fixed_stack_segment]; #[inline(never)];
-    rust_set_stdio_container_flags(c, flags);
-}
-
-pub unsafe fn set_stdio_container_fd(c: *uv_stdio_container_t,
-                                     fd: libc::c_int) {
-    #[fixed_stack_segment]; #[inline(never)];
-    rust_set_stdio_container_fd(c, fd);
-}
-
-pub unsafe fn set_stdio_container_stream(c: *uv_stdio_container_t,
-                                         stream: *uv_stream_t) {
-    #[fixed_stack_segment]; #[inline(never)];
-    rust_set_stdio_container_stream(c, stream);
-}
-
-pub unsafe fn pipe_init(loop_ptr: *c_void, p: *uv_pipe_t, ipc: c_int) -> c_int {
-    #[fixed_stack_segment]; #[inline(never)];
-    rust_uv_pipe_init(loop_ptr, p, ipc)
-}
-
 // data access helpers
 pub unsafe fn get_result_from_fs_req(req: *uv_fs_t) -> c_int {
     #[fixed_stack_segment]; #[inline(never)];
@@ -810,6 +721,22 @@ pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> size_t {
 
     return rust_uv_get_len_from_buf(buf);
 }
+pub unsafe fn get_last_err_info(uv_loop: *c_void) -> ~str {
+    let err = last_error(uv_loop);
+    let err_ptr = ptr::to_unsafe_ptr(&err);
+    let err_name = str::raw::from_c_str(err_name(err_ptr));
+    let err_msg = str::raw::from_c_str(strerror(err_ptr));
+    return fmt!("LIBUV ERROR: name: %s msg: %s",
+                    err_name, err_msg);
+}
+
+pub unsafe fn get_last_err_data(uv_loop: *c_void) -> uv_err_data {
+    let err = last_error(uv_loop);
+    let err_ptr = ptr::to_unsafe_ptr(&err);
+    let err_name = str::raw::from_c_str(err_name(err_ptr));
+    let err_msg = str::raw::from_c_str(strerror(err_ptr));
+    uv_err_data { err_name: err_name, err_msg: err_msg }
+}
 
 pub struct uv_err_data {
     err_name: ~str,
@@ -842,8 +769,9 @@ fn rust_uv_async_init(loop_handle: *c_void,
                           cb: uv_async_cb) -> c_int;
     fn rust_uv_tcp_init(loop_handle: *c_void, handle_ptr: *uv_tcp_t) -> c_int;
     fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8, len: size_t);
-    fn rust_uv_strerror(err: c_int) -> *c_char;
-    fn rust_uv_err_name(err: c_int) -> *c_char;
+    fn rust_uv_last_error(loop_handle: *c_void) -> uv_err_t;
+    fn rust_uv_strerror(err: *uv_err_t) -> *c_char;
+    fn rust_uv_err_name(err: *uv_err_t) -> *c_char;
     fn rust_uv_ip4_addrp(ip: *u8, port: c_int) -> *sockaddr_in;
     fn rust_uv_ip6_addrp(ip: *u8, port: c_int) -> *sockaddr_in6;
     fn rust_uv_free_ip4_addr(addr: *sockaddr_in);
@@ -929,13 +857,4 @@ fn rust_uv_fs_close(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int,
     fn rust_uv_set_data_for_req(req: *c_void, data: *c_void);
     fn rust_uv_get_base_from_buf(buf: uv_buf_t) -> *u8;
     fn rust_uv_get_len_from_buf(buf: uv_buf_t) -> size_t;
-    fn rust_uv_spawn(loop_ptr: *c_void, outptr: *uv_process_t,
-                     options: uv_process_options_t) -> c_int;
-    fn rust_uv_process_kill(p: *uv_process_t, signum: c_int) -> c_int;
-    fn rust_uv_process_pid(p: *uv_process_t) -> c_int;
-    fn rust_set_stdio_container_flags(c: *uv_stdio_container_t, flags: c_int);
-    fn rust_set_stdio_container_fd(c: *uv_stdio_container_t, fd: c_int);
-    fn rust_set_stdio_container_stream(c: *uv_stdio_container_t,
-                                       stream: *uv_stream_t);
-    fn rust_uv_pipe_init(loop_ptr: *c_void, p: *uv_pipe_t, ipc: c_int) -> c_int;
 }
index b91aac2224401a532dcd9f54afda9ceb7f8a144f..7fc2deff97d8bd34538c1d3c4a236c05dcba0c03 100644 (file)
 
 //! Process spawning.
 
+#[allow(missing_doc)];
+
+use c_str::ToCStr;
 use cast;
-use cell::Cell;
+use clone::Clone;
 use comm::{stream, SharedChan, GenericChan, GenericPort};
-#[cfg(not(windows))]
+use io;
+use libc::{pid_t, c_void, c_int};
 use libc;
-use libc::{pid_t, c_int};
+use option::{Some, None};
+use os;
 use prelude::*;
+use ptr;
 use task;
 use vec::ImmutableVector;
 
-use rt::io;
-use rt::local::Local;
-use rt::rtio::{IoFactoryObject, RtioProcessObject, RtioProcess, IoFactory};
-use rt::uv::process;
-
 /**
  * A value representing a child process.
  *
  * for the process to terminate.
  */
 pub struct Process {
+
     /// The unique id of the process (this should never be negative).
     priv pid: pid_t,
 
-    /// The internal handle to the underlying libuv process.
-    priv handle: ~RtioProcessObject,
+    /**
+     * A handle to the process - on unix this will always be NULL, but on
+     * windows it will be a HANDLE to the process, which will prevent the
+     * pid being re-used until the handle is closed.
+     */
+    priv handle: *(),
 
-    /// Some(fd), or None when stdin is being redirected from a fd not created
-    /// by Process::new.
-    priv input: Option<~io::Writer>,
+    /// Some(fd), or None when stdin is being redirected from a fd not created by Process::new.
+    priv input: Option<c_int>,
 
-    /// Some(file), or None when stdout is being redirected to a fd not created
-    /// by Process::new.
-    priv output: Option<~io::Reader>,
+    /// Some(file), or None when stdout is being redirected to a fd not created by Process::new.
+    priv output: Option<*libc::FILE>,
 
-    /// Some(file), or None when stderr is being redirected to a fd not created
-    /// by Process::new.
-    priv error: Option<~io::Reader>,
+    /// Some(file), or None when stderr is being redirected to a fd not created by Process::new.
+    priv error: Option<*libc::FILE>,
+
+    /// None until finish() is called.
+    priv exit_code: Option<int>,
 }
 
 /// Options that can be given when starting a Process.
@@ -87,27 +93,26 @@ pub struct ProcessOptions<'self> {
      * If this is None then a new pipe will be created for the new program's
      * output and Process.output() will provide a Reader to read from this pipe.
      *
-     * If this is Some(file-descriptor) then the new process will write its
-     * output to the given file descriptor, Process.output_redirected() will
-     * return true, and Process.output() will fail.
+     * If this is Some(file-descriptor) then the new process will write its output
+     * to the given file descriptor, Process.output_redirected() will return
+     * true, and Process.output() will fail.
      */
     out_fd: Option<c_int>,
 
     /**
-     * If this is None then a new pipe will be created for the new progam's
-     * error stream and Process.error() will provide a Reader to read from this
-     * pipe.
+     * If this is None then a new pipe will be created for the new program's
+     * error stream and Process.error() will provide a Reader to read from this pipe.
      *
-     * If this is Some(file-descriptor) then the new process will write its
-     * error output to the given file descriptor, Process.error_redirected()
-     * will return true, and and Process.error() will fail.
+     * If this is Some(file-descriptor) then the new process will write its error output
+     * to the given file descriptor, Process.error_redirected() will return true, and
+     * and Process.error() will fail.
      */
     err_fd: Option<c_int>,
 }
 
-impl<'self> ProcessOptions<'self> {
+impl <'self> ProcessOptions<'self> {
     /// Return a ProcessOptions that has None in every field.
-    pub fn new() -> ProcessOptions {
+    pub fn new<'a>() -> ProcessOptions<'a> {
         ProcessOptions {
             env: None,
             dir: None,
@@ -120,6 +125,7 @@ pub fn new() -> ProcessOptions {
 
 /// The output of a finished process.
 pub struct ProcessOutput {
+
     /// The status (exit code) of the process.
     status: int,
 
@@ -142,159 +148,223 @@ impl Process {
      *             the working directory and the standard IO streams.
      */
     pub fn new(prog: &str, args: &[~str],
-               options: ProcessOptions) -> Option<Process> {
-        // First, translate all the stdio options into their libuv equivalents
-        let (uv_stdin, stdin) = match options.in_fd {
-            Some(fd) => (process::InheritFd(fd), None),
+               options: ProcessOptions)
+               -> Process {
+        #[fixed_stack_segment]; #[inline(never)];
+
+        let (in_pipe, in_fd) = match options.in_fd {
             None => {
-                let p = io::pipe::PipeStream::new().expect("need stdin pipe");
-                (process::CreatePipe(p.uv_pipe(), true, false),
-                 Some(~p as ~io::Writer))
-            }
+                let pipe = os::pipe();
+                (Some(pipe), pipe.input)
+            },
+            Some(fd) => (None, fd)
         };
-        let (uv_stdout, stdout) = match options.out_fd {
-            Some(fd) => (process::InheritFd(fd), None),
+        let (out_pipe, out_fd) = match options.out_fd {
             None => {
-                let p = io::pipe::PipeStream::new().expect("need stdout pipe");
-                (process::CreatePipe(p.uv_pipe(), false, true),
-                 Some(~p as ~io::Reader))
-            }
+                let pipe = os::pipe();
+                (Some(pipe), pipe.out)
+            },
+            Some(fd) => (None, fd)
         };
-        let (uv_stderr, stderr) = match options.err_fd {
-            Some(fd) => (process::InheritFd(fd), None),
+        let (err_pipe, err_fd) = match options.err_fd {
             None => {
-                let p = io::pipe::PipeStream::new().expect("need stderr pipe");
-                (process::CreatePipe(p.uv_pipe(), false, true),
-                 Some(~p as ~io::Reader))
-            }
+                let pipe = os::pipe();
+                (Some(pipe), pipe.out)
+            },
+            Some(fd) => (None, fd)
         };
 
-        // Next, massage our options into the libuv options
-        let dir = options.dir.map(|d| d.to_str());
-        let dir = dir.map(|d| d.as_slice());
-        let config = process::Config {
-            program: prog,
-            args: args,
-            env: options.env.map(|e| e.as_slice()),
-            cwd: dir,
-            io: [uv_stdin, uv_stdout, uv_stderr],
-        };
+        let res = spawn_process_os(prog, args, options.env.clone(), options.dir,
+                                   in_fd, out_fd, err_fd);
 
-        // Finally, actually spawn the process
         unsafe {
-            let io: *mut IoFactoryObject = Local::unsafe_borrow();
-            match (*io).spawn(&config) {
-                Ok(handle) => {
-                    Some(Process {
-                        pid: handle.id(),
-                        handle: handle,
-                        input: stdin,
-                        output: stdout,
-                        error: stderr,
-                    })
-                }
-                Err(*) => { None }
-            }
+            for pipe in in_pipe.iter() { libc::close(pipe.input); }
+            for pipe in out_pipe.iter() { libc::close(pipe.out); }
+            for pipe in err_pipe.iter() { libc::close(pipe.out); }
+        }
+
+        Process {
+            pid: res.pid,
+            handle: res.handle,
+            input: in_pipe.map(|pipe| pipe.out),
+            output: out_pipe.map(|pipe| os::fdopen(pipe.input)),
+            error: err_pipe.map(|pipe| os::fdopen(pipe.input)),
+            exit_code: None,
         }
     }
 
     /// Returns the unique id of the process
     pub fn get_id(&self) -> pid_t { self.pid }
 
+    fn input_fd(&mut self) -> c_int {
+        match self.input {
+            Some(fd) => fd,
+            None => fail!("This Process's stdin was redirected to an \
+                           existing file descriptor.")
+        }
+    }
+
+    fn output_file(&mut self) -> *libc::FILE {
+        match self.output {
+            Some(file) => file,
+            None => fail!("This Process's stdout was redirected to an \
+                           existing file descriptor.")
+        }
+    }
+
+    fn error_file(&mut self) -> *libc::FILE {
+        match self.error {
+            Some(file) => file,
+            None => fail!("This Process's stderr was redirected to an \
+                           existing file descriptor.")
+        }
+    }
+
     /**
-     * Returns a rt::io::Writer that can be used to write to this Process's
-     * stdin.
+     * Returns whether this process is reading its stdin from an existing file
+     * descriptor rather than a pipe that was created specifically for this
+     * process.
      *
-     * Fails if this Process's stdin was redirected to an existing file
-     * descriptor.
+     * If this method returns true then self.input() will fail.
      */
-    pub fn input<'a>(&'a mut self) -> &'a mut io::Writer {
-        let ret: &mut io::Writer = *self.input.get_mut_ref();
-        return ret;
+    pub fn input_redirected(&self) -> bool {
+        self.input.is_none()
     }
 
     /**
-     * Returns a rt::io::Reader that can be used to read from this Process's
-     * stdout.
+     * Returns whether this process is writing its stdout to an existing file
+     * descriptor rather than a pipe that was created specifically for this
+     * process.
      *
-     * Fails if this Process's stdout was redirected to an existing file
-     * descriptor.
+     * If this method returns true then self.output() will fail.
      */
-    pub fn output<'a>(&'a mut self) -> &'a mut io::Reader {
-        let ret: &mut io::Reader = *self.output.get_mut_ref();
-        return ret;
+    pub fn output_redirected(&self) -> bool {
+        self.output.is_none()
     }
 
     /**
-     * Returns a rt::io::Reader that can be used to read from this Process's
-     * stderr.
+     * Returns whether this process is writing its stderr to an existing file
+     * descriptor rather than a pipe that was created specifically for this
+     * process.
      *
-     * Fails if this Process's stderr was redirected to an existing file
-     * descriptor.
+     * If this method returns true then self.error() will fail.
      */
-    pub fn error<'a>(&'a mut self) -> &'a mut io::Reader {
-        let ret: &mut io::Reader = *self.error.get_mut_ref();
-        return ret;
+    pub fn error_redirected(&self) -> bool {
+        self.error.is_none()
     }
 
     /**
-     * Closes the handle to stdin, waits for the child process to terminate, and
-     * returns the exit code.
+     * Returns an io::Writer that can be used to write to this Process's stdin.
      *
-     * If the child has already been finished then the exit code is returned.
+     * Fails if this Process's stdin was redirected to an existing file descriptor.
      */
-    pub fn finish(&mut self) -> int {
-        // We're not going to be giving any more input, so close the input by
-        // destroying it. Also, if the output is desired, then
-        // finish_with_output is called so we discard all the outputs here. Note
-        // that the process may not terminate if we don't destroy stdio because
-        // it'll be waiting in a write which we'll just never read.
-        self.input.take();
-        self.output.take();
-        self.error.take();
+    pub fn input(&mut self) -> @io::Writer {
+        // FIXME: the Writer can still be used after self is destroyed: #2625
+       io::fd_writer(self.input_fd(), false)
+    }
 
-        self.handle.wait()
+    /**
+     * Returns an io::Reader that can be used to read from this Process's stdout.
+     *
+     * Fails if this Process's stdout was redirected to an existing file descriptor.
+     */
+    pub fn output(&mut self) -> @io::Reader {
+        // FIXME: the Reader can still be used after self is destroyed: #2625
+        io::FILE_reader(self.output_file(), false)
     }
 
     /**
-     * Closes the handle to stdin, waits for the child process to terminate,
-     * and reads and returns all remaining output of stdout and stderr, along
-     * with the exit code.
+     * Returns an io::Reader that can be used to read from this Process's stderr.
      *
-     * If the child has already been finished then the exit code and any
-     * remaining unread output of stdout and stderr will be returned.
+     * Fails if this Process's stderr was redirected to an existing file descriptor.
+     */
+    pub fn error(&mut self) -> @io::Reader {
+        // FIXME: the Reader can still be used after self is destroyed: #2625
+        io::FILE_reader(self.error_file(), false)
+    }
+
+    /**
+     * Closes the handle to the child process's stdin.
      *
-     * This method will fail if the child process's stdout or stderr streams
-     * were redirected to existing file descriptors, or if this method has
-     * already been called.
+     * If this process is reading its stdin from an existing file descriptor, then this
+     * method does nothing.
      */
-    pub fn finish_with_output(&mut self) -> ProcessOutput {
-        // This should probably be a helper method in rt::io
-        fn read_everything(input: &mut io::Reader) -> ~[u8] {
-            let mut result = ~[];
-            let mut buf = [0u8, ..1024];
-            loop {
-                match input.read(buf) {
-                    Some(i) => { result = result + buf.slice_to(i) }
-                    None => break
+    pub fn close_input(&mut self) {
+        #[fixed_stack_segment]; #[inline(never)];
+        match self.input {
+            Some(-1) | None => (),
+            Some(fd) => {
+                unsafe {
+                    libc::close(fd);
                 }
+                self.input = Some(-1);
             }
-            return result;
         }
+    }
+
+    fn close_outputs(&mut self) {
+        #[fixed_stack_segment]; #[inline(never)];
+        fclose_and_null(&mut self.output);
+        fclose_and_null(&mut self.error);
+
+        fn fclose_and_null(f_opt: &mut Option<*libc::FILE>) {
+            #[allow(cstack)]; // fixed_stack_segment declared on enclosing fn
+            match *f_opt {
+                Some(f) if !f.is_null() => {
+                    unsafe {
+                        libc::fclose(f);
+                        *f_opt = Some(0 as *libc::FILE);
+                    }
+                },
+                _ => ()
+            }
+        }
+    }
+
+    /**
+     * Closes the handle to stdin, waits for the child process to terminate,
+     * and returns the exit code.
+     *
+     * If the child has already been finished then the exit code is returned.
+     */
+    pub fn finish(&mut self) -> int {
+        for &code in self.exit_code.iter() {
+            return code;
+        }
+        self.close_input();
+        let code = waitpid(self.pid);
+        self.exit_code = Some(code);
+        return code;
+    }
 
+    /**
+     * Closes the handle to stdin, waits for the child process to terminate, and reads
+     * and returns all remaining output of stdout and stderr, along with the exit code.
+     *
+     * If the child has already been finished then the exit code and any remaining
+     * unread output of stdout and stderr will be returned.
+     *
+     * This method will fail if the child process's stdout or stderr streams were
+     * redirected to existing file descriptors.
+     */
+    pub fn finish_with_output(&mut self) -> ProcessOutput {
+        let output_file = self.output_file();
+        let error_file = self.error_file();
+
+        // Spawn two entire schedulers to read both stdout and sterr
+        // in parallel so we don't deadlock while blocking on one
+        // or the other. FIXME (#2625): Surely there's a much more
+        // clever way to do this.
         let (p, ch) = stream();
         let ch = SharedChan::new(ch);
         let ch_clone = ch.clone();
-
-        let stderr = Cell::new(self.error.take().unwrap());
-        do task::spawn {
-            let output = read_everything(stderr.take());
-            ch.send((2, output));
+        do task::spawn_sched(task::SingleThreaded) {
+            let errput = io::FILE_reader(error_file, false);
+            ch.send((2, errput.read_whole_stream()));
         }
-        let stdout = Cell::new(self.output.take().unwrap());
-        do task::spawn {
-            let output = read_everything(stdout.take());
-            ch_clone.send((1, output));
+        do task::spawn_sched(task::SingleThreaded) {
+            let output = io::FILE_reader(output_file, false);
+            ch_clone.send((1, output.read_whole_stream()));
         }
 
         let status = self.finish();
@@ -312,6 +382,40 @@ fn read_everything(input: &mut io::Reader) -> ~[u8] {
                               error: errs};
     }
 
+    fn destroy_internal(&mut self, force: bool) {
+        // if the process has finished, and therefore had waitpid called,
+        // and we kill it, then on unix we might ending up killing a
+        // newer process that happens to have the same (re-used) id
+        if self.exit_code.is_none() {
+            killpid(self.pid, force);
+            self.finish();
+        }
+
+        #[cfg(windows)]
+        fn killpid(pid: pid_t, _force: bool) {
+            #[fixed_stack_segment]; #[inline(never)];
+            unsafe {
+                libc::funcs::extra::kernel32::TerminateProcess(
+                    cast::transmute(pid), 1);
+            }
+        }
+
+        #[cfg(unix)]
+        fn killpid(pid: pid_t, force: bool) {
+            #[fixed_stack_segment]; #[inline(never)];
+
+            let signal = if force {
+                libc::consts::os::posix88::SIGKILL
+            } else {
+                libc::consts::os::posix88::SIGTERM
+            };
+
+            unsafe {
+                libc::funcs::posix88::signal::kill(pid, signal as c_int);
+            }
+        }
+    }
+
     /**
      * Terminates the process, giving it a chance to clean itself up if
      * this is supported by the operating system.
@@ -319,12 +423,7 @@ fn read_everything(input: &mut io::Reader) -> ~[u8] {
      * On Posix OSs SIGTERM will be sent to the process. On Win32
      * TerminateProcess(..) will be called.
      */
-    pub fn destroy(&mut self) {
-        #[cfg(windows)]      fn sigterm() -> int { 15 }
-        #[cfg(not(windows))] fn sigterm() -> int { libc::SIGTERM as int }
-        self.handle.kill(sigterm());
-        self.finish();
-    }
+    pub fn destroy(&mut self) { self.destroy_internal(false); }
 
     /**
      * Terminates the process as soon as possible without giving it a
@@ -333,22 +432,378 @@ pub fn destroy(&mut self) {
      * On Posix OSs SIGKILL will be sent to the process. On Win32
      * TerminateProcess(..) will be called.
      */
-    pub fn force_destroy(&mut self) {
-        #[cfg(windows)]      fn sigkill() -> int { 9 }
-        #[cfg(not(windows))] fn sigkill() -> int { libc::SIGKILL as int }
-        self.handle.kill(sigkill());
-        self.finish();
-    }
+    pub fn force_destroy(&mut self) { self.destroy_internal(true); }
 }
 
 impl Drop for Process {
     fn drop(&self) {
         // FIXME(#4330) Need self by value to get mutability.
         let mut_self: &mut Process = unsafe { cast::transmute(self) };
+
         mut_self.finish();
+        mut_self.close_outputs();
+        free_handle(self.handle);
+    }
+}
+
+struct SpawnProcessResult {
+    pid: pid_t,
+    handle: *(),
+}
+
+#[cfg(windows)]
+fn spawn_process_os(prog: &str, args: &[~str],
+                    env: Option<~[(~str, ~str)]>,
+                    dir: Option<&Path>,
+                    in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
+    use libc::consts::os::extra::{
+        TRUE, FALSE,
+        STARTF_USESTDHANDLES,
+        INVALID_HANDLE_VALUE,
+        DUPLICATE_SAME_ACCESS
+    };
+    use libc::funcs::extra::kernel32::{
+        GetCurrentProcess,
+        DuplicateHandle,
+        CloseHandle,
+        CreateProcessA
+    };
+    use libc::funcs::extra::msvcrt::get_osfhandle;
+
+    use sys;
+
+    unsafe {
+
+        let mut si = zeroed_startupinfo();
+        si.cb = sys::size_of::<STARTUPINFO>() as DWORD;
+        si.dwFlags = STARTF_USESTDHANDLES;
+
+        let cur_proc = GetCurrentProcess();
+
+        let orig_std_in = get_osfhandle(in_fd) as HANDLE;
+        if orig_std_in == INVALID_HANDLE_VALUE as HANDLE {
+            fail!("failure in get_osfhandle: %s", os::last_os_error());
+        }
+        if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput,
+                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+            fail!("failure in DuplicateHandle: %s", os::last_os_error());
+        }
+
+        let orig_std_out = get_osfhandle(out_fd) as HANDLE;
+        if orig_std_out == INVALID_HANDLE_VALUE as HANDLE {
+            fail!("failure in get_osfhandle: %s", os::last_os_error());
+        }
+        if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput,
+                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+            fail!("failure in DuplicateHandle: %s", os::last_os_error());
+        }
+
+        let orig_std_err = get_osfhandle(err_fd) as HANDLE;
+        if orig_std_err == INVALID_HANDLE_VALUE as HANDLE {
+            fail!("failure in get_osfhandle: %s", os::last_os_error());
+        }
+        if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError,
+                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+            fail!("failure in DuplicateHandle: %s", os::last_os_error());
+        }
+
+        let cmd = make_command_line(prog, args);
+        let mut pi = zeroed_process_information();
+        let mut create_err = None;
+
+        do with_envp(env) |envp| {
+            do with_dirp(dir) |dirp| {
+                do cmd.with_c_str |cmdp| {
+                    let created = CreateProcessA(ptr::null(), cast::transmute(cmdp),
+                                                 ptr::mut_null(), ptr::mut_null(), TRUE,
+                                                 0, envp, dirp, &mut si, &mut pi);
+                    if created == FALSE {
+                        create_err = Some(os::last_os_error());
+                    }
+                }
+            }
+        }
+
+        CloseHandle(si.hStdInput);
+        CloseHandle(si.hStdOutput);
+        CloseHandle(si.hStdError);
+
+        for msg in create_err.iter() {
+            fail!("failure in CreateProcess: %s", *msg);
+        }
+
+        // We close the thread handle because we don't care about keeping the thread id valid,
+        // and we aren't keeping the thread handle around to be able to close it later. We don't
+        // close the process handle however because we want the process id to stay valid at least
+        // until the calling code closes the process handle.
+        CloseHandle(pi.hThread);
+
+        SpawnProcessResult {
+            pid: pi.dwProcessId as pid_t,
+            handle: pi.hProcess as *()
+        }
+    }
+}
+
+#[cfg(windows)]
+fn zeroed_startupinfo() -> libc::types::os::arch::extra::STARTUPINFO {
+    libc::types::os::arch::extra::STARTUPINFO {
+        cb: 0,
+        lpReserved: ptr::mut_null(),
+        lpDesktop: ptr::mut_null(),
+        lpTitle: ptr::mut_null(),
+        dwX: 0,
+        dwY: 0,
+        dwXSize: 0,
+        dwYSize: 0,
+        dwXCountChars: 0,
+        dwYCountCharts: 0,
+        dwFillAttribute: 0,
+        dwFlags: 0,
+        wShowWindow: 0,
+        cbReserved2: 0,
+        lpReserved2: ptr::mut_null(),
+        hStdInput: ptr::mut_null(),
+        hStdOutput: ptr::mut_null(),
+        hStdError: ptr::mut_null()
+    }
+}
+
+#[cfg(windows)]
+fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMATION {
+    libc::types::os::arch::extra::PROCESS_INFORMATION {
+        hProcess: ptr::mut_null(),
+        hThread: ptr::mut_null(),
+        dwProcessId: 0,
+        dwThreadId: 0
+    }
+}
+
+// FIXME: this is only pub so it can be tested (see issue #4536)
+#[cfg(windows)]
+pub fn make_command_line(prog: &str, args: &[~str]) -> ~str {
+    let mut cmd = ~"";
+    append_arg(&mut cmd, prog);
+    for arg in args.iter() {
+        cmd.push_char(' ');
+        append_arg(&mut cmd, *arg);
+    }
+    return cmd;
+
+    fn append_arg(cmd: &mut ~str, arg: &str) {
+        let quote = arg.iter().any(|c| c == ' ' || c == '\t');
+        if quote {
+            cmd.push_char('"');
+        }
+        for i in range(0u, arg.len()) {
+            append_char_at(cmd, arg, i);
+        }
+        if quote {
+            cmd.push_char('"');
+        }
+    }
+
+    fn append_char_at(cmd: &mut ~str, arg: &str, i: uint) {
+        match arg[i] as char {
+            '"' => {
+                // Escape quotes.
+                cmd.push_str("\\\"");
+            }
+            '\\' => {
+                if backslash_run_ends_in_quote(arg, i) {
+                    // Double all backslashes that are in runs before quotes.
+                    cmd.push_str("\\\\");
+                } else {
+                    // Pass other backslashes through unescaped.
+                    cmd.push_char('\\');
+                }
+            }
+            c => {
+                cmd.push_char(c);
+            }
+        }
+    }
+
+    fn backslash_run_ends_in_quote(s: &str, mut i: uint) -> bool {
+        while i < s.len() && s[i] as char == '\\' {
+            i += 1;
+        }
+        return i < s.len() && s[i] as char == '"';
+    }
+}
+
+#[cfg(unix)]
+fn spawn_process_os(prog: &str, args: &[~str],
+                    env: Option<~[(~str, ~str)]>,
+                    dir: Option<&Path>,
+                    in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
+    use libc::funcs::bsd44::getdtablesize;
+
+    mod rustrt {
+        use libc::c_void;
+
+        #[abi = "cdecl"]
+        extern {
+            pub fn rust_unset_sigprocmask();
+            pub fn rust_set_environ(envp: *c_void);
+        }
+    }
+
+    unsafe {
+
+        let pid = fork();
+        if pid < 0 {
+            fail!("failure in fork: %s", os::last_os_error());
+        } else if pid > 0 {
+            return SpawnProcessResult {pid: pid, handle: ptr::null()};
+        }
+
+        rustrt::rust_unset_sigprocmask();
+
+        if dup2(in_fd, 0) == -1 {
+            fail!("failure in dup2(in_fd, 0): %s", os::last_os_error());
+        }
+        if dup2(out_fd, 1) == -1 {
+            fail!("failure in dup2(out_fd, 1): %s", os::last_os_error());
+        }
+        if dup2(err_fd, 2) == -1 {
+            fail!("failure in dup3(err_fd, 2): %s", os::last_os_error());
+        }
+        // close all other fds
+        for fd in range(3, getdtablesize()).invert() {
+            close(fd as c_int);
+        }
+
+        do with_dirp(dir) |dirp| {
+            if !dirp.is_null() && chdir(dirp) == -1 {
+                fail!("failure in chdir: %s", os::last_os_error());
+            }
+        }
+
+        do with_envp(env) |envp| {
+            if !envp.is_null() {
+                rustrt::rust_set_environ(envp);
+            }
+            do with_argv(prog, args) |argv| {
+                execvp(*argv, argv);
+                // execvp only returns if an error occurred
+                fail!("failure in execvp: %s", os::last_os_error());
+            }
+        }
+    }
+}
+
+#[cfg(unix)]
+fn with_argv<T>(prog: &str, args: &[~str], cb: &fn(**libc::c_char) -> T) -> T {
+    use vec;
+
+    // We can't directly convert `str`s into `*char`s, as someone needs to hold
+    // a reference to the intermediary byte buffers. So first build an array to
+    // hold all the ~[u8] byte strings.
+    let mut tmps = vec::with_capacity(args.len() + 1);
+
+    tmps.push(prog.to_c_str());
+
+    for arg in args.iter() {
+        tmps.push(arg.to_c_str());
+    }
+
+    // Next, convert each of the byte strings into a pointer. This is
+    // technically unsafe as the caller could leak these pointers out of our
+    // scope.
+    let mut ptrs = do tmps.map |tmp| {
+        tmp.with_ref(|buf| buf)
+    };
+
+    // Finally, make sure we add a null pointer.
+    ptrs.push(ptr::null());
+
+    ptrs.as_imm_buf(|buf, _| cb(buf))
+}
+
+#[cfg(unix)]
+fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: &fn(*c_void) -> T) -> T {
+    use vec;
+
+    // On posixy systems we can pass a char** for envp, which is a
+    // null-terminated array of "k=v\n" strings. Like `with_argv`, we have to
+    // have a temporary buffer to hold the intermediary `~[u8]` byte strings.
+    match env {
+        Some(env) => {
+            let mut tmps = vec::with_capacity(env.len());
+
+            for pair in env.iter() {
+                // Use of match here is just to workaround limitations
+                // in the stage0 irrefutable pattern impl.
+                let kv = fmt!("%s=%s", pair.first(), pair.second());
+                tmps.push(kv.to_c_str());
+            }
+
+            // Once again, this is unsafe.
+            let mut ptrs = do tmps.map |tmp| {
+                tmp.with_ref(|buf| buf)
+            };
+            ptrs.push(ptr::null());
+
+            do ptrs.as_imm_buf |buf, _| {
+                unsafe { cb(cast::transmute(buf)) }
+            }
+        }
+        _ => cb(ptr::null())
+    }
+}
+
+#[cfg(windows)]
+fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T {
+    // On win32 we pass an "environment block" which is not a char**, but
+    // rather a concatenation of null-terminated k=v\0 sequences, with a final
+    // \0 to terminate.
+    match env {
+        Some(env) => {
+            let mut blk = ~[];
+
+            for pair in env.iter() {
+                let kv = fmt!("%s=%s", pair.first(), pair.second());
+                blk.push_all(kv.as_bytes());
+                blk.push(0);
+            }
+
+            blk.push(0);
+
+            do blk.as_imm_buf |p, _len| {
+                unsafe { cb(cast::transmute(p)) }
+            }
+        }
+        _ => cb(ptr::mut_null())
+    }
+}
+
+fn with_dirp<T>(d: Option<&Path>, cb: &fn(*libc::c_char) -> T) -> T {
+    match d {
+      Some(dir) => dir.with_c_str(|buf| cb(buf)),
+      None => cb(ptr::null())
+    }
+}
+
+#[cfg(windows)]
+fn free_handle(handle: *()) {
+    #[fixed_stack_segment]; #[inline(never)];
+    unsafe {
+        libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle));
     }
 }
 
+#[cfg(unix)]
+fn free_handle(_handle: *()) {
+    // unix has no process handle object, just a pid
+}
+
 /**
  * Spawns a process and waits for it to terminate. The process will
  * inherit the current stdin/stdout/stderr file descriptors.
@@ -369,7 +824,7 @@ pub fn process_status(prog: &str, args: &[~str]) -> int {
         in_fd: Some(0),
         out_fd: Some(1),
         err_fd: Some(2)
-    }).unwrap();
+    });
     prog.finish()
 }
 
@@ -386,38 +841,162 @@ pub fn process_status(prog: &str, args: &[~str]) -> int {
  * The process's stdout/stderr output and exit code.
  */
 pub fn process_output(prog: &str, args: &[~str]) -> ProcessOutput {
-    let mut prog = Process::new(prog, args, ProcessOptions::new()).unwrap();
+    let mut prog = Process::new(prog, args, ProcessOptions::new());
     prog.finish_with_output()
 }
 
+/**
+ * Waits for a process to exit and returns the exit code, failing
+ * if there is no process with the specified id.
+ *
+ * Note that this is private to avoid race conditions on unix where if
+ * a user calls waitpid(some_process.get_id()) then some_process.finish()
+ * and some_process.destroy() and some_process.finalize() will then either
+ * operate on a none-existent process or, even worse, on a newer process
+ * with the same id.
+ */
+fn waitpid(pid: pid_t) -> int {
+    return waitpid_os(pid);
+
+    #[cfg(windows)]
+    fn waitpid_os(pid: pid_t) -> int {
+        #[fixed_stack_segment]; #[inline(never)];
+
+        use libc::types::os::arch::extra::DWORD;
+        use libc::consts::os::extra::{
+            SYNCHRONIZE,
+            PROCESS_QUERY_INFORMATION,
+            FALSE,
+            STILL_ACTIVE,
+            INFINITE,
+            WAIT_FAILED
+        };
+        use libc::funcs::extra::kernel32::{
+            OpenProcess,
+            GetExitCodeProcess,
+            CloseHandle,
+            WaitForSingleObject
+        };
+
+        unsafe {
+
+            let proc = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
+            if proc.is_null() {
+                fail!("failure in OpenProcess: %s", os::last_os_error());
+            }
+
+            loop {
+                let mut status = 0;
+                if GetExitCodeProcess(proc, &mut status) == FALSE {
+                    CloseHandle(proc);
+                    fail!("failure in GetExitCodeProcess: %s", os::last_os_error());
+                }
+                if status != STILL_ACTIVE {
+                    CloseHandle(proc);
+                    return status as int;
+                }
+                if WaitForSingleObject(proc, INFINITE) == WAIT_FAILED {
+                    CloseHandle(proc);
+                    fail!("failure in WaitForSingleObject: %s", os::last_os_error());
+                }
+            }
+        }
+    }
+
+    #[cfg(unix)]
+    fn waitpid_os(pid: pid_t) -> int {
+        #[fixed_stack_segment]; #[inline(never)];
+
+        use libc::funcs::posix01::wait::*;
+
+        #[cfg(target_os = "linux")]
+        #[cfg(target_os = "android")]
+        fn WIFEXITED(status: i32) -> bool {
+            (status & 0xffi32) == 0i32
+        }
+
+        #[cfg(target_os = "macos")]
+        #[cfg(target_os = "freebsd")]
+        fn WIFEXITED(status: i32) -> bool {
+            (status & 0x7fi32) == 0i32
+        }
+
+        #[cfg(target_os = "linux")]
+        #[cfg(target_os = "android")]
+        fn WEXITSTATUS(status: i32) -> i32 {
+            (status >> 8i32) & 0xffi32
+        }
+
+        #[cfg(target_os = "macos")]
+        #[cfg(target_os = "freebsd")]
+        fn WEXITSTATUS(status: i32) -> i32 {
+            status >> 8i32
+        }
+
+        let mut status = 0 as c_int;
+        if unsafe { waitpid(pid, &mut status, 0) } == -1 {
+            fail!("failure in waitpid: %s", os::last_os_error());
+        }
+
+        return if WIFEXITED(status) {
+            WEXITSTATUS(status) as int
+        } else {
+            1
+        };
+    }
+}
+
 #[cfg(test)]
 mod tests {
+    use io;
+    use libc::c_int;
+    use option::{Option, None, Some};
     use os;
     use path::Path;
-    use prelude::*;
+    use run;
     use str;
-    use super::*;
     use unstable::running_on_valgrind;
 
+    #[test]
+    #[cfg(windows)]
+    fn test_make_command_line() {
+        assert_eq!(
+            run::make_command_line("prog", [~"aaa", ~"bbb", ~"ccc"]),
+            ~"prog aaa bbb ccc"
+        );
+        assert_eq!(
+            run::make_command_line("C:\\Program Files\\blah\\blah.exe", [~"aaa"]),
+            ~"\"C:\\Program Files\\blah\\blah.exe\" aaa"
+        );
+        assert_eq!(
+            run::make_command_line("C:\\Program Files\\test", [~"aa\"bb"]),
+            ~"\"C:\\Program Files\\test\" aa\\\"bb"
+        );
+        assert_eq!(
+            run::make_command_line("echo", [~"a b c"]),
+            ~"echo \"a b c\""
+        );
+    }
+
     #[test]
     #[cfg(not(target_os="android"))]
     fn test_process_status() {
-        assert_eq!(process_status("false", []), 1);
-        assert_eq!(process_status("true", []), 0);
+        assert_eq!(run::process_status("false", []), 1);
+        assert_eq!(run::process_status("true", []), 0);
     }
     #[test]
     #[cfg(target_os="android")]
     fn test_process_status() {
-        assert_eq!(process_status("/system/bin/sh", [~"-c",~"false"]), 1);
-        assert_eq!(process_status("/system/bin/sh", [~"-c",~"true"]), 0);
+        assert_eq!(run::process_status("/system/bin/sh", [~"-c",~"false"]), 1);
+        assert_eq!(run::process_status("/system/bin/sh", [~"-c",~"true"]), 0);
     }
 
     #[test]
     #[cfg(not(target_os="android"))]
     fn test_process_output_output() {
 
-        let ProcessOutput {status, output, error}
-             = process_output("echo", [~"hello"]);
+        let run::ProcessOutput {status, output, error}
+             = run::process_output("echo", [~"hello"]);
         let output_str = str::from_bytes(output);
 
         assert_eq!(status, 0);
@@ -431,8 +1010,8 @@ fn test_process_output_output() {
     #[cfg(target_os="android")]
     fn test_process_output_output() {
 
-        let ProcessOutput {status, output, error}
-             = process_output("/system/bin/sh", [~"-c",~"echo hello"]);
+        let run::ProcessOutput {status, output, error}
+             = run::process_output("/system/bin/sh", [~"-c",~"echo hello"]);
         let output_str = str::from_bytes(output);
 
         assert_eq!(status, 0);
@@ -447,8 +1026,8 @@ fn test_process_output_output() {
     #[cfg(not(target_os="android"))]
     fn test_process_output_error() {
 
-        let ProcessOutput {status, output, error}
-             = process_output("mkdir", [~"."]);
+        let run::ProcessOutput {status, output, error}
+             = run::process_output("mkdir", [~"."]);
 
         assert_eq!(status, 1);
         assert_eq!(output, ~[]);
@@ -458,40 +1037,90 @@ fn test_process_output_error() {
     #[cfg(target_os="android")]
     fn test_process_output_error() {
 
-        let ProcessOutput {status, output, error}
-             = process_output("/system/bin/mkdir", [~"."]);
+        let run::ProcessOutput {status, output, error}
+             = run::process_output("/system/bin/mkdir", [~"."]);
 
         assert_eq!(status, 255);
         assert_eq!(output, ~[]);
         assert!(!error.is_empty());
     }
 
+    #[test]
+    fn test_pipes() {
+
+        let pipe_in = os::pipe();
+        let pipe_out = os::pipe();
+        let pipe_err = os::pipe();
+
+        let mut proc = run::Process::new("cat", [], run::ProcessOptions {
+            dir: None,
+            env: None,
+            in_fd: Some(pipe_in.input),
+            out_fd: Some(pipe_out.out),
+            err_fd: Some(pipe_err.out)
+        });
+
+        assert!(proc.input_redirected());
+        assert!(proc.output_redirected());
+        assert!(proc.error_redirected());
+
+        os::close(pipe_in.input);
+        os::close(pipe_out.out);
+        os::close(pipe_err.out);
+
+        let expected = ~"test";
+        writeclose(pipe_in.out, expected);
+        let actual = readclose(pipe_out.input);
+        readclose(pipe_err.input);
+        proc.finish();
+
+        assert_eq!(expected, actual);
+    }
+
+    fn writeclose(fd: c_int, s: &str) {
+        let writer = io::fd_writer(fd, false);
+        writer.write_str(s);
+        os::close(fd);
+    }
+
+    fn readclose(fd: c_int) -> ~str {
+        #[fixed_stack_segment]; #[inline(never)];
+
+        unsafe {
+            let file = os::fdopen(fd);
+            let reader = io::FILE_reader(file, false);
+            let buf = reader.read_whole_stream();
+            os::fclose(file);
+            str::from_bytes(buf)
+        }
+    }
+
     #[test]
     #[cfg(not(target_os="android"))]
     fn test_finish_once() {
-        let mut prog = Process::new("false", [], ProcessOptions::new()).unwrap();
+        let mut prog = run::Process::new("false", [], run::ProcessOptions::new());
         assert_eq!(prog.finish(), 1);
     }
     #[test]
     #[cfg(target_os="android")]
     fn test_finish_once() {
-        let mut prog = Process::new("/system/bin/sh", [~"-c",~"false"],
-                                    ProcessOptions::new()).unwrap();
+        let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"false"],
+                                         run::ProcessOptions::new());
         assert_eq!(prog.finish(), 1);
     }
 
     #[test]
     #[cfg(not(target_os="android"))]
     fn test_finish_twice() {
-        let mut prog = Process::new("false", [], ProcessOptions::new()).unwrap();
+        let mut prog = run::Process::new("false", [], run::ProcessOptions::new());
         assert_eq!(prog.finish(), 1);
         assert_eq!(prog.finish(), 1);
     }
     #[test]
     #[cfg(target_os="android")]
     fn test_finish_twice() {
-        let mut prog = Process::new("/system/bin/sh", [~"-c",~"false"],
-                                    ProcessOptions::new()).unwrap();
+        let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"false"],
+                                         run::ProcessOptions::new());
         assert_eq!(prog.finish(), 1);
         assert_eq!(prog.finish(), 1);
     }
@@ -500,9 +1129,8 @@ fn test_finish_twice() {
     #[cfg(not(target_os="android"))]
     fn test_finish_with_output_once() {
 
-        let prog = Process::new("echo", [~"hello"], ProcessOptions::new());
-        let mut prog = prog.unwrap();
-        let ProcessOutput {status, output, error}
+        let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new());
+        let run::ProcessOutput {status, output, error}
             = prog.finish_with_output();
         let output_str = str::from_bytes(output);
 
@@ -517,10 +1145,28 @@ fn test_finish_with_output_once() {
     #[cfg(target_os="android")]
     fn test_finish_with_output_once() {
 
-        let mut prog = Process::new("/system/bin/sh", [~"-c",~"echo hello"],
-                                    ProcessOptions::new()).unwrap();
-        let ProcessOutput {status, output, error}
+        let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"echo hello"],
+                                         run::ProcessOptions::new());
+        let run::ProcessOutput {status, output, error}
+            = prog.finish_with_output();
+        let output_str = str::from_bytes(output);
+
+        assert_eq!(status, 0);
+        assert_eq!(output_str.trim().to_owned(), ~"hello");
+        // FIXME #7224
+        if !running_on_valgrind() {
+            assert_eq!(error, ~[]);
+        }
+    }
+
+    #[test]
+    #[cfg(not(target_os="android"))]
+    fn test_finish_with_output_twice() {
+
+        let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new());
+        let run::ProcessOutput {status, output, error}
             = prog.finish_with_output();
+
         let output_str = str::from_bytes(output);
 
         assert_eq!(status, 0);
@@ -529,61 +1175,97 @@ fn test_finish_with_output_once() {
         if !running_on_valgrind() {
             assert_eq!(error, ~[]);
         }
+
+        let run::ProcessOutput {status, output, error}
+            = prog.finish_with_output();
+
+        assert_eq!(status, 0);
+        assert_eq!(output, ~[]);
+        // FIXME #7224
+        if !running_on_valgrind() {
+            assert_eq!(error, ~[]);
+        }
+    }
+    #[test]
+    #[cfg(target_os="android")]
+    fn test_finish_with_output_twice() {
+
+        let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"echo hello"],
+                                         run::ProcessOptions::new());
+        let run::ProcessOutput {status, output, error}
+            = prog.finish_with_output();
+
+        let output_str = str::from_bytes(output);
+
+        assert_eq!(status, 0);
+        assert_eq!(output_str.trim().to_owned(), ~"hello");
+        // FIXME #7224
+        if !running_on_valgrind() {
+            assert_eq!(error, ~[]);
+        }
+
+        let run::ProcessOutput {status, output, error}
+            = prog.finish_with_output();
+
+        assert_eq!(status, 0);
+        assert_eq!(output, ~[]);
+        // FIXME #7224
+        if !running_on_valgrind() {
+            assert_eq!(error, ~[]);
+        }
     }
 
     #[test]
     #[should_fail]
     #[cfg(not(windows),not(target_os="android"))]
     fn test_finish_with_output_redirected() {
-        let mut prog = Process::new("echo", [~"hello"], ProcessOptions {
+        let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions {
             env: None,
             dir: None,
             in_fd: Some(0),
             out_fd: Some(1),
             err_fd: Some(2)
-        }).unwrap();
-        // this should fail because it is not valid to read the output when it
-        // was redirected
+        });
+        // this should fail because it is not valid to read the output when it was redirected
         prog.finish_with_output();
     }
     #[test]
     #[should_fail]
     #[cfg(not(windows),target_os="android")]
     fn test_finish_with_output_redirected() {
-        let mut prog = Process::new("/system/bin/sh", [~"-c",~"echo hello"],
-                                    ProcessOptions {
+        let mut prog = run::Process::new("/system/bin/sh", [~"-c",~"echo hello"],
+                                         run::ProcessOptions {
             env: None,
             dir: None,
             in_fd: Some(0),
             out_fd: Some(1),
             err_fd: Some(2)
-        }).unwrap();
-        // this should fail because it is not valid to read the output when it
-        // was redirected
+        });
+        // this should fail because it is not valid to read the output when it was redirected
         prog.finish_with_output();
     }
 
     #[cfg(unix,not(target_os="android"))]
-    fn run_pwd(dir: Option<&Path>) -> Process {
-        Process::new("pwd", [], ProcessOptions {
+    fn run_pwd(dir: Option<&Path>) -> run::Process {
+        run::Process::new("pwd", [], run::ProcessOptions {
             dir: dir,
-            .. ProcessOptions::new()
-        }).unwrap()
+            .. run::ProcessOptions::new()
+        })
     }
     #[cfg(unix,target_os="android")]
-    fn run_pwd(dir: Option<&Path>) -> Process {
-        Process::new("/system/bin/sh", [~"-c",~"pwd"], ProcessOptions {
+    fn run_pwd(dir: Option<&Path>) -> run::Process {
+        run::Process::new("/system/bin/sh", [~"-c",~"pwd"], run::ProcessOptions {
             dir: dir,
-            .. ProcessOptions::new()
-        }).unwrap()
+            .. run::ProcessOptions::new()
+        })
     }
 
     #[cfg(windows)]
-    fn run_pwd(dir: Option<&Path>) -> Process {
-        Process::new("cmd", [~"/c", ~"cd"], ProcessOptions {
+    fn run_pwd(dir: Option<&Path>) -> run::Process {
+        run::Process::new("cmd", [~"/c", ~"cd"], run::ProcessOptions {
             dir: dir,
-            .. ProcessOptions::new()
-        }).unwrap()
+            .. run::ProcessOptions::new()
+        })
     }
 
     #[test]
@@ -619,26 +1301,26 @@ fn test_change_working_directory() {
     }
 
     #[cfg(unix,not(target_os="android"))]
-    fn run_env(env: Option<~[(~str, ~str)]>) -> Process {
-        Process::new("env", [], ProcessOptions {
+    fn run_env(env: Option<~[(~str, ~str)]>) -> run::Process {
+        run::Process::new("env", [], run::ProcessOptions {
             env: env,
-            .. ProcessOptions::new()
-        }).unwrap()
+            .. run::ProcessOptions::new()
+        })
     }
     #[cfg(unix,target_os="android")]
-    fn run_env(env: Option<~[(~str, ~str)]>) -> Process {
-        Process::new("/system/bin/sh", [~"-c",~"set"], ProcessOptions {
+    fn run_env(env: Option<~[(~str, ~str)]>) -> run::Process {
+        run::Process::new("/system/bin/sh", [~"-c",~"set"], run::ProcessOptions {
             env: env,
-            .. ProcessOptions::new()
-        }).unwrap()
+            .. run::ProcessOptions::new()
+        })
     }
 
     #[cfg(windows)]
-    fn run_env(env: Option<~[(~str, ~str)]>) -> Process {
-        Process::new("cmd", [~"/c", ~"set"], ProcessOptions {
+    fn run_env(env: Option<~[(~str, ~str)]>) -> run::Process {
+        run::Process::new("cmd", [~"/c", ~"set"], run::ProcessOptions {
             env: env,
-            .. ProcessOptions::new()
-        }).unwrap()
+            .. run::ProcessOptions::new()
+        })
     }
 
     #[test]
@@ -675,6 +1357,7 @@ fn test_inherit_env() {
 
     #[test]
     fn test_add_to_env() {
+
         let mut new_env = os::env();
         new_env.push((~"RUN_TEST_NEW_ENV", ~"123"));
 
index f121158d4c525cfe02254028531fb6bb0815bd9b..d0afeb4be85610d834fdfc51bb7553ccba782230 100644 (file)
@@ -126,7 +126,7 @@ pub fn select2<TA, A: SelectPort<TA>, TB, B: SelectPort<TB>>(mut a: A, mut b: B)
 mod test {
     use super::*;
     use clone::Clone;
-    use iter::Times;
+    use num::Times;
     use option::*;
     use rt::comm::*;
     use rt::test::*;
index ad3e4368daa5298c3e4f07e3b9a7c9316d0810ac..ce0202ded7eda2ecd890394c07b439a88ae73038 100644 (file)
@@ -140,7 +140,6 @@ pub mod linkhack {
 pub mod from_str;
 #[path = "num/num.rs"]
 pub mod num;
-pub mod iter;
 pub mod iterator;
 pub mod to_str;
 pub mod to_bytes;
@@ -179,8 +178,14 @@ pub mod linkhack {
 pub mod sys;
 pub mod cast;
 pub mod fmt;
+#[cfg(stage0)] #[path = "repr_stage0.rs"]
+pub mod repr;
+#[cfg(not(stage0))]
 pub mod repr;
 pub mod cleanup;
+#[cfg(stage0)] #[path = "reflect_stage0.rs"]
+pub mod reflect;
+#[cfg(not(stage0))]
 pub mod reflect;
 pub mod condition;
 pub mod logging;
@@ -220,4 +225,3 @@ mod std {
     pub use fmt;
     pub use to_bytes;
 }
-
index 9ca6e8ad0899238bd568bc07d8e00faab7c71b60..4a7ab6d6732ee6dc7df14594f8eee6a6ec4b7bc7 100644 (file)
@@ -21,7 +21,7 @@
 use char::Char;
 use clone::{Clone, DeepClone};
 use container::{Container, Mutable};
-use iter::Times;
+use num::Times;
 use iterator::{Iterator, FromIterator, Extendable};
 use iterator::{Filter, AdditiveIterator, Map};
 use iterator::{Invert, DoubleEndedIterator};
@@ -621,8 +621,7 @@ enum NormalizationForm {
 #[deriving(Clone)]
 struct NormalizationIterator<'self> {
     priv kind: NormalizationForm,
-    priv index: uint,
-    priv string: &'self str,
+    priv iter: CharIterator<'self>,
     priv buffer: ~[(char, u8)],
     priv sorted: bool
 }
@@ -650,16 +649,17 @@ fn next(&mut self) -> Option<char> {
             NFKD => char::decompose_compatible
         };
 
-        while !self.sorted && self.index < self.string.len() {
-            let CharRange {ch, next} = self.string.char_range_at(self.index);
-            self.index = next;
-            do decomposer(ch) |d| {
-                let class = canonical_combining_class(d);
-                if class == 0 && !self.sorted {
-                    canonical_sort(self.buffer);
-                    self.sorted = true;
+        if !self.sorted {
+            for ch in self.iter {
+                do decomposer(ch) |d| {
+                    let class = canonical_combining_class(d);
+                    if class == 0 && !self.sorted {
+                        canonical_sort(self.buffer);
+                        self.sorted = true;
+                    }
+                    self.buffer.push((d, class));
                 }
-                self.buffer.push((d, class));
+                if self.sorted { break }
             }
         }
 
@@ -678,7 +678,10 @@ fn next(&mut self) -> Option<char> {
         }
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) { (self.string.len(), None) }
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        let (lower, _) = self.iter.size_hint();
+        (lower, None)
+    }
 }
 
 /// Replace all occurrences of one string with another
@@ -907,46 +910,6 @@ pub fn with_capacity(capacity: uint) -> ~str {
     }
 }
 
-/// As char_len but for a slice of a string
-///
-/// # Arguments
-///
-/// * s - A valid string
-/// * start - The position inside `s` where to start counting in bytes
-/// * end - The position where to stop counting
-///
-/// # Return value
-///
-/// The number of Unicode characters in `s` between the given indices.
-pub fn count_chars(s: &str, start: uint, end: uint) -> uint {
-    assert!(s.is_char_boundary(start));
-    assert!(s.is_char_boundary(end));
-    let mut i = start;
-    let mut len = 0u;
-    while i < end {
-        let next = s.char_range_at(i).next;
-        len += 1u;
-        i = next;
-    }
-    return len;
-}
-
-/// Counts the number of bytes taken by the first `n` chars in `s`
-/// starting from `start`.
-pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint {
-    assert!(s.is_char_boundary(start));
-    let mut end = start;
-    let mut cnt = n;
-    let l = s.len();
-    while cnt > 0u {
-        assert!(end < l);
-        let next = s.char_range_at(end).next;
-        cnt -= 1u;
-        end = next;
-    }
-    end - start
-}
-
 // https://tools.ietf.org/html/rfc3629
 static UTF8_CHAR_WIDTH: [u8, ..256] = [
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -1217,8 +1180,6 @@ impl Eq for ~str {
         fn eq(&self, other: &~str) -> bool {
             eq_slice((*self), (*other))
         }
-        #[inline]
-        fn ne(&self, other: &~str) -> bool { !(*self).eq(other) }
     }
 
     impl Eq for @str {
@@ -1226,8 +1187,6 @@ impl Eq for @str {
         fn eq(&self, other: &@str) -> bool {
             eq_slice((*self), (*other))
         }
-        #[inline]
-        fn ne(&self, other: &@str) -> bool { !(*self).eq(other) }
     }
 
     impl<'self> TotalEq for &'self str {
@@ -1628,8 +1587,7 @@ fn word_iter(&self) -> WordIterator<'self> {
     /// Returns the string in Unicode Normalization Form D (canonical decomposition)
     fn nfd_iter(&self) -> NormalizationIterator<'self> {
         NormalizationIterator {
-            index: 0,
-            string: *self,
+            iter: self.iter(),
             buffer: ~[],
             sorted: false,
             kind: NFD
@@ -1639,8 +1597,7 @@ fn nfd_iter(&self) -> NormalizationIterator<'self> {
     /// Returns the string in Unicode Normalization Form KD (compatibility decomposition)
     fn nfkd_iter(&self) -> NormalizationIterator<'self> {
         NormalizationIterator {
-            index: 0,
-            string: *self,
+            iter: self.iter(),
             buffer: ~[],
             sorted: false,
             kind: NFKD
@@ -1712,6 +1669,7 @@ fn slice_chars(&self, begin: uint, end: uint) -> &'self str {
             if count == end { end_byte = Some(idx); break; }
             count += 1;
         }
+        if begin_byte.is_none() && count == begin { begin_byte = Some(self.len()) }
         if end_byte.is_none() && count == end { end_byte = Some(self.len()) }
 
         match (begin_byte, end_byte) {
@@ -2699,8 +2657,11 @@ fn test_slice_chars() {
         fn t(a: &str, b: &str, start: uint) {
             assert_eq!(a.slice_chars(start, start + b.char_len()), b);
         }
+        t("", "", 0);
         t("hello", "llo", 2);
         t("hello", "el", 1);
+        t("αβλ", "β", 1);
+        t("αβλ", "", 3);
         assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8));
     }
 
index cb0753fb2e5dee4a45ea3a8d8bbbf871a3857a83..cfc285488a90f30c218e3d9dddd474687a62910d 100644 (file)
@@ -14,6 +14,7 @@
 
 use c_str::ToCStr;
 use cast;
+#[cfg(stage0)]
 use io;
 use libc;
 use libc::{c_char, size_t};
@@ -91,9 +92,19 @@ pub fn refcount<T>(t: @T) -> uint {
     }
 }
 
+#[cfg(not(stage0))]
 pub fn log_str<T>(t: &T) -> ~str {
-    do io::with_str_writer |wr| {
-        repr::write_repr(wr, t)
+    use rt::io;
+    use rt::io::Decorator;
+
+    let mut result = io::mem::MemWriter::new();
+    repr::write_repr(&mut result as &mut io::Writer, t);
+    str::from_bytes_owned(result.inner())
+}
+#[cfg(stage0)]
+pub fn log_str<T>(t: &T) -> ~str {
+    do io::with_str_writer |w| {
+        repr::write_repr(w, t)
     }
 }
 
index 90cf49cad1ccf2a9553507091bfa31c925ee146b..db106de76d94e4ce5eb97d3097da2a2fdcd378ee 100644 (file)
@@ -90,6 +90,7 @@ mod test {
     use libc;
 
     #[test]
+    #[ignore(cfg(windows))] // FIXME #8818
     fn test_loading_cosine() {
         // The math library does not need to be loaded since it is already
         // statically linked in
index cdd93ce87c35bbdfb14944571782e07cd71a1d06..018f8532eab7c412615f453d2e644bd3546b2a9a 100644 (file)
@@ -73,7 +73,7 @@ pub struct TyDesc {
 pub enum Opaque { }
 
 #[lang="ty_visitor"]
-#[cfg(not(test))]
+#[cfg(not(test), stage0)]
 pub trait TyVisitor {
     fn visit_bot(&self) -> bool;
     fn visit_nil(&self) -> bool;
@@ -168,6 +168,102 @@ fn visit_leave_fn(&self, purity: uint, proto: uint,
     fn visit_closure_ptr(&self, ck: uint) -> bool;
 }
 
+#[lang="ty_visitor"]
+#[cfg(not(test), not(stage0))]
+pub trait TyVisitor {
+    fn visit_bot(&mut self) -> bool;
+    fn visit_nil(&mut self) -> bool;
+    fn visit_bool(&mut self) -> bool;
+
+    fn visit_int(&mut self) -> bool;
+    fn visit_i8(&mut self) -> bool;
+    fn visit_i16(&mut self) -> bool;
+    fn visit_i32(&mut self) -> bool;
+    fn visit_i64(&mut self) -> bool;
+
+    fn visit_uint(&mut self) -> bool;
+    fn visit_u8(&mut self) -> bool;
+    fn visit_u16(&mut self) -> bool;
+    fn visit_u32(&mut self) -> bool;
+    fn visit_u64(&mut self) -> bool;
+
+    fn visit_float(&mut self) -> bool;
+    fn visit_f32(&mut self) -> bool;
+    fn visit_f64(&mut self) -> bool;
+
+    fn visit_char(&mut self) -> bool;
+
+    fn visit_estr_box(&mut self) -> bool;
+    fn visit_estr_uniq(&mut self) -> bool;
+    fn visit_estr_slice(&mut self) -> bool;
+    fn visit_estr_fixed(&mut self, n: uint, sz: uint, align: uint) -> bool;
+
+    fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+
+    fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
+                        mtbl: uint, inner: *TyDesc) -> bool;
+
+    fn visit_enter_rec(&mut self, n_fields: uint,
+                       sz: uint, align: uint) -> bool;
+    fn visit_rec_field(&mut self, i: uint, name: &str,
+                       mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_rec(&mut self, n_fields: uint,
+                       sz: uint, align: uint) -> bool;
+
+    fn visit_enter_class(&mut self, n_fields: uint,
+                         sz: uint, align: uint) -> bool;
+    fn visit_class_field(&mut self, i: uint, name: &str,
+                         mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_class(&mut self, n_fields: uint,
+                         sz: uint, align: uint) -> bool;
+
+    fn visit_enter_tup(&mut self, n_fields: uint,
+                       sz: uint, align: uint) -> bool;
+    fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_tup(&mut self, n_fields: uint,
+                       sz: uint, align: uint) -> bool;
+
+    fn visit_enter_enum(&mut self, n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        sz: uint, align: uint) -> bool;
+    fn visit_enter_enum_variant(&mut self, variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool;
+    fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_enum_variant(&mut self, variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool;
+    fn visit_leave_enum(&mut self, n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        sz: uint, align: uint) -> bool;
+
+    fn visit_enter_fn(&mut self, purity: uint, proto: uint,
+                      n_inputs: uint, retstyle: uint) -> bool;
+    fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool;
+    fn visit_fn_output(&mut self, retstyle: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_fn(&mut self, purity: uint, proto: uint,
+                      n_inputs: uint, retstyle: uint) -> bool;
+
+    fn visit_trait(&mut self) -> bool;
+    fn visit_param(&mut self, i: uint) -> bool;
+    fn visit_self(&mut self) -> bool;
+    fn visit_type(&mut self) -> bool;
+    fn visit_opaque_box(&mut self) -> bool;
+    fn visit_closure_ptr(&mut self, ck: uint) -> bool;
+}
+
 #[abi = "rust-intrinsic"]
 extern "rust-intrinsic" {
 
@@ -325,7 +421,10 @@ fn visit_leave_fn(&self, purity: uint, proto: uint,
     /// Returns `true` if a type is managed (will be allocated on the local heap)
     pub fn contains_managed<T>() -> bool;
 
+    #[cfg(stage0)]
     pub fn visit_tydesc(td: *TyDesc, tv: &TyVisitor);
+    #[cfg(not(stage0))]
+    pub fn visit_tydesc(td: *TyDesc, tv: &mut TyVisitor);
 
     pub fn frame_address(f: &once fn(*u8));
 
index 8d1545ea2b4506061f8c1d1c48c3bf2b3af34a3b..26313323291e5e8d4bef786dec5d989cc6942971 100644 (file)
@@ -26,6 +26,7 @@
 /// An atomically reference counted pointer.
 ///
 /// Enforces no shared-memory safety.
+#[unsafe_no_drop_flag]
 pub struct UnsafeArc<T> {
     data: *mut ArcData<T>,
 }
@@ -221,8 +222,9 @@ fn clone(&self) -> UnsafeArc<T> {
 impl<T> Drop for UnsafeArc<T>{
     fn drop(&self) {
         unsafe {
+            // Happens when destructing an unwrapper's handle and from `#[unsafe_no_drop_flag]`
             if self.data.is_null() {
-                return; // Happens when destructing an unwrapper's handle.
+                return
             }
             let mut data: ~ArcData<T> = cast::transmute(self.data);
             // Must be acquire+release, not just release, to make sure this
@@ -440,6 +442,12 @@ mod tests {
     use super::{Exclusive, UnsafeArc, atomically};
     use task;
     use util;
+    use sys::size_of;
+
+    #[test]
+    fn test_size() {
+        assert_eq!(size_of::<UnsafeArc<[int, ..10]>>(), size_of::<*[int, ..10]>());
+    }
 
     #[test]
     fn test_atomically() {
index 81113f2432923c6089cf37e932a07806c2a821c8..61dcc6c194782926f1cc80982c667adf15e69e33 100644 (file)
@@ -340,7 +340,7 @@ mod test {
     use parse::token::{str_to_ident};
     use util::parser_testing::{string_to_tts_and_sess, string_to_parser};
     use util::parser_testing::{string_to_expr, string_to_item};
-    use util::parser_testing::{string_to_stmt, strs_to_idents};
+    use util::parser_testing::string_to_stmt;
 
     // map a string to tts, return the tt without its parsesess
     fn string_to_tts_only(source_str : @str) -> ~[ast::token_tree] {
index ef2bcd134164adcaa072dcb56e62b737fdcb075e..dfae9c3e958dc086d9c0ab068cd76d196c95a433 160000 (submodule)
--- a/src/libuv
+++ b/src/libuv
@@ -1 +1 @@
-Subproject commit ef2bcd134164adcaa072dcb56e62b737fdcb075e
+Subproject commit dfae9c3e958dc086d9c0ab068cd76d196c95a433
index 0964c68ddf2c67ce455e7443a06f4bb3db9e92bb..08a3bd96ee6e1d141494f0014ede75d9871114c4 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 0964c68ddf2c67ce455e7443a06f4bb3db9e92bb
+Subproject commit 08a3bd96ee6e1d141494f0014ede75d9871114c4
index a181e76df5ca70f1bb31ee21a93c7c4be96fcd6a..8ef4572f8108f0170b577359475da5cde9fbad4b 100644 (file)
@@ -329,13 +329,20 @@ rust_uv_get_len_from_buf(uv_buf_t buf) {
     return buf.len;
 }
 
+extern "C" uv_err_t
+rust_uv_last_error(uv_loop_t* loop) {
+    return uv_last_error(loop);
+}
+
 extern "C" const char*
-rust_uv_strerror(int err) {
+rust_uv_strerror(uv_err_t* err_ptr) {
+    uv_err_t err = *err_ptr;
     return uv_strerror(err);
 }
 
 extern "C" const char*
-rust_uv_err_name(int err) {
+rust_uv_err_name(uv_err_t* err_ptr) {
+    uv_err_t err = *err_ptr;
     return uv_err_name(err);
 }
 
@@ -546,37 +553,3 @@ extern "C" uv_loop_t*
 rust_uv_get_loop_from_fs_req(uv_fs_t* req) {
   return req->loop;
 }
-extern "C" int
-rust_uv_spawn(uv_loop_t *loop, uv_process_t *p, uv_process_options_t options) {
-  return uv_spawn(loop, p, options);
-}
-
-extern "C" int
-rust_uv_process_kill(uv_process_t *p, int signum) {
-  return uv_process_kill(p, signum);
-}
-
-extern "C" void
-rust_set_stdio_container_flags(uv_stdio_container_t *c, int flags) {
-  c->flags = (uv_stdio_flags) flags;
-}
-
-extern "C" void
-rust_set_stdio_container_fd(uv_stdio_container_t *c, int fd) {
-  c->data.fd = fd;
-}
-
-extern "C" void
-rust_set_stdio_container_stream(uv_stdio_container_t *c, uv_stream_t *stream) {
-  c->data.stream = stream;
-}
-
-extern "C" int
-rust_uv_process_pid(uv_process_t* p) {
-  return p->pid;
-}
-
-extern "C" int
-rust_uv_pipe_init(uv_loop_t *loop, uv_pipe_t* p, int ipc) {
-  return uv_pipe_init(loop, p, ipc);
-}
index 2fc1a91a132da55d66c5ba660612398ebbfe06d1..b668d3944066252084add406d8c8043e66f6e0e8 100644 (file)
@@ -47,6 +47,7 @@ rust_uv_timer_start
 rust_uv_timer_stop
 rust_uv_tcp_init
 rust_uv_buf_init
+rust_uv_last_error
 rust_uv_strerror
 rust_uv_err_name
 rust_uv_ip4_addr
@@ -190,11 +191,4 @@ rust_drop_global_args_lock
 rust_take_change_dir_lock
 rust_drop_change_dir_lock
 rust_get_test_int
-rust_get_task
-rust_uv_spawn
-rust_uv_process_kill
-rust_set_stdio_container_flags
-rust_set_stdio_container_fd
-rust_set_stdio_container_stream
-rust_uv_process_pid
-rust_uv_pipe_init
+rust_get_task
\ No newline at end of file
index 56ba56cf89377fb2ea265ce1dca82df995bb5c70..615c2cc61cbee738e77fc3429337b524109dac26 100644 (file)
@@ -78,6 +78,7 @@ LLVMRustCreateTargetMachine(const char *triple,
     }
 
     TargetOptions Options;
+    Options.NoFramePointerElim = true;
     Options.EnableSegmentedStacks = EnableSegmentedStacks;
     Options.FixedStackSegmentSize = 2 * 1024 * 1024; // XXX: This is too big.
     Options.FloatABIType =
@@ -142,36 +143,15 @@ LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) {
 }
 
 extern "C" void
-LLVMRustSetLLVMOptions(bool PrintPasses,
-                       bool VectorizeLoops,
-                       bool VectorizeSLP,
-                       bool TimePasses) {
+LLVMRustSetLLVMOptions(int Argc, char **Argv) {
     // Initializing the command-line options more than once is not allowed. So,
     // check if they've already been initialized.  (This could happen if we're
     // being called from rustpkg, for example). If the arguments change, then
     // that's just kinda unfortunate.
     static bool initialized = false;
     if (initialized) return;
-
-    int argc = 3;
-    const char *argv[20] = {"rustc",
-                            "-arm-enable-ehabi",
-                            "-arm-enable-ehabi-descriptors"};
-    if (PrintPasses) {
-        argv[argc++] = "-debug-pass";
-        argv[argc++] = "Structure";
-    }
-    if (VectorizeLoops) {
-        argv[argc++] = "-vectorize-loops";
-    }
-    if (VectorizeSLP) {
-        argv[argc++] = "-vectorize-slp";
-    }
-    if (TimePasses) {
-        argv[argc++] = "-time-passes";
-    }
-    cl::ParseCommandLineOptions(argc, argv);
     initialized = true;
+    cl::ParseCommandLineOptions(Argc, Argv);
 }
 
 extern "C" bool
index 40ee486ec2d9c6a2906e75f4ce132bc58024b1d1..54af6fe7e73bafe60f73384f211c0c06bbc5e933 100644 (file)
@@ -284,6 +284,7 @@ LLVMRustBuildJIT(void* mem,
   std::string Err;
   TargetOptions Options;
   Options.JITEmitDebugInfo = true;
+  Options.NoFramePointerElim = true;
   Options.EnableSegmentedStacks = EnableSegmentedStacks;
   RustMCJITMemoryManager* MM = (RustMCJITMemoryManager*) mem;
   assert(MM);
diff --git a/src/test/auxiliary/nested_item.rs b/src/test/auxiliary/nested_item.rs
new file mode 100644 (file)
index 0000000..e9dde0d
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// original problem
+fn foo<T>() -> int {
+    {
+        static foo: int = 2;
+        foo
+    }
+}
+
+// issue 8134
+struct Foo;
+impl<T> Foo {
+    pub fn foo(&self) {
+        static X: uint = 1;
+    }
+}
+
+// issue 8134
+pub struct Parser<T>;
+impl<T: std::iterator::Iterator<char>> Parser<T> {
+    fn in_doctype(&mut self) {
+        static DOCTYPEPattern: [char, ..6] = ['O', 'C', 'T', 'Y', 'P', 'E'];
+    }
+}
+
+struct Bar;
+impl<T> Foo {
+    pub fn bar(&self) {
+        static X: uint = 1;
+    }
+}
index b2491e305b254a6c3bf1d93a69228759ec9355f0..7029ca2a49296969920d7cb804a0a077e93971a2 100644 (file)
@@ -28,7 +28,6 @@
 use std::os;
 use std::result::{Ok, Err};
 use std::task;
-use std::u64;
 use std::uint;
 
 fn fib(n: int) -> int {
diff --git a/src/test/compile-fail/lint-unused-import-tricky-globs.rs b/src/test/compile-fail/lint-unused-import-tricky-globs.rs
new file mode 100644 (file)
index 0000000..918b11b
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deny(unused_imports)];
+
+mod A {
+    pub fn p() {}
+}
+mod B {
+    pub fn p() {}
+}
+
+mod C {
+    pub fn q() {}
+}
+mod D {
+    pub fn q() {}
+}
+
+mod E {
+    pub fn r() {}
+}
+mod F {
+    pub fn r() {}
+}
+
+mod G {
+    pub fn s() {}
+    pub fn t() {}
+}
+mod H {
+    pub fn s() {}
+}
+
+mod I {
+    pub fn u() {}
+    pub fn v() {}
+}
+mod J {
+    pub fn u() {}
+    pub fn v() {}
+}
+
+mod K {
+    pub fn w() {}
+}
+mod L {
+    pub fn w() {}
+}
+
+mod m {
+   use A::p; //~ ERROR: unused import
+   use B::p;
+   use C::q; //~ ERROR: unused import
+   use D::*;
+   use E::*; //~ ERROR: unused import
+   use F::r;
+   use G::*;
+   use H::*;
+   use I::*;
+   use J::v;
+   use K::*; //~ ERROR: unused import
+   use L::*;
+
+   #[main]
+   fn my_main() {
+       p();
+       q();
+       r();
+       s();
+       t();
+       u();
+       v();
+       w();
+   }
+}
+
diff --git a/src/test/run-fail/test-tasks-invalid-value.rs b/src/test/run-fail/test-tasks-invalid-value.rs
new file mode 100644 (file)
index 0000000..74531de
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This checks that RUST_TEST_TASKS not being 1, 2, ... is detected
+// properly.
+
+// error-pattern:should be a positive integer
+// compile-flags: --test
+// exec-env:RUST_TEST_TASKS=foo
+
+#[test]
+fn do_nothing() {}
index eb7ae3d6fec99bdedf2736df02c3a696e3d61192..5ded736ab9b0472f6869e863add80fd53e505e2a 100644 (file)
 
 extern mod cci_const;
 use cci_const::bar;
-use std::cast::transmute;
 static foo: extern "C" fn() = bar;
 
 pub fn main() {
-    unsafe {
-        assert_eq!(foo, bar);
-    }
+    assert_eq!(foo, bar);
 }
index e07af4b0383fd1375f0eb2a8db4be96521e4e5ae..501a87955da5731b00a7e3df593cbe397f7ca277 100644 (file)
@@ -18,8 +18,6 @@ struct S {
 }
 
 pub fn main() {
-    unsafe {
-        assert_eq!(foopy, f);
-        assert_eq!(f, s.f);
-    }
+    assert_eq!(foopy, f);
+    assert_eq!(f, s.f);
 }
index 90e63fc977d866841394f491be862265b95ef0c2..2551d1a5cfcba32455e421de89a3cae23a37c9b8 100644 (file)
 
 #[test]
 fn test_destroy_once() {
-    let p = run::Process::new("echo", [], run::ProcessOptions::new());
-    let mut p = p.unwrap();
+    let mut p = run::Process::new("echo", [], run::ProcessOptions::new());
     p.destroy(); // this shouldn't crash (and nor should the destructor)
 }
 
 #[test]
 fn test_destroy_twice() {
-    let p = run::Process::new("echo", [], run::ProcessOptions::new());
-    let mut p = p.unwrap();
+    let mut p = run::Process::new("echo", [], run::ProcessOptions::new());
     p.destroy(); // this shouldnt crash...
     p.destroy(); // ...and nor should this (and nor should the destructor)
 }
@@ -76,8 +74,7 @@ fn process_exists(pid: libc::pid_t) -> bool {
     }
 
     // this process will stay alive indefinitely trying to read from stdin
-    let p = run::Process::new(BLOCK_COMMAND, [], run::ProcessOptions::new());
-    let mut p = p.unwrap();
+    let mut p = run::Process::new(BLOCK_COMMAND, [], run::ProcessOptions::new());
 
     assert!(process_exists(p.get_id()));
 
index 41bf4a10b5d9e74c19e82a5c31e1aaeb416abf23..5406fa283e7e76740a5169999113ba8ab01228b9 100644 (file)
@@ -15,7 +15,7 @@
 
 extern fn uintret() -> uint { 22 }
 
-extern fn uintvoidret(x: uint) {}
+extern fn uintvoidret(_x: uint) {}
 
 extern fn uintuintuintuintret(x: uint, y: uint, z: uint) -> uint { x+y+z }
 
index e636f511da8d309620b59c4c114a475e2bfa682d..b883fbd6f6a04caa4573c8ed1e9ee7cfcac123bb 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::cast::transmute;
-
 extern fn f() {
 }
 
 }
 
 pub fn main() {
-    unsafe {
-        let a: extern "C" fn() = f;
-        let b: extern "C" fn() = f;
-        let c: extern "C" fn() = g;
+    let a: extern "C" fn() = f;
+    let b: extern "C" fn() = f;
+    let c: extern "C" fn() = g;
 
-        assert_eq!(a, b);
-        assert!(a != c);
-    }
+    assert_eq!(a, b);
+    assert!(a != c);
 }
index 3e588bb53d2a6e53b7992d5bf9f3ca68d49584a1..326e92d3b70857ffc13e047fd223f2d69b4a5112 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::io;
-
 struct T (&'static [int]);
 static t : T = T (&'static [5, 4, 3]);
 fn main () {
index 7dc859e559efa53a9e2868bdb141d3f7caf63669..8baf15c8493be409930dc1d19c5622cde63a76b2 100644 (file)
@@ -10,8 +10,6 @@
 
 // xfail-fast
 
-use std::int;
-
 trait vec_monad<A> {
     fn bind<B>(&self, f: &fn(&A) -> ~[B]) -> ~[B];
 }
diff --git a/src/test/run-pass/nested_item_main.rs b/src/test/run-pass/nested_item_main.rs
new file mode 100644 (file)
index 0000000..5ce05fe
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:nested_item.rs
+// xfail-fast
+
+extern mod nested_item;
+
+pub fn main() {
+    assert_eq!(2, nested_item::foo::<()>());
+    assert_eq!(2, nested_item::foo::<int>());
+}
index b56cef4277f5742faec632f7a3098b8e4a1e4d80..1c77a6b2fb95796e7ed8d84f28ec148076fcedf3 100644 (file)
@@ -10,7 +10,6 @@
 
 // xfail-fast
 
-use std::int;
 use std::libc::c_void;
 use std::ptr;
 use std::sys;
@@ -21,7 +20,7 @@
 
 /// Trait for visitor that wishes to reflect on data.
 trait movable_ptr {
-    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void);
+    fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void);
 }
 
 /// Helper function for alignment calculation.
@@ -35,26 +34,26 @@ fn align(size: uint, align: uint) -> uint {
 impl<V:TyVisitor + movable_ptr> ptr_visit_adaptor<V> {
 
     #[inline(always)]
-    pub fn bump(&self, sz: uint) {
+    pub fn bump(&mut self, sz: uint) {
       do self.inner.move_ptr() |p| {
             ((p as uint) + sz) as *c_void
       };
     }
 
     #[inline(always)]
-    pub fn align(&self, a: uint) {
+    pub fn align(&mut self, a: uint) {
       do self.inner.move_ptr() |p| {
             align(p as uint, a) as *c_void
       };
     }
 
     #[inline(always)]
-    pub fn align_to<T>(&self) {
+    pub fn align_to<T>(&mut self) {
         self.align(sys::min_align_of::<T>());
     }
 
     #[inline(always)]
-    pub fn bump_past<T>(&self) {
+    pub fn bump_past<T>(&mut self) {
         self.bump(sys::size_of::<T>());
     }
 
@@ -62,147 +61,147 @@ pub fn bump_past<T>(&self) {
 
 impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
 
-    fn visit_bot(&self) -> bool {
+    fn visit_bot(&mut self) -> bool {
         self.align_to::<()>();
         if ! self.inner.visit_bot() { return false; }
         self.bump_past::<()>();
         true
     }
 
-    fn visit_nil(&self) -> bool {
+    fn visit_nil(&mut self) -> bool {
         self.align_to::<()>();
         if ! self.inner.visit_nil() { return false; }
         self.bump_past::<()>();
         true
     }
 
-    fn visit_bool(&self) -> bool {
+    fn visit_bool(&mut self) -> bool {
         self.align_to::<bool>();
         if ! self.inner.visit_bool() { return false; }
         self.bump_past::<bool>();
         true
     }
 
-    fn visit_int(&self) -> bool {
+    fn visit_int(&mut self) -> bool {
         self.align_to::<int>();
         if ! self.inner.visit_int() { return false; }
         self.bump_past::<int>();
         true
     }
 
-    fn visit_i8(&self) -> bool {
+    fn visit_i8(&mut self) -> bool {
         self.align_to::<i8>();
         if ! self.inner.visit_i8() { return false; }
         self.bump_past::<i8>();
         true
     }
 
-    fn visit_i16(&self) -> bool {
+    fn visit_i16(&mut self) -> bool {
         self.align_to::<i16>();
         if ! self.inner.visit_i16() { return false; }
         self.bump_past::<i16>();
         true
     }
 
-    fn visit_i32(&self) -> bool {
+    fn visit_i32(&mut self) -> bool {
         self.align_to::<i32>();
         if ! self.inner.visit_i32() { return false; }
         self.bump_past::<i32>();
         true
     }
 
-    fn visit_i64(&self) -> bool {
+    fn visit_i64(&mut self) -> bool {
         self.align_to::<i64>();
         if ! self.inner.visit_i64() { return false; }
         self.bump_past::<i64>();
         true
     }
 
-    fn visit_uint(&self) -> bool {
+    fn visit_uint(&mut self) -> bool {
         self.align_to::<uint>();
         if ! self.inner.visit_uint() { return false; }
         self.bump_past::<uint>();
         true
     }
 
-    fn visit_u8(&self) -> bool {
+    fn visit_u8(&mut self) -> bool {
         self.align_to::<u8>();
         if ! self.inner.visit_u8() { return false; }
         self.bump_past::<u8>();
         true
     }
 
-    fn visit_u16(&self) -> bool {
+    fn visit_u16(&mut self) -> bool {
         self.align_to::<u16>();
         if ! self.inner.visit_u16() { return false; }
         self.bump_past::<u16>();
         true
     }
 
-    fn visit_u32(&self) -> bool {
+    fn visit_u32(&mut self) -> bool {
         self.align_to::<u32>();
         if ! self.inner.visit_u32() { return false; }
         self.bump_past::<u32>();
         true
     }
 
-    fn visit_u64(&self) -> bool {
+    fn visit_u64(&mut self) -> bool {
         self.align_to::<u64>();
         if ! self.inner.visit_u64() { return false; }
         self.bump_past::<u64>();
         true
     }
 
-    fn visit_float(&self) -> bool {
+    fn visit_float(&mut self) -> bool {
         self.align_to::<float>();
         if ! self.inner.visit_float() { return false; }
         self.bump_past::<float>();
         true
     }
 
-    fn visit_f32(&self) -> bool {
+    fn visit_f32(&mut self) -> bool {
         self.align_to::<f32>();
         if ! self.inner.visit_f32() { return false; }
         self.bump_past::<f32>();
         true
     }
 
-    fn visit_f64(&self) -> bool {
+    fn visit_f64(&mut self) -> bool {
         self.align_to::<f64>();
         if ! self.inner.visit_f64() { return false; }
         self.bump_past::<f64>();
         true
     }
 
-    fn visit_char(&self) -> bool {
+    fn visit_char(&mut self) -> bool {
         self.align_to::<char>();
         if ! self.inner.visit_char() { return false; }
         self.bump_past::<char>();
         true
     }
 
-    fn visit_estr_box(&self) -> bool {
+    fn visit_estr_box(&mut self) -> bool {
         self.align_to::<@str>();
         if ! self.inner.visit_estr_box() { return false; }
         self.bump_past::<@str>();
         true
     }
 
-    fn visit_estr_uniq(&self) -> bool {
+    fn visit_estr_uniq(&mut self) -> bool {
         self.align_to::<~str>();
         if ! self.inner.visit_estr_uniq() { return false; }
         self.bump_past::<~str>();
         true
     }
 
-    fn visit_estr_slice(&self) -> bool {
+    fn visit_estr_slice(&mut self) -> bool {
         self.align_to::<&'static str>();
         if ! self.inner.visit_estr_slice() { return false; }
         self.bump_past::<&'static str>();
         true
     }
 
-    fn visit_estr_fixed(&self, n: uint,
+    fn visit_estr_fixed(&mut self, n: uint,
                         sz: uint,
                         align: uint) -> bool {
         self.align(align);
@@ -211,42 +210,42 @@ fn visit_estr_fixed(&self, n: uint,
         true
     }
 
-    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<@u8>();
         if ! self.inner.visit_box(mtbl, inner) { return false; }
         self.bump_past::<@u8>();
         true
     }
 
-    fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~u8>();
         if ! self.inner.visit_uniq(mtbl, inner) { return false; }
         self.bump_past::<~u8>();
         true
     }
 
-    fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~u8>();
         if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
         self.bump_past::<~u8>();
         true
     }
 
-    fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<*u8>();
         if ! self.inner.visit_ptr(mtbl, inner) { return false; }
         self.bump_past::<*u8>();
         true
     }
 
-    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<&'static u8>();
         if ! self.inner.visit_rptr(mtbl, inner) { return false; }
         self.bump_past::<&'static u8>();
         true
     }
 
-    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<Vec<()>>();
         // FIXME (#3732): Inner really has to move its own pointers on this one.
         // or else possibly we could have some weird interface wherein we
@@ -256,42 +255,42 @@ fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
         true
     }
 
-    fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~[u8]>();
         if ! self.inner.visit_vec(mtbl, inner) { return false; }
         self.bump_past::<~[u8]>();
         true
     }
 
-    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<@[u8]>();
         if ! self.inner.visit_evec_box(mtbl, inner) { return false; }
         self.bump_past::<@[u8]>();
         true
     }
 
-    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~[u8]>();
         if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; }
         self.bump_past::<~[u8]>();
         true
     }
 
-    fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<~[@u8]>();
         if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; }
         self.bump_past::<~[@u8]>();
         true
     }
 
-    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<&'static [u8]>();
         if ! self.inner.visit_evec_slice(mtbl, inner) { return false; }
         self.bump_past::<&'static [u8]>();
         true
     }
 
-    fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
+    fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
                         mtbl: uint, inner: *TyDesc) -> bool {
         self.align(align);
         if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) {
@@ -301,24 +300,24 @@ fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
         true
     }
 
-    fn visit_enter_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+    fn visit_enter_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
         self.align(align);
         if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; }
         true
     }
 
-    fn visit_rec_field(&self, i: uint, name: &str,
+    fn visit_rec_field(&mut self, i: uint, name: &str,
                        mtbl: uint, inner: *TyDesc) -> bool {
         if ! self.inner.visit_rec_field(i, name, mtbl, inner) { return false; }
         true
     }
 
-    fn visit_leave_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+    fn visit_leave_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
         if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; }
         true
     }
 
-    fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint)
+    fn visit_enter_class(&mut self, n_fields: uint, sz: uint, align: uint)
                       -> bool {
         self.align(align);
         if ! self.inner.visit_enter_class(n_fields, sz, align) {
@@ -327,7 +326,7 @@ fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint)
         true
     }
 
-    fn visit_class_field(&self, i: uint, name: &str,
+    fn visit_class_field(&mut self, i: uint, name: &str,
                          mtbl: uint, inner: *TyDesc) -> bool {
         if ! self.inner.visit_class_field(i, name, mtbl, inner) {
             return false;
@@ -335,7 +334,7 @@ fn visit_class_field(&self, i: uint, name: &str,
         true
     }
 
-    fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint)
+    fn visit_leave_class(&mut self, n_fields: uint, sz: uint, align: uint)
                       -> bool {
         if ! self.inner.visit_leave_class(n_fields, sz, align) {
             return false;
@@ -343,23 +342,23 @@ fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint)
         true
     }
 
-    fn visit_enter_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+    fn visit_enter_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
         self.align(align);
         if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; }
         true
     }
 
-    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool {
+    fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool {
         if ! self.inner.visit_tup_field(i, inner) { return false; }
         true
     }
 
-    fn visit_leave_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+    fn visit_leave_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
         if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; }
         true
     }
 
-    fn visit_enter_fn(&self, purity: uint, proto: uint,
+    fn visit_enter_fn(&mut self, purity: uint, proto: uint,
                       n_inputs: uint, retstyle: uint) -> bool {
         if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) {
             return false
@@ -367,17 +366,17 @@ fn visit_enter_fn(&self, purity: uint, proto: uint,
         true
     }
 
-    fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool {
+    fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool {
         if ! self.inner.visit_fn_input(i, mode, inner) { return false; }
         true
     }
 
-    fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool {
+    fn visit_fn_output(&mut self, retstyle: uint, inner: *TyDesc) -> bool {
         if ! self.inner.visit_fn_output(retstyle, inner) { return false; }
         true
     }
 
-    fn visit_leave_fn(&self, purity: uint, proto: uint,
+    fn visit_leave_fn(&mut self, purity: uint, proto: uint,
                       n_inputs: uint, retstyle: uint) -> bool {
         if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) {
             return false;
@@ -385,7 +384,7 @@ fn visit_leave_fn(&self, purity: uint, proto: uint,
         true
     }
 
-    fn visit_enter_enum(&self, n_variants: uint,
+    fn visit_enter_enum(&mut self, n_variants: uint,
                         get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         sz: uint, align: uint)
                      -> bool {
@@ -394,7 +393,7 @@ fn visit_enter_enum(&self, n_variants: uint,
         true
     }
 
-    fn visit_enter_enum_variant(&self, variant: uint,
+    fn visit_enter_enum_variant(&mut self, variant: uint,
                                 disr_val: int,
                                 n_fields: uint,
                                 name: &str) -> bool {
@@ -405,12 +404,12 @@ fn visit_enter_enum_variant(&self, variant: uint,
         true
     }
 
-    fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool {
+    fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool {
         if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; }
         true
     }
 
-    fn visit_leave_enum_variant(&self, variant: uint,
+    fn visit_leave_enum_variant(&mut self, variant: uint,
                                 disr_val: int,
                                 n_fields: uint,
                                 name: &str) -> bool {
@@ -421,7 +420,7 @@ fn visit_leave_enum_variant(&self, variant: uint,
         true
     }
 
-    fn visit_leave_enum(&self, n_variants: uint,
+    fn visit_leave_enum(&mut self, n_variants: uint,
                         get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         sz: uint, align: uint)
                      -> bool {
@@ -429,38 +428,38 @@ fn visit_leave_enum(&self, n_variants: uint,
         true
     }
 
-    fn visit_trait(&self) -> bool {
+    fn visit_trait(&mut self) -> bool {
         self.align_to::<@TyVisitor>();
         if ! self.inner.visit_trait() { return false; }
         self.bump_past::<@TyVisitor>();
         true
     }
 
-    fn visit_param(&self, i: uint) -> bool {
+    fn visit_param(&mut self, i: uint) -> bool {
         if ! self.inner.visit_param(i) { return false; }
         true
     }
 
-    fn visit_self(&self) -> bool {
+    fn visit_self(&mut self) -> bool {
         self.align_to::<&'static u8>();
         if ! self.inner.visit_self() { return false; }
         self.align_to::<&'static u8>();
         true
     }
 
-    fn visit_type(&self) -> bool {
+    fn visit_type(&mut self) -> bool {
         if ! self.inner.visit_type() { return false; }
         true
     }
 
-    fn visit_opaque_box(&self) -> bool {
+    fn visit_opaque_box(&mut self) -> bool {
         self.align_to::<@u8>();
         if ! self.inner.visit_opaque_box() { return false; }
         self.bump_past::<@u8>();
         true
     }
 
-    fn visit_closure_ptr(&self, ck: uint) -> bool {
+    fn visit_closure_ptr(&mut self, ck: uint) -> bool {
         self.align_to::<@fn()>();
         if ! self.inner.visit_closure_ptr(ck) { return false; }
         self.bump_past::<@fn()>();
@@ -477,17 +476,17 @@ struct Stuff {
 }
 
 impl my_visitor {
-    pub fn get<T:Clone>(&self, f: &fn(T)) {
+    pub fn get<T:Clone>(&mut self, f: &fn(T)) {
         unsafe {
             f((*(self.ptr1 as *T)).clone());
         }
     }
 
-    pub fn visit_inner(&self, inner: *TyDesc) -> bool {
+    pub fn visit_inner(&mut self, inner: *TyDesc) -> bool {
         unsafe {
             let u = my_visitor(**self);
-            let v = ptr_visit_adaptor::<my_visitor>(Inner {inner: u});
-            visit_tydesc(inner, &v as &TyVisitor);
+            let mut v = ptr_visit_adaptor::<my_visitor>(Inner {inner: u});
+            visit_tydesc(inner, &mut v as &mut TyVisitor);
             true
         }
     }
@@ -496,7 +495,7 @@ pub fn visit_inner(&self, inner: *TyDesc) -> bool {
 struct Inner<V> { inner: V }
 
 impl movable_ptr for my_visitor {
-    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) {
+    fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void) {
         self.ptr1 = adjustment(self.ptr1);
         self.ptr2 = adjustment(self.ptr2);
     }
@@ -504,125 +503,125 @@ fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) {
 
 impl TyVisitor for my_visitor {
 
-    fn visit_bot(&self) -> bool { true }
-    fn visit_nil(&self) -> bool { true }
-    fn visit_bool(&self) -> bool {
+    fn visit_bot(&mut self) -> bool { true }
+    fn visit_nil(&mut self) -> bool { true }
+    fn visit_bool(&mut self) -> bool {
         do self.get::<bool>() |b| {
             self.vals.push(b.to_str());
         };
         true
     }
-    fn visit_int(&self) -> bool {
+    fn visit_int(&mut self) -> bool {
         do self.get::<int>() |i| {
             self.vals.push(i.to_str());
         };
         true
     }
-    fn visit_i8(&self) -> bool { true }
-    fn visit_i16(&self) -> bool { true }
-    fn visit_i32(&self) -> bool { true }
-    fn visit_i64(&self) -> bool { true }
+    fn visit_i8(&mut self) -> bool { true }
+    fn visit_i16(&mut self) -> bool { true }
+    fn visit_i32(&mut self) -> bool { true }
+    fn visit_i64(&mut self) -> bool { true }
 
-    fn visit_uint(&self) -> bool { true }
-    fn visit_u8(&self) -> bool { true }
-    fn visit_u16(&self) -> bool { true }
-    fn visit_u32(&self) -> bool { true }
-    fn visit_u64(&self) -> bool { true }
+    fn visit_uint(&mut self) -> bool { true }
+    fn visit_u8(&mut self) -> bool { true }
+    fn visit_u16(&mut self) -> bool { true }
+    fn visit_u32(&mut self) -> bool { true }
+    fn visit_u64(&mut self) -> bool { true }
 
-    fn visit_float(&self) -> bool { true }
-    fn visit_f32(&self) -> bool { true }
-    fn visit_f64(&self) -> bool { true }
+    fn visit_float(&mut self) -> bool { true }
+    fn visit_f32(&mut self) -> bool { true }
+    fn visit_f64(&mut self) -> bool { true }
 
-    fn visit_char(&self) -> bool { true }
+    fn visit_char(&mut self) -> bool { true }
 
-    fn visit_estr_box(&self) -> bool { true }
-    fn visit_estr_uniq(&self) -> bool { true }
-    fn visit_estr_slice(&self) -> bool { true }
-    fn visit_estr_fixed(&self, _n: uint, _sz: uint,
+    fn visit_estr_box(&mut self) -> bool { true }
+    fn visit_estr_uniq(&mut self) -> bool { true }
+    fn visit_estr_slice(&mut self) -> bool { true }
+    fn visit_estr_fixed(&mut self, _n: uint, _sz: uint,
                         _align: uint) -> bool { true }
 
-    fn visit_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_rptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-
-    fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_unboxed_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_slice(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_fixed(&self, _n: uint, _sz: uint, _align: uint,
+    fn visit_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+
+    fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_unboxed_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint,
                         _mtbl: uint, _inner: *TyDesc) -> bool { true }
 
-    fn visit_enter_rec(&self, _n_fields: uint,
+    fn visit_enter_rec(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
-    fn visit_rec_field(&self, _i: uint, _name: &str,
+    fn visit_rec_field(&mut self, _i: uint, _name: &str,
                        _mtbl: uint, inner: *TyDesc) -> bool {
         error!("rec field!");
         self.visit_inner(inner)
     }
-    fn visit_leave_rec(&self, _n_fields: uint,
+    fn visit_leave_rec(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_class(&self, _n_fields: uint,
+    fn visit_enter_class(&mut self, _n_fields: uint,
                          _sz: uint, _align: uint) -> bool { true }
-    fn visit_class_field(&self, _i: uint, _name: &str,
+    fn visit_class_field(&mut self, _i: uint, _name: &str,
                          _mtbl: uint, inner: *TyDesc) -> bool {
         self.visit_inner(inner)
     }
-    fn visit_leave_class(&self, _n_fields: uint,
+    fn visit_leave_class(&mut self, _n_fields: uint,
                          _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_tup(&self, _n_fields: uint,
+    fn visit_enter_tup(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
-    fn visit_tup_field(&self, _i: uint, inner: *TyDesc) -> bool {
+    fn visit_tup_field(&mut self, _i: uint, inner: *TyDesc) -> bool {
         error!("tup field!");
         self.visit_inner(inner)
     }
-    fn visit_leave_tup(&self, _n_fields: uint,
+    fn visit_leave_tup(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_enum(&self, _n_variants: uint,
+    fn visit_enter_enum(&mut self, _n_variants: uint,
                         _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         _sz: uint, _align: uint) -> bool {
         // FIXME (#3732): this needs to rewind between enum variants, or something.
         true
     }
-    fn visit_enter_enum_variant(&self, _variant: uint,
+    fn visit_enter_enum_variant(&mut self, _variant: uint,
                                 _disr_val: int,
                                 _n_fields: uint,
                                 _name: &str) -> bool { true }
-    fn visit_enum_variant_field(&self, _i: uint, _offset: uint, inner: *TyDesc) -> bool {
+    fn visit_enum_variant_field(&mut self, _i: uint, _offset: uint, inner: *TyDesc) -> bool {
         self.visit_inner(inner)
     }
-    fn visit_leave_enum_variant(&self, _variant: uint,
+    fn visit_leave_enum_variant(&mut self, _variant: uint,
                                 _disr_val: int,
                                 _n_fields: uint,
                                 _name: &str) -> bool { true }
-    fn visit_leave_enum(&self, _n_variants: uint,
+    fn visit_leave_enum(&mut self, _n_variants: uint,
                         _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_fn(&self, _purity: uint, _proto: uint,
+    fn visit_enter_fn(&mut self, _purity: uint, _proto: uint,
                       _n_inputs: uint, _retstyle: uint) -> bool { true }
-    fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool {
+    fn visit_fn_input(&mut self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool {
         true
     }
-    fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool {
+    fn visit_fn_output(&mut self, _retstyle: uint, _inner: *TyDesc) -> bool {
         true
     }
-    fn visit_leave_fn(&self, _purity: uint, _proto: uint,
+    fn visit_leave_fn(&mut self, _purity: uint, _proto: uint,
                       _n_inputs: uint, _retstyle: uint) -> bool { true }
 
 
-    fn visit_trait(&self) -> bool { true }
-    fn visit_param(&self, _i: uint) -> bool { true }
-    fn visit_self(&self) -> bool { true }
-    fn visit_type(&self) -> bool { true }
-    fn visit_opaque_box(&self) -> bool { true }
-    fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
+    fn visit_trait(&mut self) -> bool { true }
+    fn visit_param(&mut self, _i: uint) -> bool { true }
+    fn visit_self(&mut self) -> bool { true }
+    fn visit_type(&mut self) -> bool { true }
+    fn visit_opaque_box(&mut self) -> bool { true }
+    fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true }
 }
 
 fn get_tydesc_for<T>(_t: T) -> *TyDesc {
@@ -640,12 +639,11 @@ pub fn main() {
         let u = my_visitor(@mut Stuff {ptr1: p,
                                        ptr2: p,
                                        vals: ~[]});
-        let v = ptr_visit_adaptor(Inner {inner: u});
+        let mut v = ptr_visit_adaptor(Inner {inner: u});
         let td = get_tydesc_for(r);
         error!("tydesc sz: %u, align: %u",
                (*td).size, (*td).align);
-        let v = &v as &TyVisitor;
-        visit_tydesc(td, v);
+        visit_tydesc(td, &mut v as &mut TyVisitor);
 
         let r = u.vals.clone();
         for s in r.iter() {
index 1462d8aace130cbe73a31ffe699a91306cabe679..934d6117647df63c9d947c0070a6130f146cb009 100644 (file)
@@ -15,157 +15,150 @@ struct MyVisitor {
 }
 
 impl TyVisitor for MyVisitor {
-    fn visit_bot(&self) -> bool {
+    fn visit_bot(&mut self) -> bool {
         self.types.push(~"bot");
         error!("visited bot type");
         true
     }
-    fn visit_nil(&self) -> bool {
+    fn visit_nil(&mut self) -> bool {
         self.types.push(~"nil");
         error!("visited nil type");
         true
     }
-    fn visit_bool(&self) -> bool {
+    fn visit_bool(&mut self) -> bool {
         self.types.push(~"bool");
         error!("visited bool type");
         true
     }
-    fn visit_int(&self) -> bool {
+    fn visit_int(&mut self) -> bool {
         self.types.push(~"int");
         error!("visited int type");
         true
     }
-    fn visit_i8(&self) -> bool {
+    fn visit_i8(&mut self) -> bool {
         self.types.push(~"i8");
         error!("visited i8 type");
         true
     }
-    fn visit_i16(&self) -> bool {
+    fn visit_i16(&mut self) -> bool {
         self.types.push(~"i16");
         error!("visited i16 type");
         true
     }
-    fn visit_i32(&self) -> bool { true }
-    fn visit_i64(&self) -> bool { true }
+    fn visit_i32(&mut self) -> bool { true }
+    fn visit_i64(&mut self) -> bool { true }
 
-    fn visit_uint(&self) -> bool { true }
-    fn visit_u8(&self) -> bool { true }
-    fn visit_u16(&self) -> bool { true }
-    fn visit_u32(&self) -> bool { true }
-    fn visit_u64(&self) -> bool { true }
+    fn visit_uint(&mut self) -> bool { true }
+    fn visit_u8(&mut self) -> bool { true }
+    fn visit_u16(&mut self) -> bool { true }
+    fn visit_u32(&mut self) -> bool { true }
+    fn visit_u64(&mut self) -> bool { true }
 
-    fn visit_float(&self) -> bool { true }
-    fn visit_f32(&self) -> bool { true }
-    fn visit_f64(&self) -> bool { true }
+    fn visit_float(&mut self) -> bool { true }
+    fn visit_f32(&mut self) -> bool { true }
+    fn visit_f64(&mut self) -> bool { true }
 
-    fn visit_char(&self) -> bool { true }
+    fn visit_char(&mut self) -> bool { true }
 
-    fn visit_estr_box(&self) -> bool { true }
-    fn visit_estr_uniq(&self) -> bool { true }
-    fn visit_estr_slice(&self) -> bool { true }
-    fn visit_estr_fixed(&self,
+    fn visit_estr_box(&mut self) -> bool { true }
+    fn visit_estr_uniq(&mut self) -> bool { true }
+    fn visit_estr_slice(&mut self) -> bool { true }
+    fn visit_estr_fixed(&mut self,
                         _sz: uint, _sz: uint,
                         _align: uint) -> bool { true }
 
-    fn visit_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_rptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
 
-    fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_unboxed_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_unboxed_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
         self.types.push(~"[");
-        unsafe {
-            visit_tydesc(inner, (&*self) as &TyVisitor);
-        }
+        unsafe { visit_tydesc(inner, &mut *self as &mut TyVisitor); }
         self.types.push(~"]");
         true
     }
-    fn visit_evec_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool {
+    fn visit_evec_uniq_managed(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
         self.types.push(~"[");
-        unsafe {
-            visit_tydesc(inner, (&*self) as &TyVisitor);
-        }
+        unsafe { visit_tydesc(inner, &mut *self as &mut TyVisitor) };
         self.types.push(~"]");
         true
     }
-    fn visit_evec_slice(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_fixed(&self, _n: uint, _sz: uint, _align: uint,
+    fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint,
                         _mtbl: uint, _inner: *TyDesc) -> bool { true }
 
-    fn visit_enter_rec(&self, _n_fields: uint,
+    fn visit_enter_rec(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
-    fn visit_rec_field(&self, _i: uint, _name: &str,
+    fn visit_rec_field(&mut self, _i: uint, _name: &str,
                        _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_rec(&self, _n_fields: uint,
+    fn visit_leave_rec(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_class(&self, _n_fields: uint,
+    fn visit_enter_class(&mut self, _n_fields: uint,
                          _sz: uint, _align: uint) -> bool { true }
-    fn visit_class_field(&self, _i: uint, _name: &str,
+    fn visit_class_field(&mut self, _i: uint, _name: &str,
                          _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_class(&self, _n_fields: uint,
+    fn visit_leave_class(&mut self, _n_fields: uint,
                          _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_tup(&self, _n_fields: uint,
+    fn visit_enter_tup(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
-    fn visit_tup_field(&self, _i: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_tup(&self, _n_fields: uint,
+    fn visit_tup_field(&mut self, _i: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_leave_tup(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_enum(&self, _n_variants: uint,
+    fn visit_enter_enum(&mut self, _n_variants: uint,
                         _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         _sz: uint, _align: uint) -> bool { true }
-    fn visit_enter_enum_variant(&self,
+    fn visit_enter_enum_variant(&mut self,
                                 _variant: uint,
                                 _disr_val: int,
                                 _n_fields: uint,
                                 _name: &str) -> bool { true }
-    fn visit_enum_variant_field(&self, _i: uint, _offset: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_enum_variant(&self,
+    fn visit_enum_variant_field(&mut self, _i: uint, _offset: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_leave_enum_variant(&mut self,
                                 _variant: uint,
                                 _disr_val: int,
                                 _n_fields: uint,
                                 _name: &str) -> bool { true }
-    fn visit_leave_enum(&self,
+    fn visit_leave_enum(&mut self,
                         _n_variants: uint,
                         _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_fn(&self, _purity: uint, _proto: uint,
+    fn visit_enter_fn(&mut self, _purity: uint, _proto: uint,
                       _n_inputs: uint, _retstyle: uint) -> bool { true }
-    fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_fn(&self, _purity: uint, _proto: uint,
+    fn visit_fn_input(&mut self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_fn_output(&mut self, _retstyle: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_leave_fn(&mut self, _purity: uint, _proto: uint,
                       _n_inputs: uint, _retstyle: uint) -> bool { true }
 
 
-    fn visit_trait(&self) -> bool { true }
-    fn visit_param(&self, _i: uint) -> bool { true }
-    fn visit_self(&self) -> bool { true }
-    fn visit_type(&self) -> bool { true }
-    fn visit_opaque_box(&self) -> bool { true }
-    fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
+    fn visit_trait(&mut self) -> bool { true }
+    fn visit_param(&mut self, _i: uint) -> bool { true }
+    fn visit_self(&mut self) -> bool { true }
+    fn visit_type(&mut self) -> bool { true }
+    fn visit_opaque_box(&mut self) -> bool { true }
+    fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true }
 }
 
-fn visit_ty<T>(v: &TyVisitor) {
-    unsafe {
-        visit_tydesc(get_tydesc::<T>(), v);
-    }
+fn visit_ty<T>(v: &mut MyVisitor) {
+    unsafe { visit_tydesc(get_tydesc::<T>(), v as &mut TyVisitor) }
 }
 
 pub fn main() {
-    let v = @MyVisitor {types: @mut ~[]};
-    let vv = v as @TyVisitor;
-
-    visit_ty::<bool>(vv);
-    visit_ty::<int>(vv);
-    visit_ty::<i8>(vv);
-    visit_ty::<i16>(vv);
-    visit_ty::<~[int]>(vv);
+    let mut v = MyVisitor {types: @mut ~[]};
+
+    visit_ty::<bool>(&mut v);
+    visit_ty::<int>(&mut v);
+    visit_ty::<i8>(&mut v);
+    visit_ty::<i16>(&mut v);
+    visit_ty::<~[int]>(&mut v);
 
     for s in v.types.iter() {
         printfln!("type: %s", (*s).clone());
diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass/rename-directory.rs
new file mode 100644 (file)
index 0000000..6079168
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test can't be a unit test in std,
+// because it needs mkdtemp, which is in extra
+
+// xfail-fast
+extern mod extra;
+
+use extra::tempfile::mkdtemp;
+use std::os;
+use std::libc;
+use std::libc::*;
+
+fn rename_directory() {
+    #[fixed_stack_segment];
+    unsafe {
+        static U_RWX: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
+
+        let tmpdir = mkdtemp(&os::tmpdir(), "rename_directory").expect("rename_directory failed");
+        let old_path = tmpdir.push_many(["foo", "bar", "baz"]);
+        assert!(os::mkdir_recursive(&old_path, U_RWX));
+        let test_file = &old_path.push("temp.txt");
+
+        /* Write the temp input file */
+        let ostream = do test_file.to_str().with_c_str |fromp| {
+            do "w+b".with_c_str |modebuf| {
+                libc::fopen(fromp, modebuf)
+            }
+        };
+        assert!((ostream as uint != 0u));
+        let s = ~"hello";
+        do "hello".with_c_str |buf| {
+            let write_len = libc::fwrite(buf as *c_void,
+                                         1u as size_t,
+                                         (s.len() + 1u) as size_t,
+                                         ostream);
+            assert_eq!(write_len, (s.len() + 1) as size_t)
+        }
+        assert_eq!(libc::fclose(ostream), (0u as c_int));
+
+        let new_path = tmpdir.push_many(["quux", "blat"]);
+        assert!(os::mkdir_recursive(&new_path, U_RWX));
+        assert!(os::rename_file(&old_path, &new_path.push("newdir")));
+        assert!(os::path_is_dir(&new_path.push("newdir")));
+        assert!(os::path_exists(&new_path.push_many(["newdir", "temp.txt"])));
+    }
+}
+
+fn main() { rename_directory() }
index 520b3583195ae75b6548e3b7f96634be6186380c..651b3342d5833e3f612c1f62384b9fab8d65c76f 100644 (file)
@@ -10,8 +10,6 @@
 
 // xfail-fast
 
-use std::uint;
-
 pub trait plus {
     fn plus(&self) -> int;
 }
index 6916db28e11ea611b08b7b99aef3ed7589ce3ab8..f448bcb4ab5d27fda032df640a84f5ae4f3ff2b3 100644 (file)
@@ -10,8 +10,6 @@
 
 // xfail-fast
 
-use std::int;
-
 trait to_str {
     fn to_string(&self) -> ~str;
 }