]> git.lizzy.rs Git - rust.git/commitdiff
Merge branch 'issue-8393-attributes-in-macros' of https://github.com/nikomatsakis...
authorErick Tryzelaar <erick.tryzelaar@gmail.com>
Sat, 10 Aug 2013 20:03:19 +0000 (13:03 -0700)
committerErick Tryzelaar <erick.tryzelaar@gmail.com>
Sat, 10 Aug 2013 20:03:19 +0000 (13:03 -0700)
258 files changed:
doc/rust.md
doc/tutorial.md
mk/install.mk
mk/rt.mk
mk/tests.mk
src/compiletest/header.rs
src/compiletest/runtest.rs
src/etc/emacs/rust-mode.el
src/libextra/arc.rs
src/libextra/bitv.rs
src/libextra/dlist.rs
src/libextra/fileinput.rs
src/libextra/future.rs
src/libextra/getopts.rs
src/libextra/json.rs
src/libextra/num/bigint.rs
src/libextra/par.rs
src/libextra/priority_queue.rs
src/libextra/ringbuf.rs
src/libextra/rl.rs
src/libextra/smallintmap.rs
src/libextra/sort.rs
src/libextra/sync.rs
src/libextra/task_pool.rs
src/libextra/terminfo/parm.rs
src/libextra/terminfo/parser/compiled.rs
src/libextra/test.rs
src/libextra/time.rs
src/libextra/treemap.rs
src/libextra/workcache.rs
src/librust/rust.rs
src/librustc/back/link.rs
src/librustc/back/passes.rs
src/librustc/back/rpath.rs
src/librustc/driver/driver.rs
src/librustc/front/config.rs
src/librustc/front/std_inject.rs
src/librustc/front/test.rs
src/librustc/lib/llvm.rs
src/librustc/metadata/common.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/loader.rs
src/librustc/middle/astencode.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/check_match.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/lint.rs
src/librustc/middle/privacy.rs
src/librustc/middle/resolve.rs
src/librustc/middle/trans/_match.rs
src/librustc/middle/trans/adt.rs
src/librustc/middle/trans/asm.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/basic_block.rs [new file with mode: 0644]
src/librustc/middle/trans/builder.rs
src/librustc/middle/trans/cabi.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/consts.rs
src/librustc/middle/trans/context.rs
src/librustc/middle/trans/controlflow.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/glue.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/mod.rs
src/librustc/middle/trans/monomorphize.rs
src/librustc/middle/trans/reflect.rs
src/librustc/middle/trans/tvec.rs
src/librustc/middle/trans/type_.rs
src/librustc/middle/trans/value.rs [new file with mode: 0644]
src/librustc/middle/ty.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/method.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/vtable.rs
src/librustc/middle/typeck/coherence.rs
src/librustc/middle/typeck/collect.rs
src/librustc/rustc.rs
src/librustdoc/attr_parser.rs
src/librustdoc/attr_pass.rs
src/librustdoc/config.rs
src/librustdoc/extract.rs
src/librustdoc/fold.rs
src/librustdoc/page_pass.rs
src/librustdoc/prune_hidden_pass.rs
src/librustdoc/prune_private_pass.rs
src/librustdoc/tystr_pass.rs
src/librusti/program.rs
src/librusti/rusti.rs
src/librustpkg/api.rs
src/librustpkg/context.rs
src/librustpkg/installed_packages.rs
src/librustpkg/package_id.rs
src/librustpkg/package_path.rs [deleted file]
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/at_vec.rs
src/libstd/bool.rs
src/libstd/c_str.rs [new file with mode: 0644]
src/libstd/cast.rs
src/libstd/char.rs
src/libstd/cleanup.rs
src/libstd/cmp.rs
src/libstd/comm.rs
src/libstd/either.rs
src/libstd/hashmap.rs
src/libstd/io.rs
src/libstd/iterator.rs
src/libstd/libc.rs
src/libstd/logging.rs
src/libstd/nil.rs
src/libstd/num/int_macros.rs
src/libstd/num/uint_macros.rs
src/libstd/option.rs
src/libstd/os.rs
src/libstd/path.rs
src/libstd/pipes.rs [deleted file]
src/libstd/prelude.rs
src/libstd/ptr.rs
src/libstd/result.rs
src/libstd/rt/borrowck.rs
src/libstd/rt/comm.rs
src/libstd/rt/env.rs
src/libstd/rt/io/comm_adapters.rs
src/libstd/rt/io/net/ip.rs
src/libstd/rt/kill.rs
src/libstd/rt/local_heap.rs
src/libstd/rt/logging.rs
src/libstd/rt/mod.rs
src/libstd/rt/sched.rs
src/libstd/rt/select.rs
src/libstd/rt/task.rs
src/libstd/rt/test.rs
src/libstd/rt/util.rs
src/libstd/rt/uv/net.rs
src/libstd/rt/uv/uvio.rs
src/libstd/rt/uv/uvll.rs
src/libstd/run.rs
src/libstd/std.rs
src/libstd/str.rs
src/libstd/str/ascii.rs
src/libstd/sys.rs
src/libstd/task/local_data_priv.rs
src/libstd/task/mod.rs
src/libstd/task/rt.rs [deleted file]
src/libstd/task/spawn.rs
src/libstd/to_bytes.rs
src/libstd/trie.rs
src/libstd/tuple.rs
src/libstd/unstable/dynamic_lib.rs
src/libstd/unstable/extfmt.rs
src/libstd/unstable/lang.rs
src/libstd/unstable/sync.rs
src/libstd/vec.rs
src/libsyntax/ast.rs
src/libsyntax/ast_util.rs
src/libsyntax/attr.rs
src/libsyntax/ext/asm.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/cfg.rs
src/libsyntax/ext/deriving/decodable.rs
src/libsyntax/ext/deriving/generic.rs
src/libsyntax/ext/deriving/rand.rs
src/libsyntax/ext/env.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/fmt.rs
src/libsyntax/ext/ifmt.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/fold.rs
src/libsyntax/opt_vec.rs
src/libsyntax/parse/comments.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/rt/boxed_region.cpp
src/rt/rust.cpp [deleted file]
src/rt/rust_builtin.cpp
src/rt/rust_crate_map.h
src/rt/rust_debug.cpp [deleted file]
src/rt/rust_debug.h [deleted file]
src/rt/rust_kernel.cpp [deleted file]
src/rt/rust_kernel.h [deleted file]
src/rt/rust_log.cpp
src/rt/rust_log.h
src/rt/rust_run_program.cpp
src/rt/rust_sched_driver.cpp [deleted file]
src/rt/rust_sched_driver.h [deleted file]
src/rt/rust_sched_launcher.cpp [deleted file]
src/rt/rust_sched_launcher.h [deleted file]
src/rt/rust_sched_loop.cpp [deleted file]
src/rt/rust_sched_loop.h [deleted file]
src/rt/rust_sched_reaper.cpp [deleted file]
src/rt/rust_sched_reaper.h [deleted file]
src/rt/rust_scheduler.cpp [deleted file]
src/rt/rust_scheduler.h [deleted file]
src/rt/rust_task.cpp [deleted file]
src/rt/rust_task.h [deleted file]
src/rt/rust_test_helpers.cpp
src/rt/rust_upcall.cpp
src/rt/rust_util.h
src/rt/rust_uv.cpp
src/rt/rustrt.def.in
src/test/auxiliary/xc_private_method_lib.rs
src/test/bench/graph500-bfs.rs
src/test/bench/rt-messaging-ping-pong.rs [new file with mode: 0644]
src/test/bench/rt-parfib.rs [new file with mode: 0644]
src/test/bench/rt-spawn-rate.rs [new file with mode: 0644]
src/test/bench/shootout-chameneos-redux.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/task-perf-one-million.rs
src/test/codegen/single-return-value.cc [new file with mode: 0644]
src/test/codegen/single-return-value.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
src/test/compile-fail/borrowck-vec-pattern-nesting.rs
src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
src/test/compile-fail/extenv-arg-2-not-string-literal.rs [new file with mode: 0644]
src/test/compile-fail/extenv-no-args.rs
src/test/compile-fail/extenv-not-defined-custom.rs [new file with mode: 0644]
src/test/compile-fail/extenv-not-defined-default.rs [new file with mode: 0644]
src/test/compile-fail/extenv-not-string-literal.rs
src/test/compile-fail/extenv-too-many-args.rs
src/test/compile-fail/extoption_env-no-args.rs [new file with mode: 0644]
src/test/compile-fail/extoption_env-not-string-literal.rs [new file with mode: 0644]
src/test/compile-fail/extoption_env-too-many-args.rs [new file with mode: 0644]
src/test/compile-fail/issue-2766-a.rs [deleted file]
src/test/compile-fail/match-vec-fixed.rs [new file with mode: 0644]
src/test/compile-fail/match-vec-unreachable.rs
src/test/compile-fail/static-slice-not-null-terminated.rs [deleted file]
src/test/compile-fail/xc-private-method.rs
src/test/run-pass/binops.rs
src/test/run-pass/block-arg.rs
src/test/run-pass/c-stack-as-value.rs
src/test/run-pass/c-stack-returning-int64.rs
src/test/run-pass/const-str-ptr.rs
src/test/run-pass/extern-mod-url.rs [deleted file]
src/test/run-pass/extoption_env-not-defined.rs [new file with mode: 0644]
src/test/run-pass/foreign-fn-linkname.rs
src/test/run-pass/issue-1251.rs
src/test/run-pass/issue-4446.rs
src/test/run-pass/issue-5530.rs
src/test/run-pass/item-attributes.rs
src/test/run-pass/match-enum-struct-0.rs [new file with mode: 0644]
src/test/run-pass/match-enum-struct-1.rs [new file with mode: 0644]
src/test/run-pass/match-struct-0.rs [new file with mode: 0644]
src/test/run-pass/trait-to-str.rs
src/test/run-pass/vec-matching-fixed.rs [new file with mode: 0644]
src/test/run-pass/vec-matching.rs
src/test/run-pass/vec-tail-matching.rs

index 2f5c310ec8328adec207bd7b0b87f2106e14c780..d285253ffe200158075a3e305131aec574079966 100644 (file)
@@ -744,7 +744,7 @@ There are several kinds of view item:
 ##### Extern mod declarations
 
 ~~~~~~~~ {.ebnf .gram}
-extern_mod_decl : "extern" "mod" ident [ '(' link_attrs ')' ] ? ;
+extern_mod_decl : "extern" "mod" ident [ '(' link_attrs ')' ] ? [ '=' string_lit ] ? ;
 link_attrs : link_attr [ ',' link_attrs ] + ;
 link_attr : ident '=' literal ;
 ~~~~~~~~
@@ -755,13 +755,25 @@ as the `ident` provided in the `extern_mod_decl`.
 
 The external crate is resolved to a specific `soname` at compile time,
 and a runtime linkage requirement to that `soname` is passed to the linker for
-loading at runtime. The `soname` is resolved at compile time by scanning the
-compiler's library path and matching the `link_attrs` provided in the
-`use_decl` against any `#link` attributes that were declared on the external
-crate when it was compiled. If no `link_attrs` are provided, a default `name`
-attribute is assumed, equal to the `ident` given in the `use_decl`.
-
-Three examples of `extern mod` declarations:
+loading at runtime.
+The `soname` is resolved at compile time by scanning the compiler's library path
+and matching the `link_attrs` provided in the `use_decl` against any `#link` attributes that
+were declared on the external crate when it was compiled.
+If no `link_attrs` are provided,
+a default `name` attribute is assumed,
+equal to the `ident` given in the `use_decl`.
+
+Optionally, an identifier in an `extern mod` declaration may be followed by an equals sign,
+then a string literal denoting a relative path on the filesystem.
+This path should exist in one of the directories in the Rust path,
+which by default contains the `.rust` subdirectory of the current directory and each of its parents,
+as well as any directories in the colon-separated (or semicolon-separated on Windows)
+list of paths that is the `RUST_PATH` environment variable.
+The meaning of `extern mod a = "b/c/d";`, supposing that `/a` is in the RUST_PATH,
+is that the name `a` should be taken as a reference to the crate whose absolute location is
+`/a/b/c/d`.
+
+Four examples of `extern mod` declarations:
 
 ~~~~~~~~{.xfail-test}
 extern mod pcre (uuid = "54aba0f8-a7b1-4beb-92f1-4cf625264841");
@@ -769,6 +781,8 @@ extern mod pcre (uuid = "54aba0f8-a7b1-4beb-92f1-4cf625264841");
 extern mod extra; // equivalent to: extern mod extra ( name = "extra" );
 
 extern mod rustextra (name = "extra"); // linking to 'extra' under another name
+
+extern mod complicated_mod = "some-file/in/the-rust/path";
 ~~~~~~~~
 
 ##### Use declarations
index 40e276ae04a158e92ecaf413bfbb12734f7d42a2..74d9b0fbfdab6103e90e734fdc7d7539086086ea 100644 (file)
@@ -1305,7 +1305,7 @@ match crayons[0] {
 A vector can be destructured using pattern matching:
 
 ~~~~
-let numbers: [int, ..3] = [1, 2, 3];
+let numbers: &[int] = &[1, 2, 3];
 let score = match numbers {
     [] => 0,
     [a] => a * 10,
index 07cb21217ae3ffba7fb5cb3793f80db588c0631e..4b50c5aa7963f2d3ddea4107a5bd800913a183e9 100644 (file)
@@ -199,7 +199,7 @@ endef
 $(foreach target,$(CFG_TARGET_TRIPLES), \
   $(if $(findstring $(target),"arm-linux-androideabi"), \
     $(if $(findstring adb,$(CFG_ADB)), \
-      $(if $(findstring device,$(shell adb devices 2>/dev/null | grep -E '^[_A-Za-z0-9-]+[[:blank:]]+device')), \
+      $(if $(findstring device,$(shell $(CFG_ADB) devices 2>/dev/null | grep -E '^[_A-Za-z0-9-]+[[:blank:]]+device')), \
         $(info install: install-runtime-target for $(target) enabled \
           $(info install: android device attached) \
           $(eval $(call DEF_ADB_DEVICE_STATUS, true))), \
index da950dffab5bfa6437fb8e004a325e901fd25d7d..0aeeec3b487e80f2bc05ca0cc9f1c627dd388d70 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -66,30 +66,21 @@ RUNTIME_CXXS_$(1)_$(2) := \
               rt/sync/timer.cpp \
               rt/sync/lock_and_signal.cpp \
               rt/sync/rust_thread.cpp \
-              rt/rust.cpp \
               rt/rust_builtin.cpp \
               rt/rust_run_program.cpp \
               rt/rust_env.cpp \
               rt/rust_rng.cpp \
-              rt/rust_sched_loop.cpp \
-              rt/rust_sched_launcher.cpp \
-              rt/rust_sched_driver.cpp \
-              rt/rust_scheduler.cpp \
-              rt/rust_sched_reaper.cpp \
-              rt/rust_task.cpp \
               rt/rust_stack.cpp \
               rt/rust_upcall.cpp \
               rt/rust_uv.cpp \
               rt/rust_crate_map.cpp \
-              rt/rust_log.cpp \
               rt/rust_gc_metadata.cpp \
               rt/rust_util.cpp \
+              rt/rust_log.cpp \
               rt/rust_exchange_alloc.cpp \
               rt/isaac/randport.cpp \
               rt/miniz.cpp \
-              rt/rust_kernel.cpp \
               rt/rust_abi.cpp \
-              rt/rust_debug.cpp \
               rt/memory_region.cpp \
               rt/boxed_region.cpp \
               rt/arch/$$(HOST_$(1))/context.cpp \
index 682ea3e5f69461fa27ab2bb43feb6e0709bdcec6..349ffc63d9701362a37ba726dfba2c1b49996ecb 100644 (file)
@@ -123,7 +123,7 @@ endef
 $(foreach target,$(CFG_TARGET_TRIPLES), \
   $(if $(findstring $(target),"arm-linux-androideabi"), \
     $(if $(findstring adb,$(CFG_ADB)), \
-      $(if $(findstring device,$(shell adb devices 2>/dev/null | grep -E '^[_A-Za-z0-9-]+[[:blank:]]+device')), \
+      $(if $(findstring device,$(shell $(CFG_ADB) devices 2>/dev/null | grep -E '^[_A-Za-z0-9-]+[[:blank:]]+device')), \
         $(info check: $(target) test enabled \
           $(info check: android device attached) \
           $(eval $(call DEF_ADB_DEVICE_STATUS, true))), \
@@ -348,7 +348,9 @@ $(3)/stage$(1)/test/rustpkgtest-$(2)$$(X_$(2)):                                     \
                $$(RUSTPKG_LIB) $$(RUSTPKG_INPUTS)              \
                $$(SREQ$(1)_T_$(2)_H_$(3)) \
                $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \
-               $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2))
+               $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) \
+               $$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$$(X_$(2)) \
+               $$(TBIN$(1)_T_$(2)_H_$(3))/rustc$$(X_$(2))
        @$$(call E, compile_and_link: $$@)
        $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
 
index a07da151afc3b8d244a4b1f710b69787f82d8f2c..5e3687d70575d3092fc46d5f9bb53553bdb40310 100644 (file)
@@ -142,7 +142,7 @@ fn parse_check_line(line: &str) -> Option<~str> {
 fn parse_exec_env(line: &str) -> Option<(~str, ~str)> {
     do parse_name_value_directive(line, ~"exec-env").map |nv| {
         // nv is either FOO or FOO=BAR
-        let mut strs: ~[~str] = nv.splitn_iter('=', 1).transform(|s| s.to_owned()).collect();
+        let mut strs: ~[~str] = nv.splitn_iter('=', 1).map(|s| s.to_owned()).collect();
 
         match strs.len() {
           1u => (strs.pop(), ~""),
index 9c176b504b2ee61fcb7440687d91412b294f0fad..0fb64152d376c6eab42d744c83e21a3abf695979 100644 (file)
@@ -350,13 +350,13 @@ fn check_expected_errors(expected_errors: ~[errors::ExpectedError],
         fatal(~"process did not return an error status");
     }
 
-    let prefixes = expected_errors.iter().transform(|ee| {
+    let prefixes = expected_errors.iter().map(|ee| {
         fmt!("%s:%u:", testfile.to_str(), ee.line)
     }).collect::<~[~str]>();
 
     fn to_lower( s : &str ) -> ~str {
         let i = s.iter();
-        let c : ~[char] = i.transform( |c| {
+        let c : ~[char] = i.map( |c| {
             if c.is_ascii() {
                 c.to_ascii().to_lower().to_char()
             } else {
@@ -760,7 +760,7 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
     let cmdline = make_cmdline("", args.prog, args.args);
 
     // get bare program string
-    let mut tvec: ~[~str] = args.prog.split_iter('/').transform(|ts| ts.to_owned()).collect();
+    let mut tvec: ~[~str] = args.prog.split_iter('/').map(|ts| ts.to_owned()).collect();
     let prog_short = tvec.pop();
 
     // copy to target
@@ -938,7 +938,7 @@ fn disassemble_extract(config: &config, _props: &TestProps,
 
 fn count_extracted_lines(p: &Path) -> uint {
     let x = io::read_whole_file_str(&p.with_filetype("ll")).unwrap();
-    x.line_iter().len_()
+    x.line_iter().len()
 }
 
 
index 87c505e69d0b90fb3b9bc9c589723b29e0b0a488..ecb223f896c37f668901c0a9c228f9451626c742 100644 (file)
 
     table))
 
+(defcustom rust-indent-offset default-tab-width
+  "*Indent Rust code by this number of spaces.
+
+The initializer is `DEFAULT-TAB-WIDTH'.")
+
 (defun rust-paren-level () (nth 0 (syntax-ppss)))
 (defun rust-in-str-or-cmnt () (nth 8 (syntax-ppss)))
 (defun rust-rewind-past-str-cmnt () (goto-char (nth 8 (syntax-ppss))))
            (let ((level (rust-paren-level)))
              (cond
               ;; A function return type is 1 level indented
-              ((looking-at "->") (* default-tab-width (+ level 1)))
+              ((looking-at "->") (* rust-indent-offset (+ level 1)))
 
               ;; A closing brace is 1 level unindended
-              ((looking-at "}") (* default-tab-width (- level 1)))
+              ((looking-at "}") (* rust-indent-offset (- level 1)))
 
               ;; If we're in any other token-tree / sexp, then:
               ;;  - [ or ( means line up with the opening token
                      (goto-char pt)
                      (back-to-indentation)
                      (if (looking-at "\\<else\\>")
-                         (* default-tab-width (+ 1 level))
+                         (* rust-indent-offset (+ 1 level))
                        (progn
                          (goto-char pt)
                          (beginning-of-line)
                          (rust-rewind-irrelevant)
                          (end-of-line)
                          (if (looking-back "[{};,]")
-                             (* default-tab-width level)
+                             (* rust-indent-offset level)
                            (back-to-indentation)
                            (if (looking-at "#")
-                               (* default-tab-width level)
-                             (* default-tab-width (+ 1 level))))))))))
+                               (* rust-indent-offset level)
+                             (* rust-indent-offset (+ 1 level))))))))))
 
               ;; Otherwise we're in a column-zero definition
               (t 0))))))
index 69203b753cdc5c0159bf7be6e83092771b2e721a..5f00f1abae0eb26ca07ad866c6d233d8b1387aa4 100644 (file)
@@ -596,14 +596,14 @@ fn test_mutex_arc_condvar() {
             let (c,p) = (Cell::new(c), Cell::new(p));
             do task::spawn || {
                 // wait until parent gets in
-                comm::recv_one(p.take());
+                p.take().recv();
                 do arc2.access_cond |state, cond| {
                     *state = true;
                     cond.signal();
                 }
             }
             do arc.access_cond |state, cond| {
-                comm::send_one(c.take(), ());
+                c.take().send(());
                 assert!(!*state);
                 while !*state {
                     cond.wait();
index 20a3add3e7b3d64e7a79d6b03daaa9af6ada9ec3..63d62bd48098055c817fc71eb06d105bc288ed74 100644 (file)
@@ -869,7 +869,7 @@ fn common_iter<'a>(&'a self, other: &'a BitvSet)
         let min = num::min(self.bitv.storage.len(), other.bitv.storage.len());
         self.bitv.storage.slice(0, min).iter().enumerate()
             .zip(Repeat::new(&other.bitv.storage))
-            .transform(|((i, &w), o_store)| (i * uint::bits, w, o_store[i]))
+            .map(|((i, &w), o_store)| (i * uint::bits, w, o_store[i]))
     }
 
     /// Visits each word in self or other that extends beyond the other. This
@@ -888,11 +888,11 @@ fn outlier_iter<'a>(&'a self, other: &'a BitvSet)
         if olen < slen {
             self.bitv.storage.slice_from(olen).iter().enumerate()
                 .zip(Repeat::new(olen))
-                .transform(|((i, &w), min)| (true, (i + min) * uint::bits, w))
+                .map(|((i, &w), min)| (true, (i + min) * uint::bits, w))
         } else {
             other.bitv.storage.slice_from(slen).iter().enumerate()
                 .zip(Repeat::new(slen))
-                .transform(|((i, &w), min)| (false, (i + min) * uint::bits, w))
+                .map(|((i, &w), min)| (false, (i + min) * uint::bits, w))
         }
     }
 }
index b0839a55795b760ccf0efdaba987c0d9edf6df35..19a72b0029fb2ab86b2aafb602727d7aa420c7b1 100644 (file)
@@ -63,7 +63,7 @@ pub struct MutDListIterator<'self, T> {
 
 /// DList consuming iterator
 #[deriving(Clone)]
-pub struct ConsumeIterator<T> {
+pub struct MoveIterator<T> {
     priv list: DList<T>
 }
 
@@ -391,14 +391,14 @@ pub fn mut_rev_iter<'a>(&'a mut self) -> Invert<MutDListIterator<'a, T>> {
 
     /// Consume the list into an iterator yielding elements by value
     #[inline]
-    pub fn consume_iter(self) -> ConsumeIterator<T> {
-        ConsumeIterator{list: self}
+    pub fn move_iter(self) -> MoveIterator<T> {
+        MoveIterator{list: self}
     }
 
     /// Consume the list into an iterator yielding elements by value, in reverse
     #[inline]
-    pub fn consume_rev_iter(self) -> Invert<ConsumeIterator<T>> {
-        self.consume_iter().invert()
+    pub fn move_rev_iter(self) -> Invert<MoveIterator<T>> {
+        self.move_iter().invert()
     }
 }
 
@@ -557,7 +557,7 @@ fn peek_next<'a>(&'a mut self) -> Option<&'a mut A> {
     }
 }
 
-impl<A> Iterator<A> for ConsumeIterator<A> {
+impl<A> Iterator<A> for MoveIterator<A> {
     #[inline]
     fn next(&mut self) -> Option<A> { self.list.pop_front() }
 
@@ -567,7 +567,7 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
-impl<A> DoubleEndedIterator<A> for ConsumeIterator<A> {
+impl<A> DoubleEndedIterator<A> for MoveIterator<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> { self.list.pop_back() }
 }
@@ -600,7 +600,7 @@ fn ne(&self, other: &DList<A>) -> bool {
 
 impl<A: Clone> Clone for DList<A> {
     fn clone(&self) -> DList<A> {
-        self.iter().transform(|x| x.clone()).collect()
+        self.iter().map(|x| x.clone()).collect()
     }
 }
 
@@ -690,7 +690,7 @@ fn generate_test() -> DList<int> {
 
     #[cfg(test)]
     fn list_from<T: Clone>(v: &[T]) -> DList<T> {
-        v.iter().transform(|x| (*x).clone()).collect()
+        v.iter().map(|x| (*x).clone()).collect()
     }
 
     #[test]
@@ -721,7 +721,7 @@ fn test_append() {
         check_links(&m);
         let sum = v + u;
         assert_eq!(sum.len(), m.len());
-        for elt in sum.consume_iter() {
+        for elt in sum.move_iter() {
             assert_eq!(m.pop_front(), Some(elt))
         }
     }
@@ -745,7 +745,7 @@ fn test_prepend() {
         check_links(&m);
         let sum = u + v;
         assert_eq!(sum.len(), m.len());
-        for elt in sum.consume_iter() {
+        for elt in sum.move_iter() {
             assert_eq!(m.pop_front(), Some(elt))
         }
     }
@@ -770,7 +770,7 @@ fn test_rotate() {
         m.rotate_backward(); check_links(&m);
         m.push_front(9); check_links(&m);
         m.rotate_forward(); check_links(&m);
-        assert_eq!(~[3,9,5,1,2], m.consume_iter().collect());
+        assert_eq!(~[3,9,5,1,2], m.move_iter().collect());
     }
 
     #[test]
@@ -900,7 +900,7 @@ fn test_insert_prev() {
         }
         check_links(&m);
         assert_eq!(m.len(), 3 + len * 2);
-        assert_eq!(m.consume_iter().collect::<~[int]>(), ~[-2,0,1,2,3,4,5,6,7,8,9,0,1]);
+        assert_eq!(m.move_iter().collect::<~[int]>(), ~[-2,0,1,2,3,4,5,6,7,8,9,0,1]);
     }
 
     #[test]
@@ -911,7 +911,7 @@ fn test_merge() {
         m.merge(n, |a, b| a <= b);
         assert_eq!(m.len(), len);
         check_links(&m);
-        let res = m.consume_iter().collect::<~[int]>();
+        let res = m.move_iter().collect::<~[int]>();
         assert_eq!(res, ~[-1, 0, 0, 0, 1, 3, 5, 6, 7, 2, 7, 7, 9]);
     }
 
@@ -927,7 +927,7 @@ fn test_insert_ordered() {
         m.push_back(4);
         m.insert_ordered(3);
         check_links(&m);
-        assert_eq!(~[2,3,4], m.consume_iter().collect::<~[int]>());
+        assert_eq!(~[2,3,4], m.move_iter().collect::<~[int]>());
     }
 
     #[test]
@@ -1003,7 +1003,7 @@ fn fuzz_test(sz: int) {
         check_links(&m);
 
         let mut i = 0u;
-        for (a, &b) in m.consume_iter().zip(v.iter()) {
+        for (a, &b) in m.move_iter().zip(v.iter()) {
             i += 1;
             assert_eq!(a, b);
         }
@@ -1014,7 +1014,7 @@ fn fuzz_test(sz: int) {
     fn bench_collect_into(b: &mut test::BenchHarness) {
         let v = &[0, ..64];
         do b.iter {
-            let _: DList<int> = v.iter().transform(|x| *x).collect();
+            let _: DList<int> = v.iter().map(|x| *x).collect();
         }
     }
 
@@ -1075,33 +1075,33 @@ fn bench_rotate_backward(b: &mut test::BenchHarness) {
     #[bench]
     fn bench_iter(b: &mut test::BenchHarness) {
         let v = &[0, ..128];
-        let m: DList<int> = v.iter().transform(|&x|x).collect();
+        let m: DList<int> = v.iter().map(|&x|x).collect();
         do b.iter {
-            assert!(m.iter().len_() == 128);
+            assert!(m.iter().len() == 128);
         }
     }
     #[bench]
     fn bench_iter_mut(b: &mut test::BenchHarness) {
         let v = &[0, ..128];
-        let mut m: DList<int> = v.iter().transform(|&x|x).collect();
+        let mut m: DList<int> = v.iter().map(|&x|x).collect();
         do b.iter {
-            assert!(m.mut_iter().len_() == 128);
+            assert!(m.mut_iter().len() == 128);
         }
     }
     #[bench]
     fn bench_iter_rev(b: &mut test::BenchHarness) {
         let v = &[0, ..128];
-        let m: DList<int> = v.iter().transform(|&x|x).collect();
+        let m: DList<int> = v.iter().map(|&x|x).collect();
         do b.iter {
-            assert!(m.rev_iter().len_() == 128);
+            assert!(m.rev_iter().len() == 128);
         }
     }
     #[bench]
     fn bench_iter_mut_rev(b: &mut test::BenchHarness) {
         let v = &[0, ..128];
-        let mut m: DList<int> = v.iter().transform(|&x|x).collect();
+        let mut m: DList<int> = v.iter().map(|&x|x).collect();
         do b.iter {
-            assert!(m.mut_rev_iter().len_() == 128);
+            assert!(m.mut_rev_iter().len() == 128);
         }
     }
 }
index 14b02688cffcfc1481ff2927727b3ab5c0981a1e..e268e83bf3fb0653d290147ee24bb7fb1844406e 100644 (file)
@@ -353,7 +353,7 @@ fn tell(&self) -> uint {
 */
 // XXX: stupid, unclear name
 pub fn pathify(vec: &[~str], stdin_hyphen : bool) -> ~[Option<Path>] {
-    vec.iter().transform(|str| {
+    vec.iter().map(|str| {
         if stdin_hyphen && "-" == *str {
             None
         } else {
index cc65c49d73a9c2b569619591a145df84c8036d3f..391e4baa8c9da417c67561447cdec71dd8dbbbd6 100644 (file)
@@ -28,7 +28,7 @@
 
 use std::cast;
 use std::cell::Cell;
-use std::comm::{PortOne, oneshot, send_one, recv_one};
+use std::comm::{PortOne, oneshot};
 use std::task;
 use std::util::replace;
 
@@ -123,7 +123,7 @@ pub fn from_port<A:Send>(port: PortOne<A>) -> Future<A> {
 
     let port = Cell::new(port);
     do from_fn {
-        recv_one(port.take())
+        port.take().recv()
     }
 }
 
@@ -152,7 +152,7 @@ pub fn spawn<A:Send>(blk: ~fn() -> A) -> Future<A> {
     let chan = Cell::new(chan);
     do task::spawn {
         let chan = chan.take();
-        send_one(chan, blk());
+        chan.send(blk());
     }
 
     return from_port(port);
@@ -163,7 +163,7 @@ mod test {
     use future::*;
 
     use std::cell::Cell;
-    use std::comm::{oneshot, send_one};
+    use std::comm::oneshot;
     use std::task;
 
     #[test]
@@ -175,7 +175,7 @@ fn test_from_value() {
     #[test]
     fn test_from_port() {
         let (po, ch) = oneshot();
-        send_one(ch, ~"whale");
+        ch.send(~"whale");
         let mut f = from_port(po);
         assert_eq!(f.get(), ~"whale");
     }
index 1b65528923a100c16a5c50108447d92dd1a637e1..000520fe41e6e5200a4d1aea90ebe62d4c300565 100644 (file)
@@ -647,7 +647,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str {
 
         let desc_sep = "\n" + " ".repeat(24);
 
-        let mut rows = opts.iter().transform(|optref| {
+        let mut rows = opts.iter().map(|optref| {
             let OptGroup{short_name: short_name,
                          long_name: long_name,
                          hint: hint,
index ec9cb902d3d29125229303677e178e4622145903..2287384b53a0e153385dd1fceac5477662d52f41 100644 (file)
@@ -948,7 +948,7 @@ fn read_enum_variant<T>(&mut self,
         let name = match self.stack.pop() {
             String(s) => s,
             List(list) => {
-                for v in list.consume_rev_iter() {
+                for v in list.move_rev_iter() {
                     self.stack.push(v);
                 }
                 match self.stack.pop() {
@@ -1066,7 +1066,7 @@ fn read_seq<T>(&mut self, f: &fn(&mut Decoder, uint) -> T) -> T {
         let len = match self.stack.pop() {
             List(list) => {
                 let len = list.len();
-                for v in list.consume_rev_iter() {
+                for v in list.move_rev_iter() {
                     self.stack.push(v);
                 }
                 len
@@ -1086,7 +1086,7 @@ fn read_map<T>(&mut self, f: &fn(&mut Decoder, uint) -> T) -> T {
         let len = match self.stack.pop() {
             Object(obj) => {
                 let len = obj.len();
-                for (key, value) in obj.consume_iter() {
+                for (key, value) in obj.move_iter() {
                     self.stack.push(value);
                     self.stack.push(String(key));
                 }
index 0c8701bd0b515b1db16a6dc7dc5f0b958cdb0558..27dfc090f8888a093fd01a766e46b7ca0bf5f8f5 100644 (file)
@@ -287,7 +287,7 @@ fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint {
             if n == 1 { return (*a).clone(); }
 
             let mut carry = 0;
-            let mut prod = do a.data.iter().transform |ai| {
+            let mut prod = do a.data.iter().map |ai| {
                 let (hi, lo) = BigDigit::from_uint(
                     (*ai as uint) * (n as uint) + (carry as uint)
                 );
@@ -625,7 +625,7 @@ fn shl_bits(&self, n_bits: uint) -> BigUint {
         if n_bits == 0 || self.is_zero() { return (*self).clone(); }
 
         let mut carry = 0;
-        let mut shifted = do self.data.iter().transform |elem| {
+        let mut shifted = do self.data.iter().map |elem| {
             let (hi, lo) = BigDigit::from_uint(
                 (*elem as uint) << n_bits | (carry as uint)
             );
index 4069c68e71c11decd173bdc1def1a4a745daa9b4..71dddc481ae37d3e3d205536d754d6020e59659a 100644 (file)
@@ -77,7 +77,7 @@ fn map_slices<A:Clone + Send,B:Clone + Send>(
         info!("num_tasks: %?", (num_tasks, futures.len()));
         assert_eq!(num_tasks, futures.len());
 
-        do futures.consume_iter().transform |ys| {
+        do futures.move_iter().map |ys| {
             let mut ys = ys;
             ys.get()
         }.collect()
@@ -90,7 +90,7 @@ pub fn map<A:Clone + Send,B:Clone + Send>(
     vec::concat(map_slices(xs, || {
         let f = fn_factory();
         let result: ~fn(uint, &[A]) -> ~[B] =
-            |_, slice| slice.iter().transform(|x| f(x)).collect();
+            |_, slice| slice.iter().map(|x| f(x)).collect();
         result
     }))
 }
@@ -102,7 +102,7 @@ pub fn mapi<A:Clone + Send,B:Clone + Send>(
     let slices = map_slices(xs, || {
         let f = fn_factory();
         let result: ~fn(uint, &[A]) -> ~[B] = |base, slice| {
-            slice.iter().enumerate().transform(|(i, x)| {
+            slice.iter().enumerate().map(|(i, x)| {
                 f(i + base, x)
             }).collect()
         };
index 696ecc881b7230c551d7b889489fdbcbe7d71e52..4b94219b30d537237406faad9799e06da2cfefdd 100644 (file)
@@ -367,7 +367,7 @@ fn test_empty_maybe_top() {
     fn test_from_iter() {
         let xs = ~[9u, 8, 7, 6, 5, 4, 3, 2, 1];
 
-        let mut q: PriorityQueue<uint> = xs.rev_iter().transform(|&x| x).collect();
+        let mut q: PriorityQueue<uint> = xs.rev_iter().map(|&x| x).collect();
 
         for &x in xs.iter() {
             assert_eq!(q.pop(), x);
index da8089250b34587a24cd3191031c87c286b40f1d..bb9ac74bc77ac3d51563e2a6b73ec8b32859e65a 100644 (file)
@@ -692,11 +692,11 @@ fn test_mut_rev_iter() {
     fn test_from_iterator() {
         use std::iterator;
         let v = ~[1,2,3,4,5,6,7];
-        let deq: RingBuf<int> = v.iter().transform(|&x| x).collect();
-        let u: ~[int] = deq.iter().transform(|&x| x).collect();
+        let deq: RingBuf<int> = v.iter().map(|&x| x).collect();
+        let u: ~[int] = deq.iter().map(|&x| x).collect();
         assert_eq!(u, v);
 
-        let mut seq = iterator::count(0u, 2).take_(256);
+        let mut seq = iterator::count(0u, 2).take(256);
         let deq: RingBuf<uint> = seq.collect();
         for (i, &x) in deq.iter().enumerate() {
             assert_eq!(2*i, x);
index 8aff8d388877f367e8e042cd4b23518b8b97c83b..9106d4cd684d916f5c6d58bcbb83dd87962cce90 100644 (file)
@@ -11,7 +11,7 @@
 // FIXME #3921. This is unsafe because linenoise uses global mutable
 // state without mutexes.
 
-
+use std::c_str::ToCStr;
 use std::libc::{c_char, c_int};
 use std::local_data;
 use std::str;
@@ -32,7 +32,7 @@ pub mod rustrt {
 
 /// Add a line to history
 pub unsafe fn add_history(line: &str) -> bool {
-    do line.as_c_str |buf| {
+    do line.to_c_str().with_ref |buf| {
         rustrt::linenoiseHistoryAdd(buf) == 1 as c_int
     }
 }
@@ -44,21 +44,21 @@ pub unsafe fn set_history_max_len(len: int) -> bool {
 
 /// Save line history to a file
 pub unsafe fn save_history(file: &str) -> bool {
-    do file.as_c_str |buf| {
+    do file.to_c_str().with_ref |buf| {
         rustrt::linenoiseHistorySave(buf) == 1 as c_int
     }
 }
 
 /// Load line history from a file
 pub unsafe fn load_history(file: &str) -> bool {
-    do file.as_c_str |buf| {
+    do file.to_c_str().with_ref |buf| {
         rustrt::linenoiseHistoryLoad(buf) == 1 as c_int
     }
 }
 
 /// Print out a prompt and then wait for input and return it
 pub unsafe fn read(prompt: &str) -> Option<~str> {
-    do prompt.as_c_str |buf| {
+    do prompt.to_c_str().with_ref |buf| {
         let line = rustrt::linenoise(buf);
 
         if line.is_null() { None }
@@ -80,7 +80,7 @@ pub unsafe fn complete(cb: CompletionCb) {
 
             unsafe {
                 do cb(str::raw::from_c_str(line)) |suggestion| {
-                    do suggestion.as_c_str |buf| {
+                    do suggestion.to_c_str().with_ref |buf| {
                         rustrt::linenoiseAddCompletion(completions, buf);
                     }
                 }
index a601270e8ece16c80c27031c966ed22b69578daa..ac07fd2bebfbb1c1443c25863c6d5c583c64756d 100644 (file)
@@ -15,7 +15,7 @@
 
 #[allow(missing_doc)];
 
-use std::iterator::{Iterator, IteratorUtil, Enumerate, FilterMap, Invert};
+use std::iterator::{Iterator, Enumerate, FilterMap, Invert};
 use std::util::replace;
 use std::vec::{VecIterator, VecMutIterator};
 use std::vec;
@@ -152,12 +152,12 @@ pub fn mut_rev_iter<'r>(&'r mut self) -> SmallIntMapMutRevIterator <'r, V> {
     }
 
     /// Empties the hash map, moving all values into the specified closure
-    pub fn consume(&mut self)
+    pub fn move_iter(&mut self)
         -> FilterMap<(uint, Option<V>), (uint, V),
-                Enumerate<vec::ConsumeIterator<Option<V>>>>
+                Enumerate<vec::MoveIterator<Option<V>>>>
     {
         let values = replace(&mut self.v, ~[]);
-        values.consume_iter().enumerate().filter_map(|(i, v)| {
+        values.move_iter().enumerate().filter_map(|(i, v)| {
             v.map_move(|v| (i, v))
         })
     }
@@ -452,11 +452,11 @@ fn test_mut_rev_iterator() {
     }
 
     #[test]
-    fn test_consume() {
+    fn test_move_iter() {
         let mut m = SmallIntMap::new();
         m.insert(1, ~2);
         let mut called = false;
-        for (k, v) in m.consume() {
+        for (k, v) in m.move_iter() {
             assert!(!called);
             called = true;
             assert_eq!(k, 1);
index daafdbc37182d581a8fc82c4c36ab2939f70daa2..c7920e727089059032033c9bb0f0084081d34271 100644 (file)
@@ -893,7 +893,7 @@ fn test_merge_sort_stability() {
         fn ile(x: &(&'static str), y: &(&'static str)) -> bool
         {
             // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
-            // to_ascii_consume and to_str_consume to not do a unnecessary clone.
+            // to_ascii_move and to_str_move to not do a unnecessary clone.
             // (Actually, could just remove the to_str_* call, but needs an deriving(Ord) on
             // Ascii)
             let x = x.to_ascii().to_lower().to_str_ascii();
index 4172c715adb96309701da1228c37f66eb4f492b9..756a5c7da006594a0efcec42dcdaf2ffe83c21e0 100644 (file)
@@ -19,6 +19,7 @@
 use std::borrow;
 use std::comm;
 use std::comm::SendDeferred;
+use std::comm::{GenericPort, Peekable};
 use std::task;
 use std::unstable::sync::{Exclusive, UnsafeAtomicRcBox};
 use std::unstable::atomics;
@@ -71,6 +72,12 @@ fn broadcast(&self) -> uint {
         }
         count
     }
+
+    fn wait_end(&self) -> WaitEnd {
+        let (wait_end, signal_end) = comm::oneshot();
+        self.tail.send_deferred(signal_end);
+        wait_end
+    }
 }
 
 // The building-block used to make semaphores, mutexes, and rwlocks.
@@ -99,19 +106,16 @@ pub fn acquire(&self) {
             do (**self).with |state| {
                 state.count -= 1;
                 if state.count < 0 {
-                    // Create waiter nobe.
-                    let (WaitEnd, SignalEnd) = comm::oneshot();
-                    // Tell outer scope we need to block.
-                    waiter_nobe = Some(WaitEnd);
-                    // Enqueue ourself.
-                    state.waiters.tail.send_deferred(SignalEnd);
+                    // Create waiter nobe, enqueue ourself, and tell
+                    // outer scope we need to block.
+                    waiter_nobe = Some(state.waiters.wait_end());
                 }
             }
             // Uncomment if you wish to test for sem races. Not valgrind-friendly.
             /* do 1000.times { task::yield(); } */
             // Need to wait outside the exclusive.
             if waiter_nobe.is_some() {
-                let _ = comm::recv_one(waiter_nobe.unwrap());
+                let _ = waiter_nobe.unwrap().recv();
             }
         }
     }
@@ -200,10 +204,7 @@ pub fn wait(&self) { self.wait_on(0) }
      * wait() is equivalent to wait_on(0).
      */
     pub fn wait_on(&self, condvar_id: uint) {
-        // Create waiter nobe.
-        let (WaitEnd, SignalEnd) = comm::oneshot();
-        let mut WaitEnd   = Some(WaitEnd);
-        let mut SignalEnd = Some(SignalEnd);
+        let mut WaitEnd = None;
         let mut out_of_bounds = None;
         do task::unkillable {
             // Release lock, 'atomically' enqueuing ourselves in so doing.
@@ -215,9 +216,9 @@ pub fn wait_on(&self, condvar_id: uint) {
                         if state.count <= 0 {
                             state.waiters.signal();
                         }
-                        // Enqueue ourself to be woken up by a signaller.
-                        let SignalEnd = SignalEnd.take_unwrap();
-                        state.blocked[condvar_id].tail.send_deferred(SignalEnd);
+                        // Create waiter nobe, and enqueue ourself to
+                        // be woken up by a signaller.
+                        WaitEnd = Some(state.blocked[condvar_id].wait_end());
                     } else {
                         out_of_bounds = Some(state.blocked.len());
                     }
@@ -235,7 +236,7 @@ pub fn wait_on(&self, condvar_id: uint) {
                 do (|| {
                     unsafe {
                         do task::rekillable {
-                            let _ = comm::recv_one(WaitEnd.take_unwrap());
+                            let _ = WaitEnd.take_unwrap().recv();
                         }
                     }
                 }).finally {
index 17588b93ec41e2036d6968f69a18106d304ae09c..f1bf9e81c7251238224989d37622efa4afe6770f 100644 (file)
@@ -14,7 +14,7 @@
 /// parallelism.
 
 
-use std::comm::Chan;
+use std::comm::{Chan, GenericChan, GenericPort};
 use std::comm;
 use std::task::SchedMode;
 use std::task;
index 0929575ee9e70bc1eb089e56b0d248d0f70f360c..bb59e34f98a123c11a1f3614b9199f8db908d602 100644 (file)
@@ -12,7 +12,6 @@
 
 use std::{char, vec, util};
 use std::num::strconv::{SignNone,SignNeg,SignAll,int_to_str_bytes_common};
-use std::iterator::IteratorUtil;
 
 #[deriving(Eq)]
 enum States {
@@ -106,7 +105,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
         *dst = (*src).clone();
     }
 
-    for c in cap.iter().transform(|&x| x) {
+    for c in cap.iter().map(|&x| x) {
         let cur = c as char;
         let mut old_state = state;
         match state {
@@ -476,6 +475,7 @@ fn to_char(self) -> char {
     }
 }
 
+#[cfg(stage0)]
 fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
     let mut s = match val {
         Number(d) => {
@@ -545,8 +545,103 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
         String(s) => {
             match op {
                 FormatString => {
-                    let mut s = s.to_bytes_with_null();
-                    s.pop(); // remove the null
+                    let mut s = s.as_bytes().to_owned();
+                    if flags.precision > 0 && flags.precision < s.len() {
+                        s.truncate(flags.precision);
+                    }
+                    s
+                }
+                _ => {
+                    return Err(fmt!("non-string on stack with %%%c", op.to_char()))
+                }
+            }
+        }
+    };
+    if flags.width > s.len() {
+        let n = flags.width - s.len();
+        if flags.left {
+            s.grow(n, &(' ' as u8));
+        } else {
+            let mut s_ = vec::with_capacity(flags.width);
+            s_.grow(n, &(' ' as u8));
+            s_.push_all_move(s);
+            s = s_;
+        }
+    }
+    Ok(s)
+}
+
+#[cfg(not(stage0))]
+fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
+    let mut s = match val {
+        Number(d) => {
+            match op {
+                FormatString => {
+                    return Err(~"non-number on stack with %s")
+                }
+                _ => {
+                    let radix = match op {
+                        FormatDigit => 10,
+                        FormatOctal => 8,
+                        FormatHex|FormatHEX => 16,
+                        FormatString => util::unreachable()
+                    };
+                    let mut s = ~[];
+                    match op {
+                        FormatDigit => {
+                            let sign = if flags.sign { SignAll } else { SignNeg };
+                            do int_to_str_bytes_common(d, radix, sign) |c| {
+                                s.push(c);
+                            }
+                        }
+                        _ => {
+                            do int_to_str_bytes_common(d as uint, radix, SignNone) |c| {
+                                s.push(c);
+                            }
+                        }
+                    };
+                    if flags.precision > s.len() {
+                        let mut s_ = vec::with_capacity(flags.precision);
+                        let n = flags.precision - s.len();
+                        s_.grow(n, &('0' as u8));
+                        s_.push_all_move(s);
+                        s = s_;
+                    }
+                    assert!(!s.is_empty(), "string conversion produced empty result");
+                    match op {
+                        FormatDigit => {
+                            if flags.space && !(s[0] == '-' as u8 || s[0] == '+' as u8) {
+                                s.unshift(' ' as u8);
+                            }
+                        }
+                        FormatOctal => {
+                            if flags.alternate && s[0] != '0' as u8 {
+                                s.unshift('0' as u8);
+                            }
+                        }
+                        FormatHex => {
+                            if flags.alternate {
+                                let s_ = util::replace(&mut s, ~['0' as u8, 'x' as u8]);
+                                s.push_all_move(s_);
+                            }
+                        }
+                        FormatHEX => {
+                            s = s.into_ascii().to_upper().into_bytes();
+                            if flags.alternate {
+                                let s_ = util::replace(&mut s, ~['0' as u8, 'X' as u8]);
+                                s.push_all_move(s_);
+                            }
+                        }
+                        FormatString => util::unreachable()
+                    }
+                    s
+                }
+            }
+        }
+        String(s) => {
+            match op {
+                FormatString => {
+                    let mut s = s.as_bytes().to_owned();
                     if flags.precision > 0 && flags.precision < s.len() {
                         s.truncate(flags.precision);
                     }
index 426cacb62faad0eaf7731c39a3df36beb2cad8a5..0d2badff4929bc185f5b722b3149d782a741a915 100644 (file)
@@ -214,7 +214,7 @@ pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> {
     }
 
     let names_str = str::from_bytes(file.read_bytes(names_bytes as uint - 1)); // don't read NUL
-    let term_names: ~[~str] = names_str.split_iter('|').transform(|s| s.to_owned()).collect();
+    let term_names: ~[~str] = names_str.split_iter('|').map(|s| s.to_owned()).collect();
 
     file.read_byte(); // consume NUL
 
index 761cb1bd76f929198e5011cd8595f3840fe30996..8b7332ff545a4868c9f62a1942dffe0cb4fc3c7e 100644 (file)
@@ -29,7 +29,7 @@
 use treemap::TreeMap;
 
 use std::clone::Clone;
-use std::comm::{stream, SharedChan};
+use std::comm::{stream, SharedChan, GenericPort, GenericChan};
 use std::libc;
 use std::either;
 use std::io;
@@ -525,12 +525,11 @@ pub fn write_run_finish(&self,
 }
 
 pub fn fmt_metrics(mm: &MetricMap) -> ~str {
-    use std::iterator::IteratorUtil;
     let v : ~[~str] = mm.iter()
-        .transform(|(k,v)| fmt!("%s: %f (+/- %f)",
-                                *k,
-                                v.value as float,
-                                v.noise as float))
+        .map(|(k,v)| fmt!("%s: %f (+/- %f)",
+                          *k,
+                          v.value as float,
+                          v.noise as float))
         .collect();
     v.connect(", ")
 }
@@ -698,7 +697,7 @@ fn run_tests(opts: &TestOpts,
 
     // All benchmarks run at the end, in serial.
     // (this includes metric fns)
-    for b in filtered_benchs_and_metrics.consume_iter() {
+    for b in filtered_benchs_and_metrics.move_iter() {
         callback(TeWait(b.desc.clone()));
         run_test(!opts.run_benchmarks, b, ch.clone());
         let (test, result) = p.recv();
@@ -744,7 +743,7 @@ fn filter_fn(test: TestDescAndFn, filter_str: &str) ->
             }
         }
 
-        filtered.consume_iter().filter_map(|x| filter_fn(x, filter_str)).collect()
+        filtered.move_iter().filter_map(|x| filter_fn(x, filter_str)).collect()
     };
 
     // Maybe pull out the ignored test and unignore them
@@ -762,7 +761,7 @@ fn filter(test: TestDescAndFn) -> Option<TestDescAndFn> {
                 None
             }
         };
-        filtered.consume_iter().filter_map(|x| filter(x)).collect()
+        filtered.move_iter().filter_map(|x| filter(x)).collect()
     };
 
     // Sort the tests alphabetically
index f6a5fd98234b58aabab5898bdc13b9137c500ee3..f79e01b6f28b296d031de972c042cb7a6a655035 100644 (file)
@@ -57,9 +57,6 @@ fn lt(&self, other: &Timespec) -> bool {
         self.sec < other.sec ||
             (self.sec == other.sec && self.nsec < other.nsec)
     }
-    fn le(&self, other: &Timespec) -> bool { !other.lt(self) }
-    fn ge(&self, other: &Timespec) -> bool { !self.lt(other) }
-    fn gt(&self, other: &Timespec) -> bool { !self.le(other) }
 }
 
 /**
@@ -287,10 +284,14 @@ fn match_strs(ss: &str, pos: uint, strs: &[(~str, i32)])
     fn match_digits(ss: &str, pos: uint, digits: uint, ws: bool)
       -> Option<(i32, uint)> {
         let mut pos = pos;
+        let len = ss.len();
         let mut value = 0_i32;
 
         let mut i = 0u;
         while i < digits {
+            if pos >= len {
+                return None;
+            }
             let range = ss.char_range_at(pos);
             pos = range.next;
 
@@ -856,7 +857,7 @@ fn parse_type(ch: char, tm: &Tm) -> ~str {
 
 #[cfg(test)]
 mod tests {
-    use time::*;
+    use super::*;
 
     use std::float;
     use std::os;
@@ -904,7 +905,7 @@ fn test_at_utc() {
         os::setenv("TZ", "America/Los_Angeles");
         tzset();
 
-        let time = ::time::Timespec::new(1234567890, 54321);
+        let time = Timespec::new(1234567890, 54321);
         let utc = at_utc(time);
 
         assert!(utc.tm_sec == 30_i32);
@@ -925,7 +926,7 @@ fn test_at() {
         os::setenv("TZ", "America/Los_Angeles");
         tzset();
 
-        let time = ::time::Timespec::new(1234567890, 54321);
+        let time = Timespec::new(1234567890, 54321);
         let local = at(time);
 
         error!("time_at: %?", local);
@@ -953,7 +954,7 @@ fn test_to_timespec() {
         os::setenv("TZ", "America/Los_Angeles");
         tzset();
 
-        let time = ::time::Timespec::new(1234567890, 54321);
+        let time = Timespec::new(1234567890, 54321);
         let utc = at_utc(time);
 
         assert_eq!(utc.to_timespec(), time);
@@ -964,7 +965,7 @@ fn test_conversions() {
         os::setenv("TZ", "America/Los_Angeles");
         tzset();
 
-        let time = ::time::Timespec::new(1234567890, 54321);
+        let time = Timespec::new(1234567890, 54321);
         let utc = at_utc(time);
         let local = at(time);
 
@@ -1145,7 +1146,7 @@ fn test_ctime() {
         os::setenv("TZ", "America/Los_Angeles");
         tzset();
 
-        let time = ::time::Timespec::new(1234567890, 54321);
+        let time = Timespec::new(1234567890, 54321);
         let utc   = at_utc(time);
         let local = at(time);
 
@@ -1159,7 +1160,7 @@ fn test_strftime() {
         os::setenv("TZ", "America/Los_Angeles");
         tzset();
 
-        let time = ::time::Timespec::new(1234567890, 54321);
+        let time = Timespec::new(1234567890, 54321);
         let utc = at_utc(time);
         let local = at(time);
 
index 4d898dfb2b4f082d6d8be4cee9562785b3e5db72..424492a3cfea4d258524d386ddfb9f63f9f9c71e 100644 (file)
@@ -213,13 +213,13 @@ pub fn upper_bound_iter<'a>(&'a self, k: &K) -> TreeMapIterator<'a, K, V> {
     }
 
     /// Get a lazy iterator that consumes the treemap.
-    pub fn consume_iter(self) -> TreeMapConsumeIterator<K, V> {
+    pub fn move_iter(self) -> TreeMapMoveIterator<K, V> {
         let TreeMap { root: root, length: length } = self;
         let stk = match root {
             None => ~[],
             Some(~tn) => ~[tn]
         };
-        TreeMapConsumeIterator {
+        TreeMapMoveIterator {
             stack: stk,
             remaining: length
         }
@@ -331,12 +331,12 @@ fn iter_traverse_complete<'a, K, V>(it: &mut TreeMapIterator<'a, K, V>) {
 }
 
 /// Lazy forward iterator over a map that consumes the map while iterating
-pub struct TreeMapConsumeIterator<K, V> {
+pub struct TreeMapMoveIterator<K, V> {
     priv stack: ~[TreeNode<K, V>],
     priv remaining: uint
 }
 
-impl<K, V> Iterator<(K, V)> for TreeMapConsumeIterator<K,V> {
+impl<K, V> Iterator<(K, V)> for TreeMapMoveIterator<K,V> {
     #[inline]
     fn next(&mut self) -> Option<(K, V)> {
         while !self.stack.is_empty() {
@@ -1259,7 +1259,7 @@ fn test_lazy_iterator() {
     fn test_from_iter() {
         let xs = ~[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
 
-        let map: TreeMap<int, int> = xs.iter().transform(|&x| x).collect();
+        let map: TreeMap<int, int> = xs.iter().map(|&x| x).collect();
 
         for &(k, v) in xs.iter() {
             assert_eq!(map.find(&k), Some(&v));
@@ -1558,7 +1558,7 @@ fn test_pop() {
     fn test_from_iter() {
         let xs = ~[1, 2, 3, 4, 5, 6, 7, 8, 9];
 
-        let set: TreeSet<int> = xs.iter().transform(|&x| x).collect();
+        let set: TreeSet<int> = xs.iter().map(|&x| x).collect();
 
         for x in xs.iter() {
             assert!(set.contains(x));
index b4ba8acae476974cff76b27e2945718900e12350..61af5cd783929b241e481b8ee978c0248eb8b34a 100644 (file)
@@ -18,7 +18,7 @@
 use treemap::TreeMap;
 
 use std::cell::Cell;
-use std::comm::{PortOne, oneshot, send_one, recv_one};
+use std::comm::{PortOne, oneshot};
 use std::either::{Either, Left, Right};
 use std::io;
 use std::run;
@@ -331,7 +331,7 @@ fn exec_work<T:Send +
                     };
                     let chan = chan.take();
                     let v = blk(&exe);
-                    send_one(chan, (exe, v));
+                    chan.send((exe, v));
                 }
                 Right(port)
             }
@@ -355,7 +355,7 @@ pub fn unwrap(self) -> T {
             None => fail!(),
             Some(Left(v)) => v,
             Some(Right(port)) => {
-                let (exe, v) = recv_one(port);
+                let (exe, v) = port.recv();
                 let s = json_encode(&v);
                 do prep.ctxt.db.write |db| {
                     db.cache(prep.fn_name,
index 010486cdf855c7747df7c33c46362d3b1cd69f95..b8f81a44759cecfaf4bd90fc8b979e8f84c8f79e 100644 (file)
@@ -128,7 +128,7 @@ fn rustc_help() {
 }
 
 fn find_cmd(command_string: &str) -> Option<Command> {
-    do COMMANDS.iter().find_ |command| {
+    do COMMANDS.iter().find |command| {
         command.cmd == command_string
     }.map_move(|x| *x)
 }
index 637ea159d79d012880d7ffe1e527a2616810cd19..5da769a60d75cd167b31999d2add104565391352 100644 (file)
 use lib::llvm::ModuleRef;
 use lib;
 use metadata::common::LinkMeta;
-use metadata::{encoder, csearch, cstore};
+use metadata::{encoder, csearch, cstore, filesearch};
 use middle::trans::context::CrateContext;
 use middle::trans::common::gensym_name;
 use middle::ty;
 use util::ppaux;
 
+use std::c_str::ToCStr;
 use std::char;
 use std::hash::Streaming;
 use std::hash;
@@ -76,9 +77,9 @@ pub fn WriteOutputFile(sess: Session,
         OptLevel: c_int,
         EnableSegmentedStacks: bool) {
     unsafe {
-        do Triple.as_c_str |Triple| {
-            do Feature.as_c_str |Feature| {
-                do Output.as_c_str |Output| {
+        do Triple.to_c_str().with_ref |Triple| {
+            do Feature.to_c_str().with_ref |Feature| {
+                do Output.to_c_str().with_ref |Output| {
                     let result = llvm::LLVMRustWriteOutputFile(
                             PM,
                             M,
@@ -105,6 +106,7 @@ pub mod jit {
     use lib::llvm::{ModuleRef, ContextRef, ExecutionEngineRef};
     use metadata::cstore;
 
+    use std::c_str::ToCStr;
     use std::cast;
     use std::local_data;
     use std::unstable::intrinsics;
@@ -146,7 +148,7 @@ pub fn exec(sess: Session,
 
                 debug!("linking: %s", path);
 
-                do path.as_c_str |buf_t| {
+                do path.to_c_str().with_ref |buf_t| {
                     if !llvm::LLVMRustLoadCrate(manager, buf_t) {
                         llvm_err(sess, ~"Could not link");
                     }
@@ -165,7 +167,7 @@ pub fn exec(sess: Session,
             // Next, we need to get a handle on the _rust_main function by
             // looking up it's corresponding ValueRef and then requesting that
             // the execution engine compiles the function.
-            let fun = do "_rust_main".as_c_str |entry| {
+            let fun = do "_rust_main".to_c_str().with_ref |entry| {
                 llvm::LLVMGetNamedFunction(m, entry)
             };
             if fun.is_null() {
@@ -230,6 +232,7 @@ pub mod write {
 
     use back::passes;
 
+    use std::c_str::ToCStr;
     use std::libc::{c_int, c_uint};
     use std::path::Path;
     use std::run;
@@ -263,14 +266,14 @@ pub fn run_passes(sess: Session,
                   output_type_bitcode => {
                     if opts.optimize != session::No {
                         let filename = output.with_filetype("no-opt.bc");
-                        do filename.to_str().as_c_str |buf| {
+                        do filename.to_c_str().with_ref |buf| {
                             llvm::LLVMWriteBitcodeToFile(llmod, buf);
                         }
                     }
                   }
                   _ => {
                     let filename = output.with_filetype("bc");
-                    do filename.to_str().as_c_str |buf| {
+                    do filename.to_c_str().with_ref |buf| {
                         llvm::LLVMWriteBitcodeToFile(llmod, buf);
                     }
                   }
@@ -333,7 +336,7 @@ pub fn run_passes(sess: Session,
                     // Always output the bitcode file with --save-temps
 
                     let filename = output.with_filetype("opt.bc");
-                    do filename.to_str().as_c_str |buf| {
+                    do filename.to_c_str().with_ref |buf| {
                         llvm::LLVMWriteBitcodeToFile(llmod, buf)
                     };
                     // Save the assembly file if -S is used
@@ -391,13 +394,13 @@ pub fn run_passes(sess: Session,
 
             if output_type == output_type_llvm_assembly {
                 // Given options "-S --emit-llvm": output LLVM assembly
-                do output.to_str().as_c_str |buf_o| {
+                do output.to_c_str().with_ref |buf_o| {
                     llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o);
                 }
             } else {
                 // If only a bitcode file is asked for by using the
                 // '--emit-llvm' flag, then output it here
-                do output.to_str().as_c_str |buf| {
+                do output.to_c_str().with_ref |buf| {
                     llvm::LLVMWriteBitcodeToFile(llmod, buf);
                 }
             }
@@ -497,6 +500,7 @@ pub fn build_link_meta(sess: Session,
     struct ProvidedMetas {
         name: Option<@str>,
         vers: Option<@str>,
+        pkg_id: Option<@str>,
         cmh_items: ~[@ast::MetaItem]
     }
 
@@ -504,6 +508,7 @@ fn provided_link_metas(sess: Session, c: &ast::Crate) ->
        ProvidedMetas {
         let mut name = None;
         let mut vers = None;
+        let mut pkg_id = None;
         let mut cmh_items = ~[];
         let linkage_metas = attr::find_linkage_metas(c.attrs);
         attr::require_unique_names(sess.diagnostic(), linkage_metas);
@@ -511,6 +516,7 @@ fn provided_link_metas(sess: Session, c: &ast::Crate) ->
             match meta.name_str_pair() {
                 Some((n, value)) if "name" == n => name = Some(value),
                 Some((n, value)) if "vers" == n => vers = Some(value),
+                Some((n, value)) if "package_id" == n => pkg_id = Some(value),
                 _ => cmh_items.push(*meta)
             }
         }
@@ -518,6 +524,7 @@ fn provided_link_metas(sess: Session, c: &ast::Crate) ->
         ProvidedMetas {
             name: name,
             vers: vers,
+            pkg_id: pkg_id,
             cmh_items: cmh_items
         }
     }
@@ -525,7 +532,8 @@ fn provided_link_metas(sess: Session, c: &ast::Crate) ->
     // This calculates CMH as defined above
     fn crate_meta_extras_hash(symbol_hasher: &mut hash::State,
                               cmh_items: ~[@ast::MetaItem],
-                              dep_hashes: ~[@str]) -> @str {
+                              dep_hashes: ~[@str],
+                              pkg_id: Option<@str>) -> @str {
         fn len_and_str(s: &str) -> ~str {
             fmt!("%u_%s", s.len(), s)
         }
@@ -563,7 +571,10 @@ fn hash(symbol_hasher: &mut hash::State, m: &@ast::MetaItem) {
             write_string(symbol_hasher, len_and_str(*dh));
         }
 
-    // tjc: allocation is unfortunate; need to change std::hash
+        for p in pkg_id.iter() {
+            write_string(symbol_hasher, len_and_str(*p));
+        }
+
         return truncated_hash_result(symbol_hasher).to_managed();
     }
 
@@ -605,6 +616,7 @@ fn crate_meta_vers(sess: Session, opt_vers: Option<@str>) -> @str {
     let ProvidedMetas {
         name: opt_name,
         vers: opt_vers,
+        pkg_id: opt_pkg_id,
         cmh_items: cmh_items
     } = provided_link_metas(sess, c);
     let name = crate_meta_name(sess, output, opt_name);
@@ -612,11 +624,12 @@ fn crate_meta_vers(sess: Session, opt_vers: Option<@str>) -> @str {
     let dep_hashes = cstore::get_dep_hashes(sess.cstore);
     let extras_hash =
         crate_meta_extras_hash(symbol_hasher, cmh_items,
-                               dep_hashes);
+                               dep_hashes, opt_pkg_id);
 
     LinkMeta {
         name: name,
         vers: vers,
+        package_id: opt_pkg_id,
         extras_hash: extras_hash
     }
 }
@@ -922,7 +935,7 @@ fn unlib(config: @session::config, stem: ~str) -> ~str {
     // Add all the link args for external crates.
     do cstore::iter_crate_data(cstore) |crate_num, _| {
         let link_args = csearch::get_link_args_for_crate(cstore, crate_num);
-        for link_arg in link_args.consume_iter() {
+        for link_arg in link_args.move_iter() {
             args.push(link_arg);
         }
     }
@@ -939,6 +952,11 @@ fn unlib(config: @session::config, stem: ~str) -> ~str {
         args.push(~"-L" + path.to_str());
     }
 
+    let rustpath = filesearch::rust_path();
+    for path in rustpath.iter() {
+        args.push(~"-L" + path.to_str());
+    }
+
     // The names of the extern libraries
     let used_libs = cstore::get_used_libraries(cstore);
     for l in used_libs.iter() { args.push(~"-l" + *l); }
index 35d070baa9bace971854c8a4c18faf73b79f0b86..854d11fd3503599e030e2d33d8f8a9dbd36ceb21 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::c_str::ToCStr;
 use std::io;
 
 use driver::session::{OptLevel, No, Less, Aggressive};
@@ -172,7 +173,7 @@ pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~s
 }
 
 pub fn create_pass(name:&str) -> Option<PassRef> {
-    do name.as_c_str |s| {
+    do name.to_c_str().with_ref |s| {
         unsafe {
             let p = llvm::LLVMCreatePass(s);
             if p.is_null() {
index 571721ed40cee8357f94c34c9f8810263e2fcd73..e7706815ff537da1752edf18df269cb682097a4d 100644 (file)
 use metadata::filesearch;
 
 use std::hashmap::HashSet;
-use std::num;
-use std::os;
-use std::util;
-use std::vec;
+use std::{os, util, vec};
 
 fn not_win32(os: session::os) -> bool {
   os != session::os_win32
@@ -52,7 +49,7 @@ fn get_sysroot_absolute_rt_lib(sess: session::Session) -> Path {
 }
 
 pub fn rpaths_to_flags(rpaths: &[Path]) -> ~[~str] {
-    rpaths.iter().transform(|rpath| fmt!("-Wl,-rpath,%s",rpath.to_str())).collect()
+    rpaths.iter().map(|rpath| fmt!("-Wl,-rpath,%s",rpath.to_str())).collect()
 }
 
 fn get_rpaths(os: session::os,
@@ -103,7 +100,7 @@ fn log_rpaths(desc: &str, rpaths: &[Path]) {
 fn get_rpaths_relative_to_output(os: session::os,
                                  output: &Path,
                                  libs: &[Path]) -> ~[Path] {
-    libs.iter().transform(|a| get_rpath_relative_to_output(os, output, a)).collect()
+    libs.iter().map(|a| get_rpath_relative_to_output(os, output, a)).collect()
 }
 
 pub fn get_rpath_relative_to_output(os: session::os,
@@ -122,52 +119,18 @@ pub fn get_rpath_relative_to_output(os: session::os,
         session::os_win32 => util::unreachable()
     };
 
-    Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output),
-                                           &os::make_absolute(lib)))
-}
-
-// Find the relative path from one file to another
-pub fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
-    assert!(abs1.is_absolute);
-    assert!(abs2.is_absolute);
-    let abs1 = abs1.normalize();
-    let abs2 = abs2.normalize();
-    debug!("finding relative path from %s to %s",
-           abs1.to_str(), abs2.to_str());
-    let split1: &[~str] = abs1.components;
-    let split2: &[~str] = abs2.components;
-    let len1 = split1.len();
-    let len2 = split2.len();
-    assert!(len1 > 0);
-    assert!(len2 > 0);
-
-    let max_common_path = num::min(len1, len2) - 1;
-    let mut start_idx = 0;
-    while start_idx < max_common_path
-        && split1[start_idx] == split2[start_idx] {
-        start_idx += 1;
-    }
-
-    let mut path = ~[];
-    for _ in range(start_idx, len1 - 1) { path.push(~".."); };
-
-    path.push_all(split2.slice(start_idx, len2 - 1));
-
-    return if !path.is_empty() {
-        Path("").push_many(path)
-    } else {
-        Path(".")
-    }
+    Path(prefix).push_rel(&os::make_absolute(output).get_relative_to(&os::make_absolute(lib)))
 }
 
 fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] {
-    libs.iter().transform(|a| get_absolute_rpath(a)).collect()
+    libs.iter().map(|a| get_absolute_rpath(a)).collect()
 }
 
 pub fn get_absolute_rpath(lib: &Path) -> Path {
     os::make_absolute(lib).dir_path()
 }
 
+#[cfg(stage0)]
 pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
     let install_prefix = env!("CFG_PREFIX");
 
@@ -179,6 +142,14 @@ pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
     os::make_absolute(&Path(install_prefix).push_rel(&tlib))
 }
 
+#[cfg(not(stage0))]
+pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
+    let install_prefix = env!("CFG_PREFIX");
+
+    let tlib = filesearch::relative_target_lib_path(target_triple);
+    os::make_absolute(&Path(install_prefix).push_rel(&tlib))
+}
+
 pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
     let mut set = HashSet::new();
     let mut minimized = ~[];
@@ -199,8 +170,7 @@ mod test {
     #[cfg(test)]
     #[cfg(test)]
     use back::rpath::{get_absolute_rpath, get_install_prefix_rpath};
-    use back::rpath::{get_relative_to, get_rpath_relative_to_output};
-    use back::rpath::{minimize_rpaths, rpaths_to_flags};
+    use back::rpath::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output};
     use driver::session;
 
     #[test]
@@ -244,78 +214,9 @@ fn test_minimize2() {
         assert_eq!(res, ~[Path("1a"), Path("2"), Path("4a"), Path("3")]);
     }
 
-    #[test]
-    fn test_relative_to1() {
-        let p1 = Path("/usr/bin/rustc");
-        let p2 = Path("/usr/lib/mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../lib"));
-    }
-
-    #[test]
-    fn test_relative_to2() {
-        let p1 = Path("/usr/bin/rustc");
-        let p2 = Path("/usr/bin/../lib/mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../lib"));
-    }
-
-    #[test]
-    fn test_relative_to3() {
-        let p1 = Path("/usr/bin/whatever/rustc");
-        let p2 = Path("/usr/lib/whatever/mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../../lib/whatever"));
-    }
-
-    #[test]
-    fn test_relative_to4() {
-        let p1 = Path("/usr/bin/whatever/../rustc");
-        let p2 = Path("/usr/lib/whatever/mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../lib/whatever"));
-    }
-
-    #[test]
-    fn test_relative_to5() {
-        let p1 = Path("/usr/bin/whatever/../rustc");
-        let p2 = Path("/usr/lib/whatever/../mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../lib"));
-    }
-
-    #[test]
-    fn test_relative_to6() {
-        let p1 = Path("/1");
-        let p2 = Path("/2/3");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("2"));
-    }
-
-    #[test]
-    fn test_relative_to7() {
-        let p1 = Path("/1/2");
-        let p2 = Path("/3");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path(".."));
-    }
-
-    #[test]
-    fn test_relative_to8() {
-        let p1 = Path("/home/brian/Dev/rust/build/").push_rel(
-            &Path("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
-        let p2 = Path("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
-            &Path("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
-        let res = get_relative_to(&p1, &p2);
-        debug!("test_relative_tu8: %s vs. %s",
-               res.to_str(),
-               Path(".").to_str());
-        assert_eq!(res, Path("."));
-    }
-
     #[test]
     #[cfg(target_os = "linux")]
-    #[cfg(target_os = "andorid")]
+    #[cfg(target_os = "android")]
     fn test_rpath_relative() {
       let o = session::os_linux;
       let res = get_rpath_relative_to_output(o,
@@ -335,7 +236,6 @@ fn test_rpath_relative() {
     #[test]
     #[cfg(target_os = "macos")]
     fn test_rpath_relative() {
-        // this is why refinements would be nice
         let o = session::os_macos;
         let res = get_rpath_relative_to_output(o,
                                                &Path("bin/rustc"),
index 61ab826e9ee51f5728c25c15edbdaca8d89c355c..fdf887574695fb40663b29bf05b1747391726b00 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.
 //
@@ -120,7 +120,7 @@ pub fn build_configuration(sess: Session, argv0: @str, input: &input) ->
 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
 fn parse_cfgspecs(cfgspecs: ~[~str],
                   demitter: diagnostic::Emitter) -> ast::CrateConfig {
-    do cfgspecs.consume_iter().transform |s| {
+    do cfgspecs.move_iter().map |s| {
         let sess = parse::new_parse_sess(Some(demitter));
         parse::parse_meta_from_source_str(@"cfgspec", s.to_managed(), ~[], sess)
     }.collect::<ast::CrateConfig>()
@@ -578,6 +578,7 @@ pub fn build_target_config(sopts: @session::options,
     return target_cfg;
 }
 
+#[cfg(stage0)]
 pub fn host_triple() -> ~str {
     // Get the host triple out of the build environment. This ensures that our
     // idea of the host triple is the same as for the set of libraries we've
@@ -595,6 +596,19 @@ pub fn host_triple() -> ~str {
         };
 }
 
+#[cfg(not(stage0))]
+pub fn host_triple() -> ~str {
+    // Get the host triple out of the build environment. This ensures that our
+    // idea of the host triple is the same as for the set of libraries we've
+    // actually built.  We can't just take LLVM's host triple because they
+    // normalize all ix86 architectures to i386.
+    //
+    // Instead of grabbing the host triple (for the current host), we grab (at
+    // compile time) the target triple that this rustc is built with and
+    // calling that (at runtime) the host triple.
+    (env!("CFG_COMPILER_TRIPLE")).to_owned()
+}
+
 pub fn build_session_options(binary: @str,
                              matches: &getopts::Matches,
                              demitter: diagnostic::Emitter)
@@ -617,7 +631,7 @@ pub fn build_session_options(binary: @str,
         let level_name = lint::level_to_str(*level);
 
         // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
-        // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+        // to_ascii_move and to_str_move to not do a unnecessary copy.
         let level_short = level_name.slice_chars(0, 1);
         let level_short = level_short.to_ascii().to_upper().to_str_ascii();
         let flags = vec::append(getopts::opt_strs(matches, level_short),
@@ -712,7 +726,7 @@ pub fn build_session_options(binary: @str,
     let addl_lib_search_paths = getopts::opt_strs(matches, "L").map(|s| Path(*s));
     let linker = getopts::opt_maybe_str(matches, "linker");
     let linker_args = getopts::opt_strs(matches, "link-args").flat_map( |a| {
-        a.split_iter(' ').transform(|arg| arg.to_owned()).collect()
+        a.split_iter(' ').map(|arg| arg.to_owned()).collect()
     });
 
     let cfg = parse_cfgspecs(getopts::opt_strs(matches, "cfg"), demitter);
@@ -723,7 +737,7 @@ pub fn build_session_options(binary: @str,
     let custom_passes = match getopts::opt_maybe_str(matches, "passes") {
         None => ~[],
         Some(s) => {
-            s.split_iter(|c: char| c == ' ' || c == ',').transform(|s| {
+            s.split_iter(|c: char| c == ' ' || c == ',').map(|s| {
                 s.trim().to_owned()
             }).collect()
         }
@@ -821,7 +835,8 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] {
   optmulti("", "cfg", "Configure the compilation
                           environment", "SPEC"),
   optflag("",  "emit-llvm",
-                        "Produce an LLVM bitcode file"),
+                        "Produce an LLVM assembly file if used with -S option;
+                         produce an LLVM bitcode file otherwise"),
   optflag("h", "help","Display this message"),
   optmulti("L", "",   "Add a directory to the library search path",
                               "PATH"),
@@ -931,7 +946,7 @@ pub fn build_output_filenames(input: &input,
           let linkage_metas = attr::find_linkage_metas(attrs);
           if !linkage_metas.is_empty() {
               // But if a linkage meta is present, that overrides
-              let maybe_name = linkage_metas.iter().find_(|m| "name" == m.name());
+              let maybe_name = linkage_metas.iter().find(|m| "name" == m.name());
               match maybe_name.chain(|m| m.value_str()) {
                   Some(s) => stem = s,
                   _ => ()
index d6584846655d2db01bc28f9cbfdabfcc699a7ce8..026532c89c3293689906de508fed2c8b2062c1ac 100644 (file)
@@ -102,12 +102,12 @@ fn fold_item_underscore(cx: @Context, item: &ast::item_,
     let item = match *item {
         ast::item_impl(ref a, ref b, ref c, ref methods) => {
             let methods = methods.iter().filter(|m| method_in_cfg(cx, **m))
-                .transform(|x| *x).collect();
+                .map(|x| *x).collect();
             ast::item_impl((*a).clone(), (*b).clone(), (*c).clone(), methods)
         }
         ast::item_trait(ref a, ref b, ref methods) => {
             let methods = methods.iter().filter(|m| trait_method_in_cfg(cx, *m) )
-                .transform(|x| (*x).clone()).collect();
+                .map(|x| (*x).clone()).collect();
             ast::item_trait((*a).clone(), (*b).clone(), methods)
         }
         ref item => (*item).clone(),
@@ -180,5 +180,5 @@ fn trait_method_in_cfg(cx: @Context, meth: &ast::trait_method) -> bool {
 // Determine if an item should be translated in the current crate
 // configuration based on the item's attributes
 fn in_cfg(cfg: &[@ast::MetaItem], attrs: &[ast::Attribute]) -> bool {
-    attr::test_cfg(cfg, attrs.iter().transform(|x| *x))
+    attr::test_cfg(cfg, attrs.iter().map(|x| *x))
 }
index 3a1129b1dd94e450f3200d06ff4b8b18fac81771..2a61ea28e0c6b3452c6118b4faf403e4db10cbc6 100644 (file)
@@ -47,7 +47,7 @@ fn spanned<T>(x: T) -> codemap::spanned<T> {
             let n1 = sess.next_node_id();
             let vi1 = ast::view_item {
                 node: ast::view_item_extern_mod(
-                        sess.ident_of("std"), ~[], n1),
+                        sess.ident_of("std"), None, ~[], n1),
                 attrs: ~[
                     attr::mk_attr(
                         attr::mk_name_value_item_str(@"vers", STD_VERSION.to_managed()))
index d2d2a8b4be99d984f4c06c04f6b80ef3598a0418..597de440ae1fc0f986bbd48f81f1a182f2b14875 100644 (file)
@@ -126,7 +126,7 @@ fn nomain(cx: @mut TestCtxt, item: @ast::item) -> @ast::item {
 
     let mod_nomain = ast::_mod {
         view_items: m.view_items.clone(),
-        items: m.items.iter().transform(|i| nomain(cx, *i)).collect(),
+        items: m.items.iter().map(|i| nomain(cx, *i)).collect(),
     };
 
     fold::noop_fold_mod(&mod_nomain, fld)
@@ -236,7 +236,7 @@ fn is_ignored(cx: @mut TestCtxt, i: @ast::item) -> bool {
     do i.attrs.iter().any |attr| {
         // check ignore(cfg(foo, bar))
         "ignore" == attr.name() && match attr.meta_item_list() {
-            Some(ref cfgs) => attr::test_cfg(cx.crate.config, cfgs.iter().transform(|x| *x)),
+            Some(ref cfgs) => attr::test_cfg(cx.crate.config, cfgs.iter().map(|x| *x)),
             None => true
         }
     }
@@ -282,7 +282,7 @@ fn mk_std(cx: &TestCtxt) -> ast::view_item {
                                             cx.sess.next_node_id()))])
     } else {
         let mi = attr::mk_name_value_item_str(@"vers", @"0.8-pre");
-        ast::view_item_extern_mod(id_extra, ~[mi], cx.sess.next_node_id())
+        ast::view_item_extern_mod(id_extra, None, ~[mi], cx.sess.next_node_id())
     };
     ast::view_item {
         node: vi,
index 90db3f8edb0a6eec5ba033ecafd0d6d57190262d..5801e43a54cd2ba0bfd7d02757a35909b18ee931 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
+use std::c_str::ToCStr;
 use std::hashmap::HashMap;
 use std::libc::{c_uint, c_ushort};
 use std::option;
@@ -1553,6 +1553,8 @@ pub fn LLVMBuildAtomicRMW(B: BuilderRef,
         /* Selected entries from the downcasts. */
         #[fast_ffi]
         pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
+        #[fast_ffi]
+        pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
 
         /** Writes a module to the specified path. Returns 0 on success. */
         #[fast_ffi]
@@ -2259,7 +2261,7 @@ pub struct TargetData {
 }
 
 pub fn mk_target_data(string_rep: &str) -> TargetData {
-    let lltd = do string_rep.as_c_str |buf| {
+    let lltd = do string_rep.to_c_str().with_ref |buf| {
         unsafe { llvm::LLVMCreateTargetData(buf) }
     };
 
index 1c5d202d4d953644fee972fefc12522dcf4731a6..f2d8b68faa6f3b7a655e5e6637830c5a0bb6e58a 100644 (file)
@@ -185,5 +185,7 @@ pub fn from_uint(value : uint) -> Option<astencode_tag> {
 pub struct LinkMeta {
     name: @str,
     vers: @str,
+    // Optional package ID
+    package_id: Option<@str>, // non-None if this was a URL-like package ID
     extras_hash: @str
 }
index d8f142288243508b1c03c4f08e2ae4f7ba5c4a97..82f5c4f88435a8c4a4c2641d239834870bcddf10 100644 (file)
@@ -18,6 +18,7 @@
 
 use std::hashmap::HashMap;
 use syntax::ast;
+use std::vec;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{span, dummy_sp};
@@ -82,7 +83,7 @@ fn warn_if_multiple_versions(e: @mut Env,
             *crate_cache[crate_cache.len() - 1].metas
         );
 
-        let vec: ~[Either<cache_entry, cache_entry>] = crate_cache.iter().transform(|&entry| {
+        let vec: ~[Either<cache_entry, cache_entry>] = crate_cache.iter().map(|&entry| {
             let othername = loader::crate_name_from_metas(*entry.metas);
             if name == othername {
                 Left(entry)
@@ -137,18 +138,33 @@ fn visit_crate(e: &Env, c: &ast::Crate) {
 
 fn visit_view_item(e: @mut Env, i: &ast::view_item) {
     match i.node {
-      ast::view_item_extern_mod(ident, ref meta_items, id) => {
-        debug!("resolving extern mod stmt. ident: %?, meta: %?",
-               ident, *meta_items);
-        let cnum = resolve_crate(e,
-                                 ident,
-                                 (*meta_items).clone(),
-                                 @"",
-                                 i.span);
-        cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum);
+      ast::view_item_extern_mod(ident, path_opt, ref meta_items, id) => {
+          let ident = token::ident_to_str(&ident);
+          let meta_items = match path_opt {
+              None => meta_items.clone(),
+              Some(p) => {
+                  let p_path = Path(p);
+                  match p_path.filestem() {
+                      Some(s) =>
+                          vec::append(
+                              ~[attr::mk_name_value_item_str(@"package_id", p),
+                               attr::mk_name_value_item_str(@"name", s.to_managed())],
+                              *meta_items),
+                      None => e.diag.span_bug(i.span, "Bad package path in `extern mod` item")
+                  }
+            }
+          };
+          debug!("resolving extern mod stmt. ident: %?, meta: %?",
+                 ident, meta_items);
+          let cnum = resolve_crate(e,
+                                   ident,
+                                   meta_items,
+                                   @"",
+                                   i.span);
+          cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum);
       }
       _ => ()
-    }
+  }
 }
 
 fn visit_item(e: &Env, i: @ast::item) {
@@ -167,7 +183,7 @@ fn visit_item(e: &Env, i: @ast::item) {
         match fm.sort {
             ast::named => {
                 let link_name = i.attrs.iter()
-                    .find_(|at| "link_name" == at.name())
+                    .find(|at| "link_name" == at.name())
                     .chain(|at| at.value_str());
 
                 let foreign_name = match link_name {
@@ -233,12 +249,12 @@ fn existing_match(e: &Env, metas: &[@ast::MetaItem], hash: &str)
 }
 
 fn resolve_crate(e: @mut Env,
-                 ident: ast::ident,
+                 ident: @str,
                  metas: ~[@ast::MetaItem],
                  hash: @str,
                  span: span)
               -> ast::CrateNum {
-    let metas = metas_with_ident(token::ident_to_str(&ident), metas);
+    let metas = metas_with_ident(ident, metas);
 
     match existing_match(e, metas, hash) {
       None => {
@@ -279,7 +295,7 @@ fn resolve_crate(e: @mut Env,
             match attr::last_meta_item_value_str_by_name(load_ctxt.metas,
                                                          "name") {
                 Some(v) => v,
-                None => token::ident_to_str(&ident),
+                None => ident
             };
         let cmeta = @cstore::crate_metadata {
             name: cname,
@@ -308,7 +324,6 @@ fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map {
     let r = decoder::get_crate_deps(cdata);
     for dep in r.iter() {
         let extrn_cnum = dep.cnum;
-        let cname = dep.name;
         let cname_str = token::ident_to_str(&dep.name);
         let cmetas = metas_with(dep.vers, @"vers", ~[]);
         debug!("resolving dep crate %s ver: %s hash: %s",
@@ -327,7 +342,7 @@ fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map {
             // FIXME (#2404): Need better error reporting than just a bogus
             // span.
             let fake_span = dummy_sp();
-            let local_cnum = resolve_crate(e, cname, cmetas, dep.hash,
+            let local_cnum = resolve_crate(e, cname_str, cmetas, dep.hash,
                                            fake_span);
             cnum_map.insert(extrn_cnum, local_cnum);
           }
index 8d3571260184b679ec621756110ac3230e021c0c..81a2e863bde00613392089509de365aaf8774149 100644 (file)
 // what crate that's in and give us a def_id that makes sense for the current
 // build.
 
-fn lookup_hash(d: ebml::Doc, eq_fn: &fn(x:&[u8]) -> bool, hash: uint) ->
+fn lookup_hash(d: ebml::Doc, eq_fn: &fn(x:&[u8]) -> bool, hash: u64) ->
    Option<ebml::Doc> {
     let index = reader::get_doc(d, tag_index);
     let table = reader::get_doc(index, tag_index_table);
-    let hash_pos = table.start + hash % 256u * 4u;
-    let pos = io::u64_from_be_bytes(*d.data, hash_pos, 4u) as uint;
+    let hash_pos = table.start + (hash % 256 * 4) as uint;
+    let pos = io::u64_from_be_bytes(*d.data, hash_pos, 4) as uint;
     let tagged_doc = reader::doc_at(d.data, pos);
 
     let belt = tag_index_buckets_bucket_elt;
 
     let mut ret = None;
     do reader::tagged_docs(tagged_doc.doc, belt) |elt| {
-        let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4u) as uint;
-        if eq_fn(elt.data.slice(elt.start + 4u, elt.end)) {
+        let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4) as uint;
+        if eq_fn(elt.data.slice(elt.start + 4, elt.end)) {
             ret = Some(reader::doc_at(d.data, pos).doc);
             false
         } else {
@@ -84,7 +84,7 @@ fn eq_item(bytes: &[u8], item_id: int) -> bool {
     }
     lookup_hash(items,
                 |a| eq_item(a, item_id),
-                item_id.hash() as uint)
+                (item_id as i64).hash())
 }
 
 fn find_item(item_id: int, items: ebml::Doc) -> ebml::Doc {
index d847d8511265344aed7f2a593543663b6ea136d1..c4919e7f263213335ade8a94d45a0030f0a9ae45 100644 (file)
@@ -319,7 +319,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                             id: NodeId,
                             variants: &[variant],
                             path: &[ast_map::path_elt],
-                            index: @mut ~[entry<int>],
+                            index: @mut ~[entry<i64>],
                             generics: &ast::Generics) {
     debug!("encode_enum_variant_info(id=%?)", id);
 
@@ -329,7 +329,8 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                                ast::def_id { crate: LOCAL_CRATE, node: id });
     for variant in variants.iter() {
         let def_id = local_def(variant.node.id);
-        index.push(entry {val: variant.node.id, pos: ebml_w.writer.tell()});
+        index.push(entry {val: variant.node.id as i64,
+                          pos: ebml_w.writer.tell()});
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'v');
@@ -677,8 +678,8 @@ fn encode_info_for_struct(ecx: &EncodeContext,
                           ebml_w: &mut writer::Encoder,
                           path: &[ast_map::path_elt],
                           fields: &[@struct_field],
-                          global_index: @mut ~[entry<int>])
-                          -> ~[entry<int>] {
+                          global_index: @mut ~[entry<i64>])
+                          -> ~[entry<i64>] {
     /* Each class has its own index, since different classes
        may have fields with the same name */
     let mut index = ~[];
@@ -692,8 +693,8 @@ fn encode_info_for_struct(ecx: &EncodeContext,
         };
 
         let id = field.node.id;
-        index.push(entry {val: id, pos: ebml_w.writer.tell()});
-        global_index.push(entry {val: id, pos: ebml_w.writer.tell()});
+        index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
+        global_index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
         ebml_w.start_tag(tag_items_data_item);
         debug!("encode_info_for_struct: doing %s %d",
                tcx.sess.str_of(nm), id);
@@ -712,8 +713,8 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
                                path: &[ast_map::path_elt],
                                name: ast::ident,
                                ctor_id: NodeId,
-                               index: @mut ~[entry<int>]) {
-    index.push(entry { val: ctor_id, pos: ebml_w.writer.tell() });
+                               index: @mut ~[entry<i64>]) {
+    index.push(entry { val: ctor_id as i64, pos: ebml_w.writer.tell() });
 
     ebml_w.start_tag(tag_items_data_item);
     encode_def_id(ebml_w, local_def(ctor_id));
@@ -815,13 +816,13 @@ fn should_inline(attrs: &[Attribute]) -> bool {
 fn encode_info_for_item(ecx: &EncodeContext,
                         ebml_w: &mut writer::Encoder,
                         item: @item,
-                        index: @mut ~[entry<int>],
+                        index: @mut ~[entry<i64>],
                         path: &[ast_map::path_elt]) {
     let tcx = ecx.tcx;
 
     fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
-                     index: @mut ~[entry<int>]) {
-        index.push(entry { val: item.id, pos: ebml_w.writer.tell() });
+                     index: @mut ~[entry<i64>]) {
+        index.push(entry { val: item.id as i64, pos: ebml_w.writer.tell() });
     }
     let add_to_index: &fn() = || add_to_index_(item, ebml_w, index);
 
@@ -969,7 +970,7 @@ fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
 
         /* Each class has its own index -- encode it */
         let bkts = create_index(idx);
-        encode_index(ebml_w, bkts, write_int);
+        encode_index(ebml_w, bkts, write_i64);
         ebml_w.end_tag();
 
         // If this is a tuple- or enum-like struct, encode the type of the
@@ -1040,7 +1041,8 @@ fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
                 Some(ast_methods[i])
             } else { None };
 
-            index.push(entry {val: m.def_id.node, pos: ebml_w.writer.tell()});
+            index.push(entry {val: m.def_id.node as i64,
+                              pos: ebml_w.writer.tell()});
             encode_info_for_method(ecx,
                                    ebml_w,
                                    *m,
@@ -1086,7 +1088,8 @@ fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
 
             let method_ty = ty::method(tcx, method_def_id);
 
-            index.push(entry {val: method_def_id.node, pos: ebml_w.writer.tell()});
+            index.push(entry {val: method_def_id.node as i64,
+                              pos: ebml_w.writer.tell()});
 
             ebml_w.start_tag(tag_items_data_item);
 
@@ -1145,10 +1148,10 @@ fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
 fn encode_info_for_foreign_item(ecx: &EncodeContext,
                                 ebml_w: &mut writer::Encoder,
                                 nitem: @foreign_item,
-                                index: @mut ~[entry<int>],
+                                index: @mut ~[entry<i64>],
                                 path: &ast_map::path,
                                 abi: AbiSet) {
-    index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() });
+    index.push(entry { val: nitem.id as i64, pos: ebml_w.writer.tell() });
 
     ebml_w.start_tag(tag_items_data_item);
     match nitem.node {
@@ -1184,10 +1187,10 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
 fn encode_info_for_items(ecx: &EncodeContext,
                          ebml_w: &mut writer::Encoder,
                          crate: &Crate)
-                         -> ~[entry<int>] {
+                         -> ~[entry<i64>] {
     let index = @mut ~[];
     ebml_w.start_tag(tag_items_data);
-    index.push(entry { val: CRATE_NODE_ID, pos: ebml_w.writer.tell() });
+    index.push(entry { val: CRATE_NODE_ID as i64, pos: ebml_w.writer.tell() });
     encode_info_for_mod(ecx,
                         ebml_w,
                         &crate.module,
@@ -1304,7 +1307,7 @@ fn write_str(writer: @io::Writer, s: ~str) {
     writer.write_str(s);
 }
 
-fn write_int(writer: @io::Writer, &n: &int) {
+fn write_i64(writer: @io::Writer, &n: &i64) {
     assert!(n < 0x7fff_ffff);
     writer.write_be_u32(n as u32);
 }
@@ -1623,7 +1626,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
 
     i = *wr.pos;
     let items_buckets = create_index(items_index);
-    encode_index(&mut ebml_w, items_buckets, write_int);
+    encode_index(&mut ebml_w, items_buckets, write_i64);
     ecx.stats.index_bytes = *wr.pos - i;
     ebml_w.end_tag();
 
index 2422be3960b44e7af38f90d20f90e7d3be1fd49c..56200a221be374716e826792984f89510277b2bc 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.
 //
 
 use std::option;
 use std::os;
-use std::result;
+use std::hashmap::HashSet;
 
 // A module for searching for libraries
 // FIXME (#2658): I'm not happy how this module turned out. Should
 // probably just be folded into cstore.
 
+/// Functions with type `pick` take a parent directory as well as
+/// a file found in that directory.
 pub type pick<'self, T> = &'self fn(path: &Path) -> Option<T>;
 
 pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
@@ -46,28 +48,33 @@ struct FileSearchImpl {
     impl FileSearch for FileSearchImpl {
         fn sysroot(&self) -> @Path { self.sysroot }
         fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool {
+            let mut visited_dirs = HashSet::new();
+
             debug!("filesearch: searching additional lib search paths [%?]",
                    self.addl_lib_search_paths.len());
-            // a little weird
-            self.addl_lib_search_paths.iter().advance(|path| f(path));
+            for path in self.addl_lib_search_paths.iter() {
+                f(path);
+                visited_dirs.insert(path.to_str());
+            }
 
             debug!("filesearch: searching target lib path");
-            if !f(&make_target_lib_path(self.sysroot,
-                                        self.target_triple)) {
-                return false;
-            }
-            debug!("filesearch: searching rustpkg lib path nearest");
-            if match get_rustpkg_lib_path_nearest() {
-                    result::Ok(ref p) => f(p),
-                    result::Err(_) => true
-                } {
-                    return true;
+            let tlib_path = make_target_lib_path(self.sysroot,
+                                        self.target_triple);
+            if !visited_dirs.contains(&tlib_path.to_str()) {
+                if !f(&tlib_path) {
+                    return false;
                 }
-           debug!("filesearch: searching rustpkg lib path");
-           match get_rustpkg_lib_path() {
-              result::Ok(ref p) => f(p),
-              result::Err(_) => true
-           }
+            }
+            visited_dirs.insert(tlib_path.to_str());
+            // Try RUST_PATH
+            let rustpath = rust_path();
+            for path in rustpath.iter() {
+                    if !visited_dirs.contains(&path.push("lib").to_str()) {
+                        f(&path.push("lib"));
+                        visited_dirs.insert(path.push("lib").to_str());
+                    }
+            }
+            true
         }
         fn get_target_lib_path(&self) -> Path {
             make_target_lib_path(self.sysroot, self.target_triple)
@@ -94,12 +101,15 @@ pub fn search<T>(filesearch: @FileSearch, pick: pick<T>) -> Option<T> {
         for path in r.iter() {
             debug!("testing %s", path.to_str());
             let maybe_picked = pick(path);
-            if maybe_picked.is_some() {
-                debug!("picked %s", path.to_str());
-                rslt = maybe_picked;
-                break;
-            } else {
-                debug!("rejected %s", path.to_str());
+            match maybe_picked {
+                Some(_) => {
+                    debug!("picked %s", path.to_str());
+                    rslt = maybe_picked;
+                    break;
+                }
+                None => {
+                    debug!("rejected %s", path.to_str());
+                }
             }
         }
         rslt.is_none()
@@ -132,60 +142,65 @@ fn get_sysroot(maybe_sysroot: &Option<@Path>) -> @Path {
     }
 }
 
-pub fn get_rustpkg_sysroot() -> Result<Path, ~str> {
-    result::Ok(get_or_default_sysroot().push_many([libdir(), ~"rustpkg"]))
+#[cfg(windows)]
+static PATH_ENTRY_SEPARATOR: &'static str = ";";
+#[cfg(not(windows))]
+static PATH_ENTRY_SEPARATOR: &'static str = ":";
+
+/// Returns RUST_PATH as a string, without default paths added
+pub fn get_rust_path() -> Option<~str> {
+    os::getenv("RUST_PATH")
 }
 
-pub fn get_rustpkg_root() -> Result<Path, ~str> {
-    match os::getenv("RUSTPKG_ROOT") {
-        Some(ref _p) => result::Ok(Path((*_p))),
-        None => match os::homedir() {
-          Some(ref _q) => result::Ok((*_q).push(".rustpkg")),
-          None => result::Err(~"no RUSTPKG_ROOT or home directory")
+/// Returns the value of RUST_PATH, as a list
+/// of Paths. Includes default entries for, if they exist:
+/// $HOME/.rust
+/// DIR/.rust for any DIR that's the current working directory
+/// or an ancestor of it
+pub fn rust_path() -> ~[Path] {
+    let mut env_rust_path: ~[Path] = match get_rust_path() {
+        Some(env_path) => {
+            let env_path_components: ~[&str] =
+                env_path.split_str_iter(PATH_ENTRY_SEPARATOR).collect();
+            env_path_components.map(|&s| Path(s))
         }
+        None => ~[]
+    };
+    let cwd = os::getcwd();
+    // now add in default entries
+    let cwd_dot_rust = cwd.push(".rust");
+    if !env_rust_path.contains(&cwd_dot_rust) {
+        env_rust_path.push(cwd_dot_rust);
     }
-}
-
-pub fn get_rustpkg_root_nearest() -> Result<Path, ~str> {
-    do get_rustpkg_root().chain |p| {
-        let cwd = os::getcwd();
-        let cwd_rustpkg = cwd.push(".rustpkg");
-        let rustpkg_is_non_root_file =
-            !os::path_is_dir(&cwd_rustpkg) && cwd_rustpkg != p;
-        let mut par_rustpkg = cwd.pop().push(".rustpkg");
-        let mut rslt = result::Ok(cwd_rustpkg);
-
-        if rustpkg_is_non_root_file {
-            while par_rustpkg != p {
-                if os::path_is_dir(&par_rustpkg) {
-                    rslt = result::Ok(par_rustpkg);
-                    break;
-                }
-                if par_rustpkg.components.len() == 1 {
-                    // We just checked /.rustpkg, stop now.
-                    break;
-                }
-                par_rustpkg = par_rustpkg.pop().pop().push(".rustpkg");
-            }
+    if !env_rust_path.contains(&cwd) {
+        env_rust_path.push(cwd.clone());
+    }
+    do cwd.each_parent() |p| {
+        if !env_rust_path.contains(&p.push(".rust")) {
+            push_if_exists(&mut env_rust_path, p);
         }
-        rslt
     }
-}
-
-fn get_rustpkg_lib_path() -> Result<Path, ~str> {
-    do get_rustpkg_root().chain |p| {
-        result::Ok(p.push(libdir()))
+    let h = os::homedir();
+    for h in h.iter() {
+        if !env_rust_path.contains(&h.push(".rust")) {
+            push_if_exists(&mut env_rust_path, h);
+        }
     }
+    env_rust_path
 }
 
-fn get_rustpkg_lib_path_nearest() -> Result<Path, ~str> {
-    do get_rustpkg_root_nearest().chain |p| {
-        result::Ok(p.push(libdir()))
+
+/// Adds p/.rust into vec, only if it exists
+fn push_if_exists(vec: &mut ~[Path], p: &Path) {
+    let maybe_dir = p.push(".rust");
+    if os::path_exists(&maybe_dir) {
+        vec.push(maybe_dir);
     }
 }
 
 // The name of the directory rustc expects libraries to be located.
 // On Unix should be "lib", on windows "bin"
+#[cfg(stage0)]
 pub fn libdir() -> ~str {
    let libdir = env!("CFG_LIBDIR");
    if libdir.is_empty() {
@@ -193,3 +208,8 @@ pub fn libdir() -> ~str {
    }
    libdir.to_owned()
 }
+
+#[cfg(not(stage0))]
+pub fn libdir() -> ~str {
+    (env!("CFG_LIBDIR")).to_owned()
+}
index 9330cfc5c88b48fc4deade90b90c0298348955fd..704a22ec979252c2f27f1746d5cbaf240339bff1 100644 (file)
 use metadata::filesearch;
 use syntax::codemap::span;
 use syntax::diagnostic::span_handler;
-use syntax::parse::token;
 use syntax::parse::token::ident_interner;
 use syntax::print::pprust;
 use syntax::{ast, attr};
 use syntax::attr::AttrMetaMethods;
 
+use std::c_str::ToCStr;
 use std::cast;
 use std::io;
 use std::num;
@@ -46,7 +46,7 @@ pub struct Context {
     diag: @span_handler,
     filesearch: @FileSearch,
     span: span,
-    ident: ast::ident,
+    ident: @str,
     metas: ~[@ast::MetaItem],
     hash: @str,
     os: os,
@@ -60,7 +60,7 @@ pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) {
       None => {
         cx.diag.span_fatal(cx.span,
                            fmt!("can't find crate for `%s`",
-                                token::ident_to_str(&cx.ident)));
+                                cx.ident));
       }
     }
 }
@@ -89,37 +89,38 @@ fn find_library_crate_aux(
     filesearch: @filesearch::FileSearch
 ) -> Option<(~str, @~[u8])> {
     let crate_name = crate_name_from_metas(cx.metas);
-    let prefix = prefix + crate_name + "-";
-
+    // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
+    let prefix = fmt!("%s%s-", prefix, crate_name);
     let mut matches = ~[];
     filesearch::search(filesearch, |path| -> Option<()> {
-        debug!("inspecting file %s", path.to_str());
-        match path.filename() {
-            Some(ref f) if f.starts_with(prefix) && f.ends_with(suffix) => {
-                debug!("%s is a candidate", path.to_str());
-                match get_metadata_section(cx.os, path) {
-                    Some(cvec) =>
-                        if !crate_matches(cvec, cx.metas, cx.hash) {
-                            debug!("skipping %s, metadata doesn't match",
-                                   path.to_str());
-                            None
-                        } else {
-                            debug!("found %s with matching metadata", path.to_str());
-                            matches.push((path.to_str(), cvec));
-                            None
-                        },
-                    _ => {
-                        debug!("could not load metadata for %s", path.to_str());
-                        None
-                    }
-                }
-            }
-            _ => {
-                debug!("skipping %s, doesn't look like %s*%s", path.to_str(),
-                       prefix, suffix);
-                None
-            }
-        }});
+      let path_str = path.filename();
+      match path_str {
+          None => None,
+          Some(path_str) =>
+              if path_str.starts_with(prefix) && path_str.ends_with(suffix) {
+                  debug!("%s is a candidate", path.to_str());
+                  match get_metadata_section(cx.os, path) {
+                      Some(cvec) =>
+                          if !crate_matches(cvec, cx.metas, cx.hash) {
+                              debug!("skipping %s, metadata doesn't match",
+                                  path.to_str());
+                              None
+                          } else {
+                              debug!("found %s with matching metadata", path.to_str());
+                              matches.push((path.to_str(), cvec));
+                              None
+                          },
+                      _ => {
+                          debug!("could not load metadata for %s", path.to_str());
+                          None
+                      }
+                  }
+               }
+               else {
+                   None
+               }
+      }
+    });
 
     match matches.len() {
         0 => None,
@@ -137,8 +138,8 @@ fn find_library_crate_aux(
                 }
                 cx.diag.handler().abort_if_errors();
                 None
-            }
         }
+    }
 }
 
 pub fn crate_name_from_metas(metas: &[@ast::MetaItem]) -> @str {
@@ -151,6 +152,16 @@ pub fn crate_name_from_metas(metas: &[@ast::MetaItem]) -> @str {
     fail!("expected to find the crate name")
 }
 
+pub fn package_id_from_metas(metas: &[@ast::MetaItem]) -> Option<@str> {
+    for m in metas.iter() {
+        match m.name_str_pair() {
+            Some((name, s)) if "package_id" == name => { return Some(s); }
+            _ => {}
+        }
+    }
+    None
+}
+
 pub fn note_linkage_attrs(intr: @ident_interner,
                           diag: @span_handler,
                           attrs: ~[ast::Attribute]) {
@@ -175,6 +186,8 @@ fn crate_matches(crate_data: @~[u8],
 pub fn metadata_matches(extern_metas: &[@ast::MetaItem],
                         local_metas: &[@ast::MetaItem]) -> bool {
 
+// extern_metas: metas we read from the crate
+// local_metas: metas we're looking for
     debug!("matching %u metadata requirements against %u items",
            local_metas.len(), extern_metas.len());
 
@@ -186,7 +199,7 @@ pub fn metadata_matches(extern_metas: &[@ast::MetaItem],
 fn get_metadata_section(os: os,
                         filename: &Path) -> Option<@~[u8]> {
     unsafe {
-        let mb = do filename.to_str().as_c_str |buf| {
+        let mb = do filename.to_c_str().with_ref |buf| {
             llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
         };
         if mb as int == 0 { return option::None::<@~[u8]>; }
index b909f70440a8258031011ac11d0bf8024a2d4eda..8a7894efb915d97015466ea867e617cbe74eff1a 100644 (file)
@@ -1204,7 +1204,7 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
                     }
                     c::tag_table_capture_map => {
                         let cvars =
-                            at_vec::to_managed_consume(
+                            at_vec::to_managed_move(
                                 val_dsr.read_to_vec(
                                     |val_dsr| val_dsr.read_capture_var(xcx)));
                         dcx.maps.capture_map.insert(id, cvars);
index 767c2b4ee2ed75ca0de10e269d49b1bdcd54e79b..282292a2ac09ce52796390f042d2f08748d7da6a 100644 (file)
@@ -112,23 +112,23 @@ fn pat(&mut self, pat: @ast::pat, pred: CFGIndex) -> CFGIndex {
             ast::pat_enum(_, Some(ref subpats)) |
             ast::pat_tup(ref subpats) => {
                 let pats_exit =
-                    self.pats_all(subpats.iter().transform(|p| *p), pred);
+                    self.pats_all(subpats.iter().map(|p| *p), pred);
                 self.add_node(pat.id, [pats_exit])
             }
 
             ast::pat_struct(_, ref subpats, _) => {
                 let pats_exit =
-                    self.pats_all(subpats.iter().transform(|f| f.pat), pred);
+                    self.pats_all(subpats.iter().map(|f| f.pat), pred);
                 self.add_node(pat.id, [pats_exit])
             }
 
             ast::pat_vec(ref pre, ref vec, ref post) => {
                 let pre_exit =
-                    self.pats_all(pre.iter().transform(|p| *p), pred);
+                    self.pats_all(pre.iter().map(|p| *p), pred);
                 let vec_exit =
-                    self.pats_all(vec.iter().transform(|p| *p), pre_exit);
+                    self.pats_all(vec.iter().map(|p| *p), pre_exit);
                 let post_exit =
-                    self.pats_all(post.iter().transform(|p| *p), vec_exit);
+                    self.pats_all(post.iter().map(|p| *p), vec_exit);
                 self.add_node(pat.id, [post_exit])
             }
         }
@@ -376,7 +376,7 @@ fn expr(&mut self, expr: @ast::expr, pred: CFGIndex) -> CFGIndex {
             ast::expr_struct(_, ref fields, base) => {
                 let base_exit = self.opt_expr(base, pred);
                 let field_exprs: ~[@ast::expr] =
-                    fields.iter().transform(|f| f.expr).collect();
+                    fields.iter().map(|f| f.expr).collect();
                 self.straightline(expr, base_exit, field_exprs)
             }
 
index 1b420b9c06a55b60a758d3dfb6f76b311573ef6f..37f45142a1107f189c9eb5f897018ab255164ac0 100644 (file)
@@ -169,7 +169,7 @@ pub fn check_exhaustive(cx: &MatchCheckCtxt, sp: span, pats: ~[@pat]) {
                     };
                     let variants = ty::enum_variants(cx.tcx, id);
 
-                    match variants.iter().find_(|v| v.id == vid) {
+                    match variants.iter().find(|v| v.id == vid) {
                         Some(v) => Some(cx.tcx.sess.str_of(v.name)),
                         None => {
                             fail!("check_exhaustive: bad variant in ctor")
@@ -222,7 +222,7 @@ pub enum ctor {
 pub fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful {
     if m.len() == 0u { return useful_; }
     if m[0].len() == 0u { return not_useful; }
-    let real_pat = match m.iter().find_(|r| r[0].id != 0) {
+    let real_pat = match m.iter().find(|r| r[0].id != 0) {
       Some(r) => r[0], None => v[0]
     };
     let left_ty = if real_pat.id == 0 { ty::mk_nil() }
@@ -255,6 +255,9 @@ pub fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful {
                 }
                 not_useful
               }
+              ty::ty_evec(_, ty::vstore_fixed(n)) => {
+                is_useful_specialized(cx, m, v, vec(n), n, left_ty)
+              }
               ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
                 let max_len = do m.rev_iter().fold(0) |max_len, r| {
                   match r[0].node {
@@ -409,6 +412,29 @@ pub fn missing_ctor(cx: &MatchCheckCtxt,
         else if true_found { Some(val(const_bool(false))) }
         else { Some(val(const_bool(true))) }
       }
+      ty::ty_evec(_, ty::vstore_fixed(n)) => {
+        let mut missing = true;
+        let mut wrong = false;
+        for r in m.iter() {
+          match r[0].node {
+            pat_vec(ref before, ref slice, ref after) => {
+              let count = before.len() + after.len();
+              if (count < n && slice.is_none()) || count > n {
+                wrong = true;
+              }
+              if count == n || (count < n && slice.is_some()) {
+                missing = false;
+              }
+            }
+            _ => {}
+          }
+        }
+        match (wrong, missing) {
+          (true, _) => Some(vec(n)), // should be compile-time error
+          (_, true) => Some(vec(n)),
+          _         => None
+        }
+      }
       ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
 
         // Find the lengths and slices of all vector patterns.
@@ -470,7 +496,7 @@ pub fn ctor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
       ty::ty_enum(eid, _) => {
           let id = match *ctor { variant(id) => id,
           _ => fail!("impossible case") };
-        match ty::enum_variants(cx.tcx, eid).iter().find_(|v| v.id == id ) {
+        match ty::enum_variants(cx.tcx, eid).iter().find(|v| v.id == id ) {
             Some(v) => v.args.len(),
             None => fail!("impossible case")
         }
@@ -627,7 +653,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
                         if variant(variant_id) == *ctor_id {
                             // FIXME #4731: Is this right? --pcw
                             let args = flds.map(|ty_field| {
-                                match flds.iter().find_(|f|
+                                match flds.iter().find(|f|
                                                 f.ident == ty_field.ident) {
                                     Some(f) => f.pat,
                                     _ => wild()
@@ -657,8 +683,8 @@ pub fn specialize(cx: &MatchCheckCtxt,
                                          ty_to_str(cx.tcx, left_ty)));
                             }
                         }
-                        let args = class_fields.iter().transform(|class_field| {
-                            match flds.iter().find_(|f|
+                        let args = class_fields.iter().map(|class_field| {
+                            match flds.iter().find(|f|
                                             f.ident == class_field.ident) {
                                 Some(f) => f.pat,
                                 _ => wild()
index 3b56764f2fcad1afb0f38f41df22a46f744d794c..2de94cdbf4ccd03d2c249c1d6cd9f4f8b968b37b 100644 (file)
@@ -102,7 +102,7 @@ pub fn classify(e: &expr,
 
               ast::expr_tup(ref es) |
               ast::expr_vec(ref es, ast::m_imm) => {
-                join_all(es.iter().transform(|e| classify(*e, tcx)))
+                join_all(es.iter().map(|e| classify(*e, tcx)))
               }
 
               ast::expr_vstore(e, vstore) => {
@@ -116,7 +116,7 @@ pub fn classify(e: &expr,
               }
 
               ast::expr_struct(_, ref fs, None) => {
-                let cs = do fs.iter().transform |f| {
+                let cs = do fs.iter().map |f| {
                     classify(f.expr, tcx)
                 };
                 join_all(cs)
index bbcb40df77528f13b1deed76e89cdc6a29abc305..3a15cbe0f5221bcb30101cd98df7fa11eed345c7 100644 (file)
@@ -994,7 +994,7 @@ fn lint_session(cx: @mut Context) -> @visit::Visitor<()> {
         match cx.tcx.sess.lints.pop(&id) {
             None => {},
             Some(l) => {
-                for (lint, span, msg) in l.consume_iter() {
+                for (lint, span, msg) in l.move_iter() {
                     cx.span_lint(lint, span, msg)
                 }
             }
index 9ffeb99ac3559bf7bf82810e3b7abba8579173c4..a4b88870b97390deb3140287e71cf3542563af34 100644 (file)
@@ -403,6 +403,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                     // Ditto
                     match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
                                                           base))).sty {
+                        ty_enum(id, _) |
                         ty_struct(id, _)
                         if id.crate != LOCAL_CRATE ||
                            !privileged_items.iter().any(|x| x == &(id.node)) => {
index f55fdd22c9a9f8bcd91889887db598a33fc367da..4d95909404e18ef33f8bc69e7630b3724575ab04 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.
 //
@@ -1487,9 +1487,10 @@ pub fn build_reduced_graph_for_view_item(@mut self,
                 }
             }
 
-            view_item_extern_mod(name, _, node_id) => {
+            view_item_extern_mod(name, _, _, node_id) => {
+                // n.b. we don't need to look at the path option here, because cstore already did
                 match find_extern_mod_stmt_cnum(self.session.cstore,
-                                                node_id) {
+                                                        node_id) {
                     Some(crate_id) => {
                         let def_id = def_id { crate: crate_id, node: 0 };
                         let parent_link = ModuleParentLink
@@ -4994,7 +4995,9 @@ pub fn resolve_expr(@mut self, expr: @expr, visitor: ResolveVisitor) {
                             if self.structs.contains(&class_id) => {
                         self.record_def(expr.id, definition);
                     }
-                    _ => {
+                    result => {
+                        debug!("(resolving expression) didn't find struct \
+                                def: %?", result);
                         self.session.span_err(
                             path.span,
                             fmt!("`%s` does not name a structure",
@@ -5363,7 +5366,7 @@ pub fn module_to_str(@mut self, module_: @mut Module) -> ~str {
         if idents.len() == 0 {
             return ~"???";
         }
-        return self.idents_to_str(idents.consume_rev_iter().collect::<~[ast::ident]>());
+        return self.idents_to_str(idents.move_rev_iter().collect::<~[ast::ident]>());
     }
 
     pub fn dump_module(@mut self, module_: @mut Module) {
index 9a0dc5f036c76b701fe192d9724b68559b6539e6..1a9c36313df74c6d9be934577004edda112d08b3 100644 (file)
 
 // An option identifying a literal: either a unit-like struct or an
 // expression.
-pub enum Lit {
+enum Lit {
     UnitLikeStructLit(ast::NodeId),    // the node ID of the pattern
     ExprLit(@ast::expr),
     ConstLit(ast::def_id),              // the def ID of the constant
@@ -191,7 +191,7 @@ pub enum Lit {
 
 // An option identifying a branch (either a literal, a enum variant or a
 // range)
-pub enum Opt {
+enum Opt {
     lit(Lit),
     var(/* disr val */ uint, @adt::Repr),
     range(@ast::expr, @ast::expr),
@@ -199,7 +199,7 @@ pub enum Opt {
     vec_len_ge(uint, /* slice */uint)
 }
 
-pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
+fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
     match (a, b) {
         (&lit(a), &lit(b)) => {
             match (a, b) {
@@ -258,7 +258,7 @@ pub enum opt_result {
     lower_bound(Result),
     range_result(Result, Result),
 }
-pub fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result {
+fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result {
     let _icx = push_ctxt("match::trans_opt");
     let ccx = bcx.ccx();
     let bcx = bcx;
@@ -292,7 +292,7 @@ pub fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result {
     }
 }
 
-pub fn variant_opt(bcx: @mut Block, pat_id: ast::NodeId)
+fn variant_opt(bcx: @mut Block, pat_id: ast::NodeId)
     -> Opt {
     let ccx = bcx.ccx();
     match ccx.tcx.def_map.get_copy(&pat_id) {
@@ -317,7 +317,7 @@ pub fn variant_opt(bcx: @mut Block, pat_id: ast::NodeId)
 }
 
 #[deriving(Clone)]
-pub enum TransBindingMode {
+enum TransBindingMode {
     TrByValue(/*llbinding:*/ ValueRef),
     TrByRef,
 }
@@ -331,24 +331,24 @@ pub enum TransBindingMode {
  * - `id` is the node id of the binding
  * - `ty` is the Rust type of the binding */
  #[deriving(Clone)]
-pub struct BindingInfo {
+struct BindingInfo {
     llmatch: ValueRef,
     trmode: TransBindingMode,
     id: ast::NodeId,
     ty: ty::t,
 }
 
-pub type BindingsMap = HashMap<ident, BindingInfo>;
+type BindingsMap = HashMap<ident, BindingInfo>;
 
 #[deriving(Clone)]
-pub struct ArmData<'self> {
+struct ArmData<'self> {
     bodycx: @mut Block,
     arm: &'self ast::arm,
     bindings_map: @BindingsMap
 }
 
 #[deriving(Clone)]
-pub struct Match<'self> {
+struct Match<'self> {
     pats: ~[@ast::pat],
     data: ArmData<'self>
 }
@@ -364,7 +364,7 @@ fn repr(&self, tcx: ty::ctxt) -> ~str {
     }
 }
 
-pub fn has_nested_bindings(m: &[Match], col: uint) -> bool {
+fn has_nested_bindings(m: &[Match], col: uint) -> bool {
     for br in m.iter() {
         match br.pats[col].node {
           ast::pat_ident(_, _, Some(_)) => return true,
@@ -374,7 +374,7 @@ pub fn has_nested_bindings(m: &[Match], col: uint) -> bool {
     return false;
 }
 
-pub fn expand_nested_bindings<'r>(bcx: @mut Block,
+fn expand_nested_bindings<'r>(bcx: @mut Block,
                                   m: &[Match<'r>],
                                   col: uint,
                                   val: ValueRef)
@@ -409,7 +409,7 @@ pub fn expand_nested_bindings<'r>(bcx: @mut Block,
     }
 }
 
-pub fn assert_is_binding_or_wild(bcx: @mut Block, p: @ast::pat) {
+fn assert_is_binding_or_wild(bcx: @mut Block, p: @ast::pat) {
     if !pat_is_binding_or_wild(bcx.tcx().def_map, p) {
         bcx.sess().span_bug(
             p.span,
@@ -418,9 +418,9 @@ pub fn assert_is_binding_or_wild(bcx: @mut Block, p: @ast::pat) {
     }
 }
 
-pub type enter_pat<'self> = &'self fn(@ast::pat) -> Option<~[@ast::pat]>;
+type enter_pat<'self> = &'self fn(@ast::pat) -> Option<~[@ast::pat]>;
 
-pub fn enter_match<'r>(bcx: @mut Block,
+fn enter_match<'r>(bcx: @mut Block,
                        dm: DefMap,
                        m: &[Match<'r>],
                        col: uint,
@@ -470,7 +470,7 @@ pub fn enter_match<'r>(bcx: @mut Block,
     return result;
 }
 
-pub fn enter_default<'r>(bcx: @mut Block,
+fn enter_default<'r>(bcx: @mut Block,
                          dm: DefMap,
                          m: &[Match<'r>],
                          col: uint,
@@ -485,7 +485,7 @@ pub fn enter_default<'r>(bcx: @mut Block,
 
     do enter_match(bcx, dm, m, col, val) |p| {
         match p.node {
-          ast::pat_wild | ast::pat_tup(_) | ast::pat_struct(*) => Some(~[]),
+          ast::pat_wild | ast::pat_tup(_) => Some(~[]),
           ast::pat_ident(_, _, None) if pat_is_binding(dm, p) => Some(~[]),
           _ => None
         }
@@ -516,7 +516,7 @@ pub fn enter_default<'r>(bcx: @mut Block,
 // <nmatsakis> so all patterns must either be records (resp. tuples) or
 //             wildcards
 
-pub fn enter_opt<'r>(bcx: @mut Block,
+fn enter_opt<'r>(bcx: @mut Block,
                      m: &[Match<'r>],
                      opt: &Opt,
                      col: uint,
@@ -588,7 +588,7 @@ pub fn enter_opt<'r>(bcx: @mut Block,
                     let mut reordered_patterns = ~[];
                     let r = ty::lookup_struct_fields(tcx, struct_id);
                     for field in r.iter() {
-                            match field_pats.iter().find_(|p| p.ident == field.ident) {
+                            match field_pats.iter().find(|p| p.ident == field.ident) {
                                 None => reordered_patterns.push(dummy),
                                 Some(fp) => reordered_patterns.push(fp.pat)
                             }
@@ -628,7 +628,7 @@ pub fn enter_opt<'r>(bcx: @mut Block,
     }
 }
 
-pub fn enter_rec_or_struct<'r>(bcx: @mut Block,
+fn enter_rec_or_struct<'r>(bcx: @mut Block,
                                dm: DefMap,
                                m: &[Match<'r>],
                                col: uint,
@@ -648,7 +648,7 @@ pub fn enter_rec_or_struct<'r>(bcx: @mut Block,
             ast::pat_struct(_, ref fpats, _) => {
                 let mut pats = ~[];
                 for fname in fields.iter() {
-                    match fpats.iter().find_(|p| p.ident == *fname) {
+                    match fpats.iter().find(|p| p.ident == *fname) {
                         None => pats.push(dummy),
                         Some(pat) => pats.push(pat.pat)
                     }
@@ -663,7 +663,7 @@ pub fn enter_rec_or_struct<'r>(bcx: @mut Block,
     }
 }
 
-pub fn enter_tup<'r>(bcx: @mut Block,
+fn enter_tup<'r>(bcx: @mut Block,
                      dm: DefMap,
                      m: &[Match<'r>],
                      col: uint,
@@ -689,7 +689,7 @@ pub fn enter_tup<'r>(bcx: @mut Block,
     }
 }
 
-pub fn enter_tuple_struct<'r>(bcx: @mut Block,
+fn enter_tuple_struct<'r>(bcx: @mut Block,
                               dm: DefMap,
                               m: &[Match<'r>],
                               col: uint,
@@ -715,7 +715,7 @@ pub fn enter_tuple_struct<'r>(bcx: @mut Block,
     }
 }
 
-pub fn enter_box<'r>(bcx: @mut Block,
+fn enter_box<'r>(bcx: @mut Block,
                      dm: DefMap,
                      m: &[Match<'r>],
                      col: uint,
@@ -742,7 +742,7 @@ pub fn enter_box<'r>(bcx: @mut Block,
     }
 }
 
-pub fn enter_uniq<'r>(bcx: @mut Block,
+fn enter_uniq<'r>(bcx: @mut Block,
                       dm: DefMap,
                       m: &[Match<'r>],
                       col: uint,
@@ -769,7 +769,7 @@ pub fn enter_uniq<'r>(bcx: @mut Block,
     }
 }
 
-pub fn enter_region<'r>(bcx: @mut Block,
+fn enter_region<'r>(bcx: @mut Block,
                         dm: DefMap,
                         m: &[Match<'r>],
                         col: uint,
@@ -799,7 +799,7 @@ pub fn enter_region<'r>(bcx: @mut Block,
 // Returns the options in one column of matches. An option is something that
 // needs to be conditionally matched at runtime; for example, the discriminant
 // on a set of enum variants or a literal.
-pub fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] {
+fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] {
     let ccx = bcx.ccx();
     fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) {
         if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;}
@@ -865,12 +865,12 @@ fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) {
     return found;
 }
 
-pub struct ExtractedBlock {
+struct ExtractedBlock {
     vals: ~[ValueRef],
     bcx: @mut Block
 }
 
-pub fn extract_variant_args(bcx: @mut Block,
+fn extract_variant_args(bcx: @mut Block,
                             repr: &adt::Repr,
                             disr_val: uint,
                             val: ValueRef)
@@ -893,7 +893,7 @@ fn match_datum(bcx: @mut Block, val: ValueRef, pat_id: ast::NodeId) -> Datum {
 }
 
 
-pub fn extract_vec_elems(bcx: @mut Block,
+fn extract_vec_elems(bcx: @mut Block,
                          pat_span: span,
                          pat_id: ast::NodeId,
                          elem_count: uint,
@@ -947,24 +947,37 @@ pub fn extract_vec_elems(bcx: @mut Block,
     ExtractedBlock { vals: elems, bcx: bcx }
 }
 
-// NB: This function does not collect fields from struct-like enum variants.
-pub fn collect_record_or_struct_fields(bcx: @mut Block,
+/// Checks every pattern in `m` at `col` column.
+/// If there are a struct pattern among them function
+/// returns list of all fields that are matched in these patterns.
+/// Function returns None if there is no struct pattern.
+/// Function doesn't collect fields from struct-like enum variants.
+/// Function can return empty list if there is only wildcard struct pattern.
+fn collect_record_or_struct_fields(bcx: @mut Block,
                                        m: &[Match],
                                        col: uint)
-                                    -> ~[ast::ident] {
+                                    -> Option<~[ast::ident]> {
     let mut fields: ~[ast::ident] = ~[];
+    let mut found = false;
     for br in m.iter() {
         match br.pats[col].node {
           ast::pat_struct(_, ref fs, _) => {
             match ty::get(node_id_type(bcx, br.pats[col].id)).sty {
-              ty::ty_struct(*) => extend(&mut fields, *fs),
+              ty::ty_struct(*) => {
+                   extend(&mut fields, *fs);
+                   found = true;
+              }
               _ => ()
             }
           }
           _ => ()
         }
     }
-    return fields;
+    if found {
+        return Some(fields);
+    } else {
+        return None;
+    }
 
     fn extend(idents: &mut ~[ast::ident], field_pats: &[ast::field_pat]) {
         for field_pat in field_pats.iter() {
@@ -976,7 +989,7 @@ fn extend(idents: &mut ~[ast::ident], field_pats: &[ast::field_pat]) {
     }
 }
 
-pub fn pats_require_rooting(bcx: @mut Block,
+fn pats_require_rooting(bcx: @mut Block,
                             m: &[Match],
                             col: uint)
                          -> bool {
@@ -987,7 +1000,7 @@ pub fn pats_require_rooting(bcx: @mut Block,
     }
 }
 
-pub fn root_pats_as_necessary(mut bcx: @mut Block,
+fn root_pats_as_necessary(mut bcx: @mut Block,
                               m: &[Match],
                               col: uint,
                               val: ValueRef)
@@ -1018,23 +1031,23 @@ macro_rules! any_pat (
     )
 )
 
-pub fn any_box_pat(m: &[Match], col: uint) -> bool {
+fn any_box_pat(m: &[Match], col: uint) -> bool {
     any_pat!(m, ast::pat_box(_))
 }
 
-pub fn any_uniq_pat(m: &[Match], col: uint) -> bool {
+fn any_uniq_pat(m: &[Match], col: uint) -> bool {
     any_pat!(m, ast::pat_uniq(_))
 }
 
-pub fn any_region_pat(m: &[Match], col: uint) -> bool {
+fn any_region_pat(m: &[Match], col: uint) -> bool {
     any_pat!(m, ast::pat_region(_))
 }
 
-pub fn any_tup_pat(m: &[Match], col: uint) -> bool {
+fn any_tup_pat(m: &[Match], col: uint) -> bool {
     any_pat!(m, ast::pat_tup(_))
 }
 
-pub fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool {
+fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool {
     do m.iter().any |br| {
         let pat = br.pats[col];
         match pat.node {
@@ -1050,9 +1063,9 @@ pub fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool {
     }
 }
 
-pub type mk_fail = @fn() -> BasicBlockRef;
+type mk_fail = @fn() -> BasicBlockRef;
 
-pub fn pick_col(m: &[Match]) -> uint {
+fn pick_col(m: &[Match]) -> uint {
     fn score(p: &ast::pat) -> uint {
         match p.node {
           ast::pat_lit(_) | ast::pat_enum(_, _) | ast::pat_range(_, _) => 1u,
@@ -1088,7 +1101,7 @@ pub enum branch_kind { no_branch, single, switch, compare, compare_vec_len, }
 // Compiles a comparison between two things.
 //
 // NB: This must produce an i1, not a Rust bool (i8).
-pub fn compare_values(cx: @mut Block,
+fn compare_values(cx: @mut Block,
                       lhs: ValueRef,
                       rhs: ValueRef,
                       rhs_t: ty::t)
@@ -1204,7 +1217,7 @@ fn insert_lllocals(bcx: @mut Block,
     return bcx;
 }
 
-pub fn compile_guard(bcx: @mut Block,
+fn compile_guard(bcx: @mut Block,
                      guard_expr: @ast::expr,
                      data: &ArmData,
                      m: &[Match],
@@ -1261,7 +1274,7 @@ fn drop_bindings(bcx: @mut Block, data: &ArmData) -> @mut Block {
     }
 }
 
-pub fn compile_submatch(bcx: @mut Block,
+fn compile_submatch(bcx: @mut Block,
                         m: &[Match],
                         vals: &[ValueRef],
                         chk: Option<mk_fail>) {
@@ -1336,22 +1349,24 @@ fn compile_submatch_continue(mut bcx: @mut Block,
     // required to root any values.
     assert!(any_box_pat(m, col) || !pats_require_rooting(bcx, m, col));
 
-    let rec_fields = collect_record_or_struct_fields(bcx, m, col);
-    if rec_fields.len() > 0 {
-        let pat_ty = node_id_type(bcx, pat_id);
-        let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
-        do expr::with_field_tys(tcx, pat_ty, None) |discr, field_tys| {
-            let rec_vals = rec_fields.map(|field_name| {
-                let ix = ty::field_idx_strict(tcx, *field_name, field_tys);
-                adt::trans_field_ptr(bcx, pat_repr, val, discr, ix)
-            });
-            compile_submatch(
-                bcx,
-                enter_rec_or_struct(bcx, dm, m, col, rec_fields, val),
-                vec::append(rec_vals, vals_left),
-                chk);
+    match collect_record_or_struct_fields(bcx, m, col) {
+        Some(ref rec_fields) => {
+            let pat_ty = node_id_type(bcx, pat_id);
+            let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
+            do expr::with_field_tys(tcx, pat_ty, None) |discr, field_tys| {
+                let rec_vals = rec_fields.map(|field_name| {
+                        let ix = ty::field_idx_strict(tcx, *field_name, field_tys);
+                        adt::trans_field_ptr(bcx, pat_repr, val, discr, ix)
+                        });
+                compile_submatch(
+                        bcx,
+                        enter_rec_or_struct(bcx, dm, m, col, *rec_fields, val),
+                        vec::append(rec_vals, vals_left),
+                        chk);
+            }
+            return;
         }
-        return;
+        None => {}
     }
 
     if any_tup_pat(m, col) {
@@ -1670,7 +1685,7 @@ fn create_bindings_map(bcx: @mut Block, pat: @ast::pat) -> BindingsMap {
     return bindings_map;
 }
 
-pub fn trans_match_inner(scope_cx: @mut Block,
+fn trans_match_inner(scope_cx: @mut Block,
                          discr_expr: @ast::expr,
                          arms: &[ast::arm],
                          dest: Dest) -> @mut Block {
@@ -1752,7 +1767,7 @@ fn mk_fail(bcx: @mut Block, sp: span, msg: @str,
     }
 }
 
-pub enum IrrefutablePatternBindingMode {
+enum IrrefutablePatternBindingMode {
     // Stores the association between node ID and LLVM value in `lllocals`.
     BindLocal,
     // Stores the association between node ID and LLVM value in `llargs`.
index 2eb9841c6c7577411454205a0a9f8c0e8bcec754..a00cfa2912380a771e7b14066cc47e65e7ee5009 100644 (file)
@@ -508,7 +508,7 @@ pub fn trans_const(ccx: &mut CrateContext, r: &Repr, discr: uint,
         }
         General(ref cases) => {
             let case = &cases[discr];
-            let max_sz = cases.iter().transform(|x| x.size).max().unwrap();
+            let max_sz = cases.iter().map(|x| x.size).max().unwrap();
             let discr_ty = C_uint(ccx, discr);
             let contents = build_const_struct(ccx, case,
                                               ~[discr_ty] + vals);
@@ -519,7 +519,7 @@ pub fn trans_const(ccx: &mut CrateContext, r: &Repr, discr: uint,
                 C_struct(build_const_struct(ccx, nonnull, vals))
             } else {
                 assert_eq!(vals.len(), 0);
-                let vals = do nonnull.fields.iter().enumerate().transform |(i, &ty)| {
+                let vals = do nonnull.fields.iter().enumerate().map |(i, &ty)| {
                     let llty = type_of::sizing_type_of(ccx, ty);
                     if i == ptrfield { C_null(llty) } else { C_undef(llty) }
                 }.collect::<~[ValueRef]>();
index e54724b02ad40efd0225b389488ffb4b20c64e24..b6057199a280fbccddba02aefe60d7b20f42c5f7 100644 (file)
@@ -12,6 +12,7 @@
 # Translation of inline assembly.
 */
 
+use std::c_str::ToCStr;
 
 use lib;
 use middle::trans::build::*;
@@ -119,8 +120,8 @@ pub fn trans_inline_asm(bcx: @mut Block, ia: &ast::inline_asm) -> @mut Block {
         ast::asm_intel => lib::llvm::AD_Intel
     };
 
-    let r = do ia.asm.as_c_str |a| {
-        do constraints.as_c_str |c| {
+    let r = do ia.asm.to_c_str().with_ref |a| {
+        do constraints.to_c_str().with_ref |c| {
             InlineAsmCall(bcx, a, c, inputs, output, ia.volatile, ia.alignstack, dialect)
         }
     };
index db8a86fe948dff3d38bb9fafcbd811ef2e0d9219..762f6953bb2228aede51fac529c16359ad1db826 100644 (file)
 use middle::trans::tvec;
 use middle::trans::type_of;
 use middle::trans::type_of::*;
+use middle::trans::value::Value;
 use middle::ty;
 use util::common::indenter;
 use util::ppaux::{Repr, ty_to_str};
 
 use middle::trans::type_::Type;
 
+use std::c_str::ToCStr;
 use std::hash;
 use std::hashmap::HashMap;
 use std::io;
@@ -179,7 +181,7 @@ pub fn drop(&self) {
 }
 
 pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
-    let llfn: ValueRef = do name.as_c_str |buf| {
+    let llfn: ValueRef = do name.to_c_str().with_ref |buf| {
         unsafe {
             llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
         }
@@ -219,7 +221,7 @@ pub fn get_extern_const(externs: &mut ExternMap, llmod: ModuleRef,
         None => ()
     }
     unsafe {
-        let c = do name.as_c_str |buf| {
+        let c = do name.to_c_str().with_ref |buf| {
             llvm::LLVMAddGlobal(llmod, ty.to_ref(), buf)
         };
         externs.insert(name, c);
@@ -521,7 +523,7 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
 // Structural comparison: a rather involved form of glue.
 pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
     if cx.sess.opts.save_temps {
-        do s.as_c_str |buf| {
+        do s.to_c_str().with_ref |buf| {
             unsafe {
                 llvm::LLVMSetValueName(v, buf)
             }
@@ -1135,7 +1137,7 @@ pub fn new_block(cx: @mut FunctionContext,
                  opt_node_info: Option<NodeInfo>)
               -> @mut Block {
     unsafe {
-        let llbb = do name.as_c_str |buf| {
+        let llbb = do name.to_c_str().with_ref |buf| {
             llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf)
         };
         let bcx = @mut Block::new(llbb,
@@ -1276,7 +1278,7 @@ pub fn cleanup_and_leave(bcx: @mut Block,
                         let mut skip = 0;
                         let mut dest = None;
                         {
-                            let r = (*inf).cleanup_paths.rev_iter().find_(|cp| cp.target == leave);
+                            let r = (*inf).cleanup_paths.rev_iter().find(|cp| cp.target == leave);
                             for cp in r.iter() {
                                 if cp.size == inf.cleanups.len() {
                                     Br(bcx, cp.dest);
@@ -1552,7 +1554,7 @@ pub struct BasicBlocks {
 pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
     unsafe {
         let cx = task_llcx();
-        do "static_allocas".as_c_str | buf| {
+        do "static_allocas".to_c_str().with_ref | buf| {
             llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
         }
     }
@@ -1561,7 +1563,7 @@ pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
 pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
     unsafe {
         let cx = task_llcx();
-        do "return".as_c_str |buf| {
+        do "return".to_c_str().with_ref |buf| {
             llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
         }
     }
@@ -1791,11 +1793,30 @@ pub fn finish_fn(fcx: @mut FunctionContext, last_bcx: @mut Block) {
 // Builds the return block for a function.
 pub fn build_return_block(fcx: &FunctionContext, ret_cx: @mut Block) {
     // Return the value if this function immediate; otherwise, return void.
-    if fcx.llretptr.is_some() && fcx.has_immediate_return_value {
-        Ret(ret_cx, Load(ret_cx, fcx.llretptr.unwrap()))
-    } else {
-        RetVoid(ret_cx)
+    if fcx.llretptr.is_none() || !fcx.has_immediate_return_value {
+        return RetVoid(ret_cx);
     }
+
+    let retptr = Value(fcx.llretptr.unwrap());
+    let retval = match retptr.get_dominating_store(ret_cx) {
+        // If there's only a single store to the ret slot, we can directly return
+        // the value that was stored and omit the store and the alloca
+        Some(s) => {
+            let retval = *s.get_operand(0).unwrap();
+            s.erase_from_parent();
+
+            if retptr.has_no_uses() {
+                retptr.erase_from_parent();
+            }
+
+            retval
+        }
+        // Otherwise, load the return value from the ret slot
+        None => Load(ret_cx, fcx.llretptr.unwrap())
+    };
+
+
+    Ret(ret_cx, retval);
 }
 
 pub enum self_arg { impl_self(ty::t, ty::SelfMode), no_self, }
@@ -2312,7 +2333,7 @@ fn create_entry_fn(ccx: @mut CrateContext,
             };
             decl_cdecl_fn(ccx.llmod, main_name, llfty)
         };
-        let llbb = do "top".as_c_str |buf| {
+        let llbb = do "top".to_c_str().with_ref |buf| {
             unsafe {
                 llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
             }
@@ -2322,7 +2343,7 @@ fn create_entry_fn(ccx: @mut CrateContext,
             llvm::LLVMPositionBuilderAtEnd(bld, llbb);
 
             let crate_map = ccx.crate_map;
-            let opaque_crate_map = do "crate_map".as_c_str |buf| {
+            let opaque_crate_map = do "crate_map".to_c_str().with_ref |buf| {
                 llvm::LLVMBuildPointerCast(bld, crate_map, Type::i8p().to_ref(), buf)
             };
 
@@ -2340,7 +2361,7 @@ fn create_entry_fn(ccx: @mut CrateContext,
                 };
 
                 let args = {
-                    let opaque_rust_main = do "rust_main".as_c_str |buf| {
+                    let opaque_rust_main = do "rust_main".to_c_str().with_ref |buf| {
                         llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p().to_ref(), buf)
                     };
 
@@ -2365,11 +2386,10 @@ fn create_entry_fn(ccx: @mut CrateContext,
                 (rust_main, args)
             };
 
-            let result = llvm::LLVMBuildCall(bld,
-                                             start_fn,
-                                             &args[0],
-                                             args.len() as c_uint,
-                                             noname());
+            let result = do args.as_imm_buf |buf, len| {
+                llvm::LLVMBuildCall(bld, start_fn, buf, len as c_uint, noname())
+            };
+
             llvm::LLVMBuildRet(bld, result);
         }
     }
@@ -2428,7 +2448,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
 
                             unsafe {
                                 let llty = llvm::LLVMTypeOf(v);
-                                let g = do sym.as_c_str |buf| {
+                                let g = do sym.to_c_str().with_ref |buf| {
                                     llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
                                 };
 
@@ -2452,7 +2472,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
 
                     match (attr::first_attr_value_str_by_name(i.attrs, "link_section")) {
                         Some(sect) => unsafe {
-                            do sect.as_c_str |buf| {
+                            do sect.to_c_str().with_ref |buf| {
                                 llvm::LLVMSetSection(v, buf);
                             }
                         },
@@ -2493,7 +2513,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
                         }
                         ast::foreign_item_static(*) => {
                             let ident = token::ident_to_str(&ni.ident);
-                            let g = do ident.as_c_str |buf| {
+                            let g = do ident.to_c_str().with_ref |buf| {
                                 unsafe {
                                     let ty = type_of(ccx, ty);
                                     llvm::LLVMAddGlobal(ccx.llmod, ty.to_ref(), buf)
@@ -2600,7 +2620,7 @@ pub fn trans_constant(ccx: &mut CrateContext, it: @ast::item) {
             let s = mangle_exported_name(ccx, p, ty::mk_int()).to_managed();
             let disr_val = vi[i].disr_val;
             note_unique_llvm_symbol(ccx, s);
-            let discrim_gvar = do s.as_c_str |buf| {
+            let discrim_gvar = do s.to_c_str().with_ref |buf| {
                 unsafe {
                     llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
                 }
@@ -2741,7 +2761,7 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) {
     }
 
     let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id;
-    let gc_metadata = do gc_metadata_name.as_c_str |buf| {
+    let gc_metadata = do gc_metadata_name.to_c_str().with_ref |buf| {
         unsafe {
             llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
         }
@@ -2756,7 +2776,7 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) {
 pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef {
     let elttype = Type::struct_([ccx.int_type, ccx.int_type], false);
     let maptype = Type::array(&elttype, (ccx.module_data.len() + 1) as u64);
-    let map = do "_rust_mod_map".as_c_str |buf| {
+    let map = do "_rust_mod_map".to_c_str().with_ref |buf| {
         unsafe {
             llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
         }
@@ -2804,7 +2824,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
     let sym_name = ~"_rust_crate_map_" + mapname;
     let arrtype = Type::array(&int_type, n_subcrates as u64);
     let maptype = Type::struct_([Type::i32(), Type::i8p(), int_type, arrtype], false);
-    let map = do sym_name.as_c_str |buf| {
+    let map = do sym_name.to_c_str().with_ref |buf| {
         unsafe {
             llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
         }
@@ -2823,7 +2843,7 @@ pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) {
                       cdata.name,
                       cstore::get_crate_vers(cstore, i),
                       cstore::get_crate_hash(cstore, i));
-        let cr = do nm.as_c_str |buf| {
+        let cr = do nm.to_c_str().with_ref |buf| {
             unsafe {
                 llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
             }
@@ -2886,21 +2906,21 @@ pub fn write_metadata(cx: &mut CrateContext, crate: &ast::Crate) {
     let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
     let llmeta = C_bytes(encoder::encode_metadata(encode_parms, crate));
     let llconst = C_struct([llmeta]);
-    let mut llglobal = do "rust_metadata".as_c_str |buf| {
+    let mut llglobal = do "rust_metadata".to_c_str().with_ref |buf| {
         unsafe {
             llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst).to_ref(), buf)
         }
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
-        do cx.sess.targ_cfg.target_strs.meta_sect_name.as_c_str |buf| {
+        do cx.sess.targ_cfg.target_strs.meta_sect_name.to_c_str().with_ref |buf| {
             llvm::LLVMSetSection(llglobal, buf)
         };
         lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
 
         let t_ptr_i8 = Type::i8p();
         llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8.to_ref());
-        let llvm_used = do "llvm.used".as_c_str |buf| {
+        let llvm_used = do "llvm.used".to_c_str().with_ref |buf| {
             llvm::LLVMAddGlobal(cx.llmod, Type::array(&t_ptr_i8, 1).to_ref(), buf)
         };
         lib::llvm::SetLinkage(llvm_used, lib::llvm::AppendingLinkage);
@@ -2914,7 +2934,7 @@ fn mk_global(ccx: &CrateContext,
              internal: bool)
           -> ValueRef {
     unsafe {
-        let llglobal = do name.as_c_str |buf| {
+        let llglobal = do name.to_c_str().with_ref |buf| {
             llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval).to_ref(), buf)
         };
         llvm::LLVMSetInitializer(llglobal, llval);
diff --git a/src/librustc/middle/trans/basic_block.rs b/src/librustc/middle/trans/basic_block.rs
new file mode 100644 (file)
index 0000000..8ca18d8
--- /dev/null
@@ -0,0 +1,42 @@
+// 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 lib::llvm::{llvm, BasicBlockRef};
+use middle::trans::value::{UserIterator, Value};
+use std::iterator::{Filter, Map};
+
+pub struct BasicBlock(BasicBlockRef);
+
+pub type PredIterator<'self> = Map<'self, Value, BasicBlock, Filter<'self, Value, UserIterator>>;
+
+/**
+ * Wrapper for LLVM BasicBlockRef
+ */
+impl BasicBlock {
+    pub fn as_value(self) -> Value {
+        unsafe {
+            Value(llvm::LLVMBasicBlockAsValue(*self))
+        }
+    }
+
+    pub fn pred_iter(self) -> PredIterator {
+        self.as_value().user_iter()
+            .filter(|user| user.is_a_terminator_inst())
+            .map(|user| user.get_parent().unwrap())
+    }
+
+    pub fn get_single_predecessor(self) -> Option<BasicBlock> {
+        let mut iter = self.pred_iter();
+        match (iter.next(), iter.next()) {
+            (Some(first), None) => Some(first),
+            _ => None
+        }
+    }
+}
index 1d821e5af94bd3769c8477a846978c66564209e9..8f48c00b8d6b4795e4e83efd4612f0c7afd22627 100644 (file)
@@ -423,7 +423,7 @@ pub fn alloca(&self, ty: Type, name: &str) -> ValueRef {
             if name.is_empty() {
                 llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
             } else {
-                do name.as_c_str |c| {
+                do name.to_c_str().with_ref |c| {
                     llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), c)
                 }
             }
@@ -521,7 +521,7 @@ pub fn gepi(&self, base: ValueRef, ixs: &[uint]) -> ValueRef {
             }
             self.inbounds_gep(base, small_vec.slice(0, ixs.len()))
         } else {
-            let v = do ixs.iter().transform |i| { C_i32(*i as i32) }.collect::<~[ValueRef]>();
+            let v = do ixs.iter().map |i| { C_i32(*i as i32) }.collect::<~[ValueRef]>();
             self.count_insn("gepi");
             self.inbounds_gep(base, v)
         }
@@ -739,7 +739,7 @@ pub fn add_comment(&self, text: &str) {
             let sanitized = text.replace("$", "");
             let comment_text = fmt!("# %s", sanitized.replace("\n", "\n\t# "));
             self.count_insn("inlineasm");
-            let asm = do comment_text.as_c_str |c| {
+            let asm = do comment_text.to_c_str().with_ref |c| {
                 unsafe {
                     llvm::LLVMConstInlineAsm(Type::func([], &Type::void()).to_ref(),
                                              c, noname(), False, False)
@@ -895,7 +895,7 @@ pub fn trap(&self) {
             let BB: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
             let FN: ValueRef = llvm::LLVMGetBasicBlockParent(BB);
             let M: ModuleRef = llvm::LLVMGetGlobalParent(FN);
-            let T: ValueRef = do "llvm.trap".as_c_str |buf| {
+            let T: ValueRef = do "llvm.trap".to_c_str().with_ref |buf| {
                 llvm::LLVMGetNamedFunction(M, buf)
             };
             assert!((T as int != 0));
index 895bea715c964e73713dcc086f491d9516cabdc6..6a1905c451f97e4d99f397cc3498e841d754244e 100644 (file)
@@ -37,7 +37,7 @@ pub struct FnType {
 
 impl FnType {
     pub fn decl_fn(&self, decl: &fn(fnty: Type) -> ValueRef) -> ValueRef {
-        let atys = self.arg_tys.iter().transform(|t| t.ty).collect::<~[Type]>();
+        let atys = self.arg_tys.iter().map(|t| t.ty).collect::<~[Type]>();
         let rty = self.ret_ty.ty;
         let fnty = Type::func(atys, &rty);
         let llfn = decl(fnty);
index 240696ec1908b5a706b5b1da79ef34308b87bf8f..40a83eb9770787e8338e7471d31f4f4ee80f0c4d 100644 (file)
@@ -31,6 +31,7 @@
 
 use middle::trans::type_::Type;
 
+use std::c_str::ToCStr;
 use std::cast::transmute;
 use std::cast;
 use std::hashmap::{HashMap};
@@ -315,7 +316,7 @@ pub struct cleanup_path {
 pub fn shrink_scope_clean(scope_info: &mut ScopeInfo, size: uint) {
     scope_info.landing_pad = None;
     scope_info.cleanup_paths = scope_info.cleanup_paths.iter()
-            .take_while(|&cu| cu.size <= size).transform(|&x|x).collect();
+            .take_while(|&cu| cu.size <= size).map(|&x|x).collect();
 }
 
 pub fn grow_scope_clean(scope_info: &mut ScopeInfo) {
@@ -707,7 +708,7 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
 
 pub fn C_floating(s: &str, t: Type) -> ValueRef {
     unsafe {
-        do s.as_c_str |buf| {
+        do s.to_c_str().with_ref |buf| {
             llvm::LLVMConstRealOfString(t.to_ref(), buf)
         }
     }
@@ -755,12 +756,12 @@ pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef {
             None => ()
         }
 
-        let sc = do s.as_c_str |buf| {
+        let sc = do s.to_c_str().with_ref |buf| {
             llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint, False)
         };
 
         let gsym = token::gensym("str");
-        let g = do fmt!("str%u", gsym).as_c_str |buf| {
+        let g = do fmt!("str%u", gsym).to_c_str().with_ref |buf| {
             llvm::LLVMAddGlobal(cx.llmod, val_ty(sc).to_ref(), buf)
         };
         llvm::LLVMSetInitializer(g, sc);
@@ -779,7 +780,7 @@ pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef {
     unsafe {
         let len = s.len();
         let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p().to_ref());
-        C_struct([cs, C_uint(cx, len + 1u /* +1 for null */)])
+        C_struct([cs, C_uint(cx, len)])
     }
 }
 
@@ -999,7 +1000,7 @@ pub fn node_id_type_params(bcx: @mut Block, id: ast::NodeId) -> ~[ty::t] {
 
     match bcx.fcx.param_substs {
       Some(substs) => {
-        do params.iter().transform |t| {
+        do params.iter().map |t| {
             ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
         }.collect()
       }
@@ -1024,7 +1025,7 @@ pub fn resolve_vtables_under_param_substs(tcx: ty::ctxt,
                                           param_substs: Option<@param_substs>,
                                           vts: typeck::vtable_res)
     -> typeck::vtable_res {
-    @vts.iter().transform(|ds|
+    @vts.iter().map(|ds|
       resolve_param_vtables_under_param_substs(tcx,
                                                param_substs,
                                                *ds))
@@ -1036,7 +1037,7 @@ pub fn resolve_param_vtables_under_param_substs(
     param_substs: Option<@param_substs>,
     ds: typeck::vtable_param_res)
     -> typeck::vtable_param_res {
-    @ds.iter().transform(
+    @ds.iter().map(
         |d| resolve_vtable_under_param_substs(tcx,
                                               param_substs,
                                               d))
@@ -1062,7 +1063,7 @@ pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
         typeck::vtable_static(trait_id, ref tys, sub) => {
             let tys = match param_substs {
                 Some(substs) => {
-                    do tys.iter().transform |t| {
+                    do tys.iter().map |t| {
                         ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
                     }.collect()
                 }
index 40d0d77c16ecb11cfe39ddcc75bc86a059ba1823..1992d71427f2053baacc7413c310324c9602202e 100644 (file)
@@ -30,6 +30,7 @@
 
 use middle::trans::type_::Type;
 
+use std::c_str::ToCStr;
 use std::libc::c_uint;
 use syntax::{ast, ast_util, ast_map};
 
@@ -101,7 +102,7 @@ pub fn const_vec(cx: @mut CrateContext, e: &ast::expr, es: &[@ast::expr])
 
 fn const_addr_of(cx: &mut CrateContext, cv: ValueRef) -> ValueRef {
     unsafe {
-        let gv = do "const".as_c_str |name| {
+        let gv = do "const".to_c_str().with_ref |name| {
             llvm::LLVMAddGlobal(cx.llmod, val_ty(cv).to_ref(), name)
         };
         llvm::LLVMSetInitializer(gv, cv);
@@ -498,8 +499,8 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef {
               do expr::with_field_tys(tcx, ety, Some(e.id))
                   |discr, field_tys| {
                   let cs: ~[ValueRef] = field_tys.iter().enumerate()
-                      .transform(|(ix, &field_ty)| {
-                      match fs.iter().find_(|f| field_ty.ident == f.ident) {
+                      .map(|(ix, &field_ty)| {
+                      match fs.iter().find(|f| field_ty.ident == f.ident) {
                           Some(f) => const_expr(cx, (*f).expr),
                           None => {
                               match base_val {
@@ -527,7 +528,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef {
               ast::expr_vec(ref es, ast::m_imm) => {
                 let (cv, sz, llunitty) = const_vec(cx, e, *es);
                 let llty = val_ty(cv);
-                let gv = do "const".as_c_str |name| {
+                let gv = do "const".to_c_str().with_ref |name| {
                     llvm::LLVMAddGlobal(cx.llmod, llty.to_ref(), name)
                 };
                 llvm::LLVMSetInitializer(gv, cv);
index 56ba1ae1694b6684f3a02681c69318032d7abb36..a644174731ab47940b9c08e6484e4a9468d73ebe 100644 (file)
@@ -26,6 +26,7 @@
 
 use middle::trans::type_::Type;
 
+use std::c_str::ToCStr;
 use std::hash;
 use std::hashmap::{HashMap, HashSet};
 use std::local_data;
@@ -124,11 +125,17 @@ pub fn new(sess: session::Session,
         unsafe {
             let llcx = llvm::LLVMContextCreate();
             set_task_llcx(llcx);
-            let llmod = name.as_c_str(|buf| llvm::LLVMModuleCreateWithNameInContext(buf, llcx));
+            let llmod = do name.to_c_str().with_ref |buf| {
+                llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
+            };
             let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
             let targ_triple: &str = sess.targ_cfg.target_strs.target_triple;
-            data_layout.as_c_str(|buf| llvm::LLVMSetDataLayout(llmod, buf));
-            targ_triple.as_c_str(|buf| llvm::LLVMSetTarget(llmod, buf));
+            do data_layout.to_c_str().with_ref |buf| {
+                llvm::LLVMSetDataLayout(llmod, buf)
+            };
+            do targ_triple.to_c_str().with_ref |buf| {
+                llvm::LLVMSetTarget(llmod, buf)
+            };
             let targ_cfg = sess.targ_cfg;
 
             let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
index 823b1e0645cbcccc3a52dd5b3d52ef01f57705de..46eb3928d595eb956d7998ebb09f762b5e2abe34 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::c_str::ToCStr;
 
 use back::link;
 use lib;
@@ -240,7 +241,7 @@ pub fn trans_log(log_ex: &ast::expr,
             ccx, modpath, "loglevel");
         let global;
         unsafe {
-            global = do s.as_c_str |buf| {
+            global = do s.to_c_str().with_ref |buf| {
                 llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
             };
             llvm::LLVMSetGlobalConstant(global, False);
index 624704c2c686c540c4457df43a9a9ab57be13154..1fb64d9c67130066722789673447d9139fd1b3ca 100644 (file)
@@ -63,6 +63,7 @@
 use middle::pat_util;
 use util::ppaux::ty_to_str;
 
+use std::c_str::ToCStr;
 use std::hashmap::HashMap;
 use std::libc::{c_uint, c_ulonglong, c_longlong};
 use std::ptr;
@@ -159,7 +160,7 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
         let ty = node_id_type(bcx, node_id);
         let type_metadata = type_metadata(cx, ty, span);
 
-        let var_metadata = do name.as_c_str |name| {
+        let var_metadata = do name.to_c_str().with_ref |name| {
             unsafe {
                 llvm::LLVMDIBuilderCreateLocalVariable(
                     DIB(cx),
@@ -246,7 +247,7 @@ pub fn create_argument_metadata(bcx: @mut Block,
             argument_index as c_uint
         };
 
-        let arg_metadata = do name.as_c_str |name| {
+        let arg_metadata = do name.to_c_str().with_ref |name| {
             unsafe {
                 llvm::LLVMDIBuilderCreateLocalVariable(
                     DIB(cx),
@@ -382,8 +383,8 @@ pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
     };
 
     let fn_metadata =
-        do cx.sess.str_of(ident).as_c_str |name| {
-        do cx.sess.str_of(ident).as_c_str |linkage| {
+        do cx.sess.str_of(ident).to_c_str().with_ref |name| {
+        do cx.sess.str_of(ident).to_c_str().with_ref |linkage| {
             unsafe {
                 llvm::LLVMDIBuilderCreateFunction(
                     DIB(cx),
@@ -430,11 +431,11 @@ fn compile_unit_metadata(cx: @mut CrateContext) {
     let work_dir = cx.sess.working_dir.to_str();
     let producer = fmt!("rustc version %s", env!("CFG_VERSION"));
 
-    do crate_name.as_c_str |crate_name| {
-    do work_dir.as_c_str |work_dir| {
-    do producer.as_c_str |producer| {
-    do "".as_c_str |flags| {
-    do "".as_c_str |split_name| {
+    do crate_name.to_c_str().with_ref |crate_name| {
+    do work_dir.to_c_str().with_ref |work_dir| {
+    do producer.to_c_str().with_ref |producer| {
+    do "".to_c_str().with_ref |flags| {
+    do "".to_c_str().with_ref |split_name| {
         unsafe {
             llvm::LLVMDIBuilderCreateCompileUnit(dcx.builder,
                 DW_LANG_RUST as c_uint, crate_name, work_dir, producer,
@@ -461,8 +462,8 @@ fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
         };
 
     let file_metadata =
-        do file_name.as_c_str |file_name| {
-        do work_dir.as_c_str |work_dir| {
+        do file_name.to_c_str().with_ref |file_name| {
+        do work_dir.to_c_str().with_ref |work_dir| {
             unsafe {
                 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
             }
@@ -550,7 +551,7 @@ fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
 
     let llvm_type = type_of::type_of(cx, t);
     let (size, align) = size_and_align_of(cx, llvm_type);
-    let ty_metadata = do name.as_c_str |name| {
+    let ty_metadata = do name.to_c_str().with_ref |name| {
         unsafe {
             llvm::LLVMDIBuilderCreateBasicType(
                 DIB(cx),
@@ -571,7 +572,7 @@ fn pointer_type_metadata(cx: &mut CrateContext,
     let pointer_llvm_type = type_of::type_of(cx, pointer_type);
     let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
     let name = ty_to_str(cx.tcx, pointer_type);
-    let ptr_metadata = do name.as_c_str |name| {
+    let ptr_metadata = do name.to_c_str().with_ref |name| {
         unsafe {
             llvm::LLVMDIBuilderCreatePointerType(
                 DIB(cx),
@@ -661,11 +662,11 @@ fn enum_metadata(cx: &mut CrateContext,
 
     let enumerators_metadata: ~[DIDescriptor] = variants
         .iter()
-        .transform(|v| {
+        .map(|v| {
             let name: &str = cx.sess.str_of(v.name);
             let discriminant_value = v.disr_val as c_ulonglong;
 
-            do name.as_c_str |name| {
+            do name.to_c_str().with_ref |name| {
                 unsafe {
                     llvm::LLVMDIBuilderCreateEnumerator(
                         DIB(cx),
@@ -679,7 +680,7 @@ fn enum_metadata(cx: &mut CrateContext,
     let loc = span_start(cx, span);
     let file_metadata = file_metadata(cx, loc.file.name);
 
-    let discriminant_type_metadata = do enum_name.as_c_str |enum_name| {
+    let discriminant_type_metadata = do enum_name.to_c_str().with_ref |enum_name| {
         unsafe {
             llvm::LLVMDIBuilderCreateEnumerationType(
                 DIB(cx),
@@ -708,7 +709,7 @@ fn enum_metadata(cx: &mut CrateContext,
             let variants_member_metadata: ~[DIDescriptor] = do struct_defs
                 .iter()
                 .enumerate()
-                .transform |(i, struct_def)| {
+                .map |(i, struct_def)| {
                     let variant_type_metadata = adt_struct_metadata(
                         cx,
                         struct_def,
@@ -716,7 +717,7 @@ fn enum_metadata(cx: &mut CrateContext,
                         Some(discriminant_type_metadata),
                         span);
 
-                    do "".as_c_str |name| {
+                    do "".to_c_str().with_ref |name| {
                         unsafe {
                             llvm::LLVMDIBuilderCreateMemberType(
                                 DIB(cx),
@@ -736,7 +737,7 @@ fn enum_metadata(cx: &mut CrateContext,
             let enum_llvm_type = type_of::type_of(cx, enum_type);
             let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
 
-            return do enum_name.as_c_str |enum_name| {
+            return do enum_name.to_c_str().with_ref |enum_name| {
                 unsafe {
                     llvm::LLVMDIBuilderCreateUnionType(
                     DIB(cx),
@@ -765,7 +766,7 @@ fn adt_struct_metadata(cx: &mut CrateContext,
     {
         let arg_llvm_types: ~[Type] = do struct_def.fields.map |&ty| { type_of::type_of(cx, ty) };
         let arg_metadata: ~[DIType] = do struct_def.fields.iter().enumerate()
-            .transform |(i, &ty)| {
+            .map |(i, &ty)| {
                 match discriminant_type_metadata {
                     Some(metadata) if i == 0 => metadata,
                     _                        => type_metadata(cx, ty, span)
@@ -815,12 +816,12 @@ fn composite_type_metadata(cx: &mut CrateContext,
     let member_metadata: ~[DIDescriptor] = member_llvm_types
         .iter()
         .enumerate()
-        .transform(|(i, &member_llvm_type)| {
+        .map(|(i, &member_llvm_type)| {
             let (member_size, member_align) = size_and_align_of(cx, member_llvm_type);
             let member_offset = machine::llelement_offset(cx, composite_llvm_type, i);
             let member_name: &str = member_names[i];
 
-            do member_name.as_c_str |member_name| {
+            do member_name.to_c_str().with_ref |member_name| {
                 unsafe {
                     llvm::LLVMDIBuilderCreateMemberType(
                         DIB(cx),
@@ -838,7 +839,7 @@ fn composite_type_metadata(cx: &mut CrateContext,
         })
         .collect();
 
-    return do composite_type_name.as_c_str |name| {
+    return do composite_type_name.to_c_str().with_ref |name| {
         unsafe {
             llvm::LLVMDIBuilderCreateStructType(
                 DIB(cx),
@@ -1064,7 +1065,7 @@ fn unimplemented_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
     debug!("unimplemented_type_metadata: %?", ty::get(t));
 
     let name = ty_to_str(cx.tcx, t);
-    let metadata = do fmt!("NYI<%s>", name).as_c_str |name| {
+    let metadata = do fmt!("NYI<%s>", name).to_c_str().with_ref |name| {
         unsafe {
             llvm::LLVMDIBuilderCreateBasicType(
                 DIB(cx),
index a44f93214881b3b7e0898e19f70488f4148a701d..5931b54342f33e4d50e4c82ef7b13c122f546ff8 100644 (file)
@@ -582,7 +582,7 @@ fn trans_rvalue_dps_unadjusted(bcx: @mut Block, expr: @ast::expr,
         ast::expr_tup(ref args) => {
             let repr = adt::represent_type(bcx.ccx(), expr_ty(bcx, expr));
             let numbered_fields: ~[(uint, @ast::expr)] =
-                args.iter().enumerate().transform(|(i, arg)| (i, *arg)).collect();
+                args.iter().enumerate().map(|(i, arg)| (i, *arg)).collect();
             return trans_adt(bcx, repr, 0, numbered_fields, None, dest);
         }
         ast::expr_lit(@codemap::spanned {node: ast::lit_str(s), _}) => {
@@ -849,7 +849,6 @@ fn trans_index(bcx: @mut Block,
 
         let _icx = push_ctxt("trans_index");
         let ccx = bcx.ccx();
-        let base_ty = expr_ty(bcx, base);
         let mut bcx = bcx;
 
         let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base));
@@ -879,12 +878,6 @@ fn trans_index(bcx: @mut Block,
         let (bcx, base, len) =
             base_datum.get_vec_base_and_len(bcx, index_expr.span,
                                             index_expr.id, 0);
-        let mut len = len;
-
-        if ty::type_is_str(base_ty) {
-            // acccount for null terminator in the case of string
-            len = Sub(bcx, len, C_uint(bcx.ccx(), 1u));
-        }
 
         debug!("trans_index: base %s", bcx.val_to_str(base));
         debug!("trans_index: len %s", bcx.val_to_str(len));
@@ -943,7 +936,7 @@ fn get_val(bcx: @mut Block, did: ast::def_id, const_ty: ty::t)
                             let symbol = csearch::get_symbol(
                                 bcx.ccx().sess.cstore,
                                 did);
-                            let llval = do symbol.as_c_str |buf| {
+                            let llval = do symbol.to_c_str().with_ref |buf| {
                                 llvm::LLVMAddGlobal(bcx.ccx().llmod,
                                                     llty.to_ref(),
                                                     buf)
index 948c9ceef8e6182da8188e5f6eb048ef556647cc..a70b907f2628cc4090eb86174f16cb51a7543aed 100644 (file)
@@ -37,6 +37,7 @@
 
 use middle::trans::type_::Type;
 
+use std::c_str::ToCStr;
 use std::libc::c_uint;
 use syntax::ast;
 
@@ -659,7 +660,7 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
     let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
     note_unique_llvm_symbol(ccx, name);
     debug!("+++ declare_tydesc %s %s", ppaux::ty_to_str(ccx.tcx, t), name);
-    let gvar = do name.as_c_str |buf| {
+    let gvar = do name.to_c_str().with_ref |buf| {
         unsafe {
             llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type.to_ref(), buf)
         }
index 9be01ef1db94f639da751f44bb3ed3ef253e31bd..4cc4f8fa696d0cb1b92f5b6257351636f614a142 100644 (file)
@@ -32,6 +32,7 @@
 
 use middle::trans::type_::Type;
 
+use std::c_str::ToCStr;
 use std::vec;
 use syntax::ast_map::{path, path_mod, path_name};
 use syntax::ast_util;
@@ -287,7 +288,7 @@ pub fn method_with_name(ccx: &mut CrateContext,
 
     let imp = ccx.tcx.impls.find(&impl_id)
         .expect("could not find impl while translating");
-    let meth = imp.methods.iter().find_(|m| m.ident == name)
+    let meth = imp.methods.iter().find(|m| m.ident == name)
         .expect("could not find method while translating");
 
     ccx.impl_method_cache.insert((impl_id, name), meth.def_id);
@@ -604,7 +605,7 @@ pub fn make_vtable(ccx: &mut CrateContext,
 
         let tbl = C_struct(components);
         let vtable = ccx.sess.str_of(gensym_name("vtable"));
-        let vt_gvar = do vtable.as_c_str |buf| {
+        let vt_gvar = do vtable.to_c_str().with_ref |buf| {
             llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl).to_ref(), buf)
         };
         llvm::LLVMSetInitializer(vt_gvar, tbl);
index d47d9a4ff1628b63d5f51a57c7cbb1722595ead5..387a8ecc5eec60a6d39392bc4784b5104618281d 100644 (file)
@@ -42,3 +42,5 @@
 pub mod adt;
 pub mod asm;
 pub mod type_;
+pub mod value;
+pub mod basic_block;
index 5f8837b538cdfbd8b0b9992fc47c26713c21696a..21ef9058069ab3154c5a3a0be766166b92b56fa2 100644 (file)
@@ -245,7 +245,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
       }
       ast_map::node_variant(ref v, enum_item, _) => {
         let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
-        let this_tv = *tvs.iter().find_(|tv| { tv.id.node == fn_id.node}).unwrap();
+        let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
         let d = mk_lldecl();
         set_inline_hint(d);
         match v.node.kind {
@@ -366,18 +366,18 @@ pub fn make_mono_id(ccx: @mut CrateContext,
                     param_uses: Option<@~[type_use::type_uses]>) -> mono_id {
     // FIXME (possibly #5801): Need a lot of type hints to get
     // .collect() to work.
-    let substs_iter = substs.self_ty.iter().chain_(substs.tys.iter());
+    let substs_iter = substs.self_ty.iter().chain(substs.tys.iter());
     let precise_param_ids: ~[(ty::t, Option<@~[mono_id]>)] = match substs.vtables {
       Some(vts) => {
         debug!("make_mono_id vtables=%s substs=%s",
                vts.repr(ccx.tcx), substs.tys.repr(ccx.tcx));
-        let vts_iter = substs.self_vtables.iter().chain_(vts.iter());
-        vts_iter.zip(substs_iter).transform(|(vtable, subst)| {
+        let vts_iter = substs.self_vtables.iter().chain(vts.iter());
+        vts_iter.zip(substs_iter).map(|(vtable, subst)| {
             let v = vtable.map(|vt| meth::vtable_id(ccx, vt));
             (*subst, if !v.is_empty() { Some(@v) } else { None })
         }).collect()
       }
-      None => substs_iter.transform(|subst| (*subst, None::<@~[mono_id]>)).collect()
+      None => substs_iter.map(|subst| (*subst, None::<@~[mono_id]>)).collect()
     };
 
 
@@ -387,9 +387,9 @@ pub fn make_mono_id(ccx: @mut CrateContext,
         // We just say it is fully used.
         let self_use =
             substs.self_ty.map(|_| type_use::use_repr|type_use::use_tydesc);
-        let uses_iter = self_use.iter().chain_(uses.iter());
+        let uses_iter = self_use.iter().chain(uses.iter());
 
-        precise_param_ids.iter().zip(uses_iter).transform(|(id, uses)| {
+        precise_param_ids.iter().zip(uses_iter).map(|(id, uses)| {
             if ccx.sess.no_monomorphic_collapse() {
                 match *id {
                     (a, b) => mono_precise(a, b)
@@ -429,7 +429,7 @@ pub fn make_mono_id(ccx: @mut CrateContext,
         }).collect()
       }
       None => {
-          precise_param_ids.iter().transform(|x| {
+          precise_param_ids.iter().map(|x| {
               let (a, b) = *x;
               mono_precise(a, b)
           }).collect()
index 609aad0bc201cc514aef7e5f533a7b5c7b5d52af..e0403ac9ad7a800875bf1ba67726499031957fad 100644 (file)
@@ -58,7 +58,7 @@ pub fn c_slice(&mut self, s: @str) -> ValueRef {
         let str_vstore = ty::vstore_slice(ty::re_static);
         let str_ty = ty::mk_estr(bcx.tcx(), str_vstore);
         let scratch = scratch_datum(bcx, str_ty, "", false);
-        let len = C_uint(bcx.ccx(), s.len() + 1);
+        let len = C_uint(bcx.ccx(), s.len());
         let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), Type::i8p());
         Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ]));
         Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ]));
index 34404e49317b6d396ef0919f2df47ca2e51b6394..5b0e2fa18f240af3716c6604a6ae391512b18d5e 100644 (file)
@@ -265,7 +265,7 @@ pub fn trans_lit_str(bcx: @mut Block,
         Ignore => bcx,
         SaveIn(lldest) => {
             unsafe {
-                let bytes = str_lit.len() + 1; // count null-terminator too
+                let bytes = str_lit.len(); // count null-terminator too
                 let llbytes = C_uint(bcx.ccx(), bytes);
                 let llcstr = C_cstr(bcx.ccx(), str_lit);
                 let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p().to_ref());
@@ -363,7 +363,7 @@ pub fn write_content(bcx: @mut Block,
                     return bcx;
                 }
                 SaveIn(lldest) => {
-                    let bytes = s.len() + 1; // copy null-terminator too
+                    let bytes = s.len();
                     let llbytes = C_uint(bcx.ccx(), bytes);
                     let llcstr = C_cstr(bcx.ccx(), s);
                     base::call_memcpy(bcx, lldest, llcstr, llbytes, 1);
@@ -491,7 +491,7 @@ pub fn elements_required(bcx: @mut Block, content_expr: &ast::expr) -> uint {
 
     match content_expr.node {
         ast::expr_lit(@codemap::spanned { node: ast::lit_str(s), _ }) => {
-            s.len() + 1
+            s.len()
         },
         ast::expr_vec(ref es, _) => es.len(),
         ast::expr_repeat(_, count_expr, _) => {
@@ -524,7 +524,6 @@ pub fn get_base_and_len(bcx: @mut Block,
     match vstore {
         ty::vstore_fixed(n) => {
             let base = GEPi(bcx, llval, [0u, 0u]);
-            let n = if ty::type_is_str(vec_ty) { n + 1u } else { n };
             let len = Mul(bcx, C_uint(ccx, n), vt.llunit_size);
             (base, len)
         }
index 9bb7f9571f39f1775b5e3c9a32ba324a866edd83..110febfcc9f579b7080786fb98335b77c7f6a678 100644 (file)
@@ -20,6 +20,7 @@
 use syntax::ast;
 use syntax::abi::{Architecture, X86, X86_64, Arm, Mips};
 
+use std::c_str::ToCStr;
 use std::vec;
 use std::cast;
 
@@ -170,7 +171,7 @@ pub fn struct_(els: &[Type], packed: bool) -> Type {
 
     pub fn named_struct(name: &str) -> Type {
         let ctx = base::task_llcx();
-        ty!(name.as_c_str(|s| llvm::LLVMStructCreateNamed(ctx, s)))
+        ty!(name.to_c_str().with_ref(|s| llvm::LLVMStructCreateNamed(ctx, s)))
     }
 
     pub fn empty_struct() -> Type {
diff --git a/src/librustc/middle/trans/value.rs b/src/librustc/middle/trans/value.rs
new file mode 100644 (file)
index 0000000..08b2db6
--- /dev/null
@@ -0,0 +1,157 @@
+// 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 lib::llvm::{llvm, UseRef, ValueRef};
+use middle::trans::basic_block::BasicBlock;
+use middle::trans::common::Block;
+use std::libc::c_uint;
+
+pub struct Value(ValueRef);
+
+macro_rules! opt_val ( ($e:expr) => (
+    unsafe {
+        match $e {
+            p if p.is_not_null() => Some(Value(p)),
+            _ => None
+        }
+    }
+))
+
+/**
+ * Wrapper for LLVM ValueRef
+ */
+impl Value {
+    /// Returns the BasicBlock that contains this value
+    pub fn get_parent(self) -> Option<BasicBlock> {
+        unsafe {
+            match llvm::LLVMGetInstructionParent(*self) {
+                p if p.is_not_null() => Some(BasicBlock(p)),
+                _ => None
+            }
+        }
+    }
+
+    /// Removes this value from its containing BasicBlock
+    pub fn erase_from_parent(self) {
+        unsafe {
+            llvm::LLVMInstructionEraseFromParent(*self);
+        }
+    }
+
+    /// Returns the single dominating store to this value, if any
+    /// This only performs a search for a trivially dominating store. The store
+    /// must be the only user of this value, and there must not be any conditional
+    /// branches between the store and the given block.
+    pub fn get_dominating_store(self, bcx: @mut Block) -> Option<Value> {
+        match self.get_single_user().chain(|user| user.as_store_inst()) {
+            Some(store) => {
+                do store.get_parent().chain |store_bb| {
+                    let mut bb = BasicBlock(bcx.llbb);
+                    let mut ret = Some(store);
+                    while *bb != *store_bb {
+                        match bb.get_single_predecessor() {
+                            Some(pred) => bb = pred,
+                            None => { ret = None; break }
+                        }
+                    }
+                    ret
+                }
+            }
+            _ => None
+        }
+    }
+
+    /// Returns the first use of this value, if any
+    pub fn get_first_use(self) -> Option<Use> {
+        unsafe {
+            match llvm::LLVMGetFirstUse(*self) {
+                u if u.is_not_null() => Some(Use(u)),
+                _ => None
+            }
+        }
+    }
+
+    /// Tests if there are no uses of this value
+    pub fn has_no_uses(self) -> bool {
+        self.get_first_use().is_none()
+    }
+
+    /// Returns the single user of this value
+    /// If there are no users or multiple users, this returns None
+    pub fn get_single_user(self) -> Option<Value> {
+        let mut iter = self.user_iter();
+        match (iter.next(), iter.next()) {
+            (Some(first), None) => Some(first),
+            _ => None
+        }
+    }
+
+    /// Returns an iterator for the users of this value
+    pub fn user_iter(self) -> UserIterator {
+        UserIterator {
+            next: self.get_first_use()
+        }
+    }
+
+    /// Returns the requested operand of this instruction
+    /// Returns None, if there's no operand at the given index
+    pub fn get_operand(self, i: uint) -> Option<Value> {
+        opt_val!(llvm::LLVMGetOperand(*self, i as c_uint))
+    }
+
+    /// Returns the Store represent by this value, if any
+    pub fn as_store_inst(self) -> Option<Value> {
+        opt_val!(llvm::LLVMIsAStoreInst(*self))
+    }
+
+    /// Tests if this value is a terminator instruction
+    pub fn is_a_terminator_inst(self) -> bool {
+        unsafe {
+            llvm::LLVMIsATerminatorInst(*self).is_not_null()
+        }
+    }
+}
+
+pub struct Use(UseRef);
+
+/**
+ * Wrapper for LLVM UseRef
+ */
+impl Use {
+    pub fn get_user(self) -> Value {
+        unsafe {
+            Value(llvm::LLVMGetUser(*self))
+        }
+    }
+
+    pub fn get_next_use(self) -> Option<Use> {
+        unsafe {
+            match llvm::LLVMGetNextUse(*self) {
+                u if u.is_not_null() => Some(Use(u)),
+                _ => None
+            }
+        }
+    }
+}
+
+/// Iterator for the users of a value
+pub struct UserIterator {
+    priv next: Option<Use>
+}
+
+impl Iterator<Value> for UserIterator {
+    fn next(&mut self) -> Option<Value> {
+        let current = self.next;
+
+        self.next = do current.chain |u| { u.get_next_use() };
+
+        do current.map |u| { u.get_user() }
+    }
+}
index 849c35cdd2c038eec2662fbf09c77466a2edcfb0..bba5d85083b70ff6377b1f01b6417db10d485c8e 100644 (file)
@@ -3791,9 +3791,9 @@ pub fn substd_enum_variants(cx: ctxt,
                             id: ast::def_id,
                             substs: &substs)
                          -> ~[@VariantInfo] {
-    do enum_variants(cx, id).iter().transform |variant_info| {
+    do enum_variants(cx, id).iter().map |variant_info| {
         let substd_args = variant_info.args.iter()
-            .transform(|aty| subst(cx, substs, *aty)).collect();
+            .map(|aty| subst(cx, substs, *aty)).collect();
 
         let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
 
@@ -3935,7 +3935,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] {
                     _
                 }, _) => {
             let mut last_discriminant: Option<uint> = None;
-            @enum_definition.variants.iter().transform(|variant| {
+            @enum_definition.variants.iter().map(|variant| {
 
                 let mut discriminant = match last_discriminant {
                     Some(val) => val + 1,
@@ -4117,7 +4117,7 @@ pub fn lookup_struct_field(cx: ctxt,
                            field_id: ast::def_id)
                         -> field_ty {
     let r = lookup_struct_fields(cx, parent);
-    match r.iter().find_(
+    match r.iter().find(
                  |f| f.id.node == field_id.node) {
         Some(t) => *t,
         None => cx.sess.bug("struct ID not found in parent's fields")
index 750bd506f3e48583a66c7740b1aeb1806dba6d57..c666e98c9c15f5fab9ef218346b2bf538475af67 100644 (file)
@@ -724,7 +724,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Clone + 'static>(
         in_binding_rscope(rscope,
                           RegionParamNames(bound_lifetime_names.clone()));
 
-    let input_tys = do decl.inputs.iter().enumerate().transform |(i, a)| {
+    let input_tys = do decl.inputs.iter().enumerate().map |(i, a)| {
         let expected_arg_ty = do expected_sig.chain_ref |e| {
             // no guarantee that the correct number of expected args
             // were supplied
index ae0a95688ed20dfef1b5c1607283f9518d0cd8b3..84e5d8f9bf7430f3a27602f3a147db732f5e34db 100644 (file)
@@ -759,7 +759,7 @@ pub fn consider_candidates(&self,
                                -> Option<method_map_entry> {
         // XXX(pcwalton): Do we need to clone here?
         let relevant_candidates: ~[Candidate] =
-            candidates.iter().transform(|c| (*c).clone()).
+            candidates.iter().map(|c| (*c).clone()).
                 filter(|c| self.is_relevant(rcvr_ty, c)).collect();
 
         let relevant_candidates = self.merge_candidates(relevant_candidates);
index da0e219310fde2b64b3f325b892d7cd5d028acc5..8bc3241256875fb9ea6e80ec9a5887c89164dd7f 100644 (file)
@@ -1122,7 +1122,7 @@ pub fn lookup_field_ty(tcx: ty::ctxt,
                        fieldname: ast::ident,
                        substs: &ty::substs) -> Option<ty::t> {
 
-    let o_field = items.iter().find_(|f| f.ident == fieldname);
+    let o_field = items.iter().find(|f| f.ident == fieldname);
     do o_field.map() |f| {
         ty::lookup_field_type(tcx, class_id, f.id, substs)
     }
@@ -1818,7 +1818,7 @@ fn check_field(fcx: @mut FnCtxt,
             _ => ()
         }
 
-        let tps : ~[ty::t] = tys.iter().transform(|ty| fcx.to_ty(ty)).collect();
+        let tps : ~[ty::t] = tys.iter().map(|ty| fcx.to_ty(ty)).collect();
         match method::lookup(fcx,
                              expr,
                              base,
@@ -2644,7 +2644,7 @@ fn types_compatible(fcx: @mut FnCtxt, sp: span,
         let mut bot_field = false;
         let mut err_field = false;
 
-        let elt_ts = do elts.iter().enumerate().transform |(i, e)| {
+        let elt_ts = do elts.iter().enumerate().map |(i, e)| {
             let opt_hint = match flds {
                 Some(ref fs) if i < fs.len() => Some(fs[i]),
                 _ => None
index 700d96727eae2f9a0f3700e0a9f4c91b09c379df..37f4a6ba49737720cb64c19a1a5313d9818b9bf6 100644 (file)
@@ -100,7 +100,7 @@ fn lookup_vtables(vcx: &VtableContext,
     let mut result =
         substs.tps.rev_iter()
         .zip(type_param_defs.rev_iter())
-        .transform(|(ty, def)|
+        .map(|(ty, def)|
                    lookup_vtables_for_param(vcx, location_info, Some(substs),
                                             &*def.bounds, *ty, is_early))
         .to_owned_vec();
index c3df0d06f83dd5bd78499100c1b9093f962e8e45..b93f979894db707f1a38a64b721e53050426985f 100644 (file)
@@ -182,7 +182,7 @@ pub fn check_coherence(self, crate: &Crate) {
                     item_impl(_, ref opt_trait, _, _) => {
                         let opt_trait : ~[trait_ref] =
                             opt_trait.iter()
-                                     .transform(|x| (*x).clone())
+                                     .map(|x| (*x).clone())
                                      .collect();
                         self.check_implementation(item, opt_trait);
                     }
index 907a076b1a1efce000e622877195440379157c62..b5516fcc8eba6ed372992b8776740a8f5323a7c9 100644 (file)
@@ -675,7 +675,7 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
     // we'll catch it in coherence
     let trait_ms = ty::trait_methods(tcx, trait_ref.def_id);
     for impl_m in impl_ms.iter() {
-        match trait_ms.iter().find_(|trait_m| trait_m.ident == impl_m.mty.ident) {
+        match trait_ms.iter().find(|trait_m| trait_m.ident == impl_m.mty.ident) {
             Some(trait_m) => {
                 let num_impl_tps = generics.ty_params.len();
                 compare_impl_method(
@@ -731,7 +731,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
                     -> ~[ConvertedMethod]
 {
     let tcx = ccx.tcx;
-    return ms.iter().transform(|m| {
+    return ms.iter().map(|m| {
         let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs.len();
         let m_ty_generics =
             ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics,
index 5bc22db0ca1a76700fc93d12394c72ed7d0699d0..4cb6d7de0d3ddfdc3973bdcb395031edbade2684 100644 (file)
@@ -117,6 +117,7 @@ mod std {
 }
 */
 
+#[cfg(stage0)]
 pub fn version(argv0: &str) {
     let mut vers = ~"unknown version";
     let env_vers = env!("CFG_VERSION");
@@ -125,6 +126,16 @@ pub fn version(argv0: &str) {
     printfln!("host: %s", host_triple());
 }
 
+#[cfg(not(stage0))]
+pub fn version(argv0: &str) {
+    let vers = match option_env!("CFG_VERSION") {
+        Some(vers) => vers,
+        None => "unknown version"
+    };
+    printfln!("%s %s", argv0, vers);
+    printfln!("host: %s", host_triple());
+}
+
 pub fn usage(argv0: &str) {
     let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0);
     printfln!("%s\
@@ -145,8 +156,8 @@ pub fn describe_warnings() {
 ");
 
     let lint_dict = lint::get_lint_dict();
-    let mut lint_dict = lint_dict.consume()
-                                 .transform(|(k, v)| (v, k))
+    let mut lint_dict = lint_dict.move_iter()
+                                 .map(|(k, v)| (v, k))
                                  .collect::<~[(lint::LintSpec, &'static str)]>();
     lint_dict.qsort();
 
@@ -162,7 +173,7 @@ fn padded(max: uint, s: &str) -> ~str {
               padded(max_key, "name"), "default", "meaning");
     printfln!("    %s  %7.7s  %s\n",
               padded(max_key, "----"), "-------", "-------");
-    for (spec, name) in lint_dict.consume_iter() {
+    for (spec, name) in lint_dict.move_iter() {
         let name = name.replace("_", "-");
         printfln!("    %s  %7.7s  %s",
                   padded(max_key, name),
@@ -301,7 +312,7 @@ pub fn monitor(f: ~fn(diagnostic::Emitter)) {
 
     // XXX: This is a hack for newsched since it doesn't support split stacks.
     // rustc needs a lot of stack!
-    static STACK_SIZE: uint = 4000000;
+    static STACK_SIZE: uint = 6000000;
 
     let (p, ch) = stream();
     let ch = SharedChan::new(ch);
index f8eff69cc8f3e978b391a0961421afd6748586bd..ce8d1977443f81f6ab73189748c7829643589cde 100644 (file)
@@ -27,7 +27,7 @@ pub struct CrateAttrs {
 fn doc_metas(attrs: ~[ast::Attribute]) -> ~[@ast::MetaItem] {
     attrs.iter()
         .filter(|at| "doc" == at.name())
-        .transform(|at| at.desugar_doc().meta())
+        .map(|at| at.desugar_doc().meta())
         .collect()
 }
 
@@ -41,7 +41,7 @@ pub fn parse_crate(attrs: ~[ast::Attribute]) -> CrateAttrs {
 }
 
 pub fn parse_desc(attrs: ~[ast::Attribute]) -> Option<~str> {
-    let doc_strs = do doc_metas(attrs).consume_iter().filter_map |meta| {
+    let doc_strs = do doc_metas(attrs).move_iter().filter_map |meta| {
         meta.value_str()
     }.collect::<~[@str]>();
     if doc_strs.is_empty() {
index a1cb81f4503579eae39d6c34a9f13c9728dbbfcd..b5503cc51e10ce755dda2345e6e32c6effd2ce24 100644 (file)
@@ -123,7 +123,7 @@ fn fold_enum(
     let doc = fold::default_seq_fold_enum(fold, doc);
 
     doc::EnumDoc {
-        variants: do doc.variants.iter().transform |variant| {
+        variants: do doc.variants.iter().map |variant| {
             let variant = (*variant).clone();
             let desc = {
                 let variant = variant.clone();
@@ -133,7 +133,7 @@ fn fold_enum(
                             node: ast::item_enum(ref enum_definition, _), _
                         }, _) => {
                             let ast_variant =
-                                (*enum_definition.variants.iter().find_(|v| {
+                                (*enum_definition.variants.iter().find(|v| {
                                     to_str(v.node.name) == variant.name
                                 }).unwrap()).clone();
 
@@ -182,7 +182,7 @@ fn merge_method_attrs(
             ast_map::node_item(@ast::item {
                 node: ast::item_trait(_, _, ref methods), _
             }, _) => {
-                methods.iter().transform(|method| {
+                methods.iter().map(|method| {
                     match (*method).clone() {
                         ast::required(ty_m) => {
                             (to_str(ty_m.ident),
@@ -197,7 +197,7 @@ fn merge_method_attrs(
             ast_map::node_item(@ast::item {
                 node: ast::item_impl(_, _, _, ref methods), _
             }, _) => {
-                methods.iter().transform(|method| {
+                methods.iter().map(|method| {
                     (to_str(method.ident),
                      attr_parser::parse_desc(method.attrs.clone()))
                 }).collect()
@@ -206,7 +206,7 @@ fn merge_method_attrs(
         }
     };
 
-    do docs.iter().zip(attrs.iter()).transform |(doc, attrs)| {
+    do docs.iter().zip(attrs.iter()).map |(doc, attrs)| {
         assert!(doc.name == attrs.first());
         let desc = attrs.second();
 
index 3598eb7c0fb9b217d8af908ae888c112567382b1..877338902cc07ebf4e6b596c7d0fbcf3315708b8 100644 (file)
@@ -221,7 +221,7 @@ pub fn maybe_find_pandoc(
       }
     };
 
-    let pandoc = do possible_pandocs.iter().find_ |&pandoc| {
+    let pandoc = do possible_pandocs.iter().find |&pandoc| {
         let output = process_output(*pandoc, [~"--version"]);
         debug!("testing pandoc cmd %s: %?", *pandoc, output);
         output.status == 0
index 2cab62296a4ddbdec2d051013ee1dde305bca2fd..55552924d4461575ba32aaca38b54f32af6527db 100644 (file)
@@ -185,7 +185,7 @@ fn enumdoc_from_enum(
 fn variantdocs_from_variants(
     variants: ~[ast::variant]
 ) -> ~[doc::VariantDoc] {
-    variants.iter().transform(variantdoc_from_variant).collect()
+    variants.iter().map(variantdoc_from_variant).collect()
 }
 
 fn variantdoc_from_variant(variant: &ast::variant) -> doc::VariantDoc {
@@ -202,7 +202,7 @@ fn traitdoc_from_trait(
 ) -> doc::TraitDoc {
     doc::TraitDoc {
         item: itemdoc,
-        methods: do methods.iter().transform |method| {
+        methods: do methods.iter().map |method| {
             match (*method).clone() {
               ast::required(ty_m) => {
                 doc::MethodDoc {
@@ -238,7 +238,7 @@ fn impldoc_from_impl(
         bounds_str: None,
         trait_types: ~[],
         self_ty: None,
-        methods: do methods.iter().transform |method| {
+        methods: do methods.iter().map |method| {
             doc::MethodDoc {
                 name: to_str(method.ident),
                 brief: None,
index 589232f6e2f2f3cc447c2df44d5c770f8e0b6bf3..3e74916228f00f046c034e73b94dbeabbea741cb 100644 (file)
@@ -153,7 +153,7 @@ pub fn default_par_fold<T:Clone>(ctxt: T) -> Fold<T> {
 
 pub fn default_seq_fold_doc<T>(fold: &Fold<T>, doc: doc::Doc) -> doc::Doc {
     doc::Doc {
-        pages: do doc.pages.iter().transform |page| {
+        pages: do doc.pages.iter().map |page| {
             match (*page).clone() {
               doc::CratePage(doc) => {
                 doc::CratePage((fold.fold_crate)(fold, doc))
@@ -189,7 +189,7 @@ pub fn default_any_fold_mod<T:Clone>(
 ) -> doc::ModDoc {
     doc::ModDoc {
         item: (fold.fold_item)(fold, doc.item.clone()),
-        items: doc.items.iter().transform(|ItemTag| {
+        items: doc.items.iter().map(|ItemTag| {
             fold_ItemTag(fold, (*ItemTag).clone())
         }).collect(),
         .. doc
@@ -202,7 +202,7 @@ pub fn default_seq_fold_mod<T>(
 ) -> doc::ModDoc {
     doc::ModDoc {
         item: (fold.fold_item)(fold, doc.item.clone()),
-        items: doc.items.iter().transform(|ItemTag| {
+        items: doc.items.iter().map(|ItemTag| {
             fold_ItemTag(fold, (*ItemTag).clone())
         }).collect(),
         .. doc
@@ -215,7 +215,7 @@ pub fn default_par_fold_mod<T:Clone>(
 ) -> doc::ModDoc {
     doc::ModDoc {
         item: (fold.fold_item)(fold, doc.item.clone()),
-        items: doc.items.iter().transform(|ItemTag| {
+        items: doc.items.iter().map(|ItemTag| {
             fold_ItemTag(fold, (*ItemTag).clone())
         }).collect(),
         .. doc
@@ -228,7 +228,7 @@ pub fn default_any_fold_nmod<T:Clone>(
 ) -> doc::NmodDoc {
     doc::NmodDoc {
         item: (fold.fold_item)(fold, doc.item.clone()),
-        fns: doc.fns.iter().transform(|FnDoc| {
+        fns: doc.fns.iter().map(|FnDoc| {
             (fold.fold_fn)(fold, (*FnDoc).clone())
         }).collect(),
         .. doc
@@ -241,7 +241,7 @@ pub fn default_seq_fold_nmod<T>(
 ) -> doc::NmodDoc {
     doc::NmodDoc {
         item: (fold.fold_item)(fold, doc.item.clone()),
-        fns: doc.fns.iter().transform(|FnDoc| {
+        fns: doc.fns.iter().map(|FnDoc| {
             (fold.fold_fn)(fold, (*FnDoc).clone())
         }).collect(),
         .. doc
@@ -254,7 +254,7 @@ pub fn default_par_fold_nmod<T:Clone>(
 ) -> doc::NmodDoc {
     doc::NmodDoc {
         item: (fold.fold_item)(fold, doc.item.clone()),
-        fns: doc.fns.iter().transform(|FnDoc| {
+        fns: doc.fns.iter().map(|FnDoc| {
             (fold.fold_fn)(fold, (*FnDoc).clone())
         }).collect(),
         .. doc
index 82a4724496dd189f8f6eb3b2f6f3a12285907afc..342c949e3fc60957ba507c0d7105ae7394117efc 100644 (file)
@@ -123,7 +123,7 @@ fn strip_mod(doc: doc::ModDoc) -> doc::ModDoc {
               doc::ModTag(_) | doc::NmodTag(_) => false,
               _ => true
             }
-        }.transform(|x| (*x).clone()).collect::<~[doc::ItemTag]>(),
+        }.map(|x| (*x).clone()).collect::<~[doc::ItemTag]>(),
         .. doc.clone()
     }
 }
index 04cb0e3f71076f55efb87225dd697eea1dbcbdf1..9dc2f43f7ac92451e98811920fa1141603204f87 100644 (file)
@@ -43,7 +43,7 @@ fn fold_mod(
     doc::ModDoc {
         items: do doc.items.iter().filter |item_tag| {
             !is_hidden(fold.ctxt.clone(), item_tag.item())
-        }.transform(|x| (*x).clone()).collect(),
+        }.map(|x| (*x).clone()).collect(),
         .. doc
     }
 }
index 3e380732d0f07e87aaff5be5ff76c00d5813524d..e1bc059e20f9cc6b23bab4a4319b0c0c60885f37 100644 (file)
@@ -81,7 +81,7 @@ fn strip_priv_methods(
     item_vis: ast::visibility
 ) -> doc::ImplDoc {
     let methods = do doc.methods.iter().filter |method| {
-        let ast_method = do methods.iter().find_ |m| {
+        let ast_method = do methods.iter().find |m| {
             extract::to_str(m.ident) == method.name
         };
         assert!(ast_method.is_some());
@@ -91,7 +91,7 @@ fn strip_priv_methods(
             ast::private => false,
             ast::inherited => item_vis == ast::public
         }
-    }.transform(|x| (*x).clone()).collect();
+    }.map(|x| (*x).clone()).collect();
 
     doc::ImplDoc {
         methods: methods,
@@ -126,7 +126,7 @@ fn fold_mod(
                     is_visible(fold.ctxt.clone(), item_tag.item())
                 }
             }
-        }).transform(|x| (*x).clone()).collect(),
+        }).map(|x| (*x).clone()).collect(),
         .. doc
     }
 }
index 196c7e892a8801e90b04cceb87eac3d3af7d636e..aa4407af76d2e2ba00bc21d220b6cc6d2d0ae893 100644 (file)
@@ -124,7 +124,7 @@ fn fold_enum(
     let srv = fold.ctxt.clone();
 
     doc::EnumDoc {
-        variants: do doc.variants.iter().transform |variant| {
+        variants: do doc.variants.iter().map |variant| {
             let sig = {
                 let variant = (*variant).clone();
                 do astsrv::exec(srv.clone()) |ctxt| {
@@ -133,7 +133,7 @@ fn fold_enum(
                             node: ast::item_enum(ref enum_definition, _), _
                         }, _) => {
                             let ast_variant =
-                                (*do enum_definition.variants.iter().find_ |v| {
+                                (*do enum_definition.variants.iter().find |v| {
                                 to_str(v.node.name) == variant.name
                             }.unwrap()).clone();
 
@@ -169,7 +169,7 @@ fn merge_methods(
     item_id: doc::AstId,
     docs: ~[doc::MethodDoc]
 ) -> ~[doc::MethodDoc] {
-    do docs.iter().transform |doc| {
+    do docs.iter().map |doc| {
         doc::MethodDoc {
             sig: get_method_sig(srv.clone(), item_id, doc.name.clone()),
             .. (*doc).clone()
@@ -187,7 +187,7 @@ fn get_method_sig(
             ast_map::node_item(@ast::item {
                 node: ast::item_trait(_, _, ref methods), _
             }, _) => {
-                match methods.iter().find_(|&method| {
+                match methods.iter().find(|&method| {
                     match (*method).clone() {
                         ast::required(ty_m) => to_str(ty_m.ident) == method_name,
                         ast::provided(m) => to_str(m.ident) == method_name,
@@ -223,7 +223,7 @@ fn get_method_sig(
             ast_map::node_item(@ast::item {
                 node: ast::item_impl(_, _, _, ref methods), _
             }, _) => {
-                match methods.iter().find_(|method| {
+                match methods.iter().find(|method| {
                     to_str(method.ident) == method_name
                 }) {
                     Some(method) => {
index d8a640bc19cf9f5bb82fea42cf4b019d0e52f199..07af301260148db8fb0824d7b30c339716e7e6be 100644 (file)
@@ -167,7 +167,7 @@ fn main() {
         }
 
         let newvars = util::replace(&mut self.newvars, HashMap::new());
-        for (name, var) in newvars.consume() {
+        for (name, var) in newvars.move_iter() {
             self.local_vars.insert(name, var);
         }
 
@@ -233,7 +233,7 @@ pub fn set_cache(&self) {
     pub fn consume_cache(&mut self) {
         let map = local_data::pop(tls_key).expect("tls is empty");
         let cons_map = util::replace(map, HashMap::new());
-        for (name, value) in cons_map.consume() {
+        for (name, value) in cons_map.move_iter() {
             match self.local_vars.find_mut(&name) {
                 Some(v) => { v.data = (*value).clone(); }
                 None => { fail!("unknown variable %s", name) }
@@ -345,7 +345,7 @@ pub fn register_new_vars(&mut self, blk: &ast::Block, tcx: ty::ctxt) {
 
         // I'm not an @ pointer, so this has to be done outside.
         let cons_newvars = util::replace(newvars, HashMap::new());
-        for (k, v) in cons_newvars.consume() {
+        for (k, v) in cons_newvars.move_iter() {
             self.newvars.insert(k, v);
         }
 
index bb863df33481211c354b5519fb223be17cd2fe06..29ad9eb49a3b120526aff145cdd83f9172a50331 100644 (file)
@@ -315,7 +315,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
         // file, skip compilation and return None.
         let mut should_compile = true;
         let dir = os::list_dir_path(&Path(outputs.out_filename.dirname()));
-        let maybe_lib_path = do dir.iter().find_ |file| {
+        let maybe_lib_path = do dir.iter().find |file| {
             // The actual file's name has a hash value and version
             // number in it which is unknown at this time, so looking
             // for a file that matches out_filename won't work,
@@ -453,7 +453,7 @@ pub fn run_line(repl: &mut Repl, input: @io::Reader, out: @io::Writer, line: ~st
     if line.starts_with(":") {
         // drop the : and the \n (one byte each)
         let full = line.slice(1, line.len());
-        let split: ~[~str] = full.word_iter().transform(|s| s.to_owned()).collect();
+        let split: ~[~str] = full.word_iter().map(|s| s.to_owned()).collect();
         let len = split.len();
 
         if len > 0 {
index bcda135cbb666442746066a1c1bf10190fcd918d..2da66baa412b57914b7d27e535ffac99d36505dd 100644 (file)
@@ -23,33 +23,30 @@ fn default_ctxt(p: @Path) -> Ctx {
     Ctx { sysroot_opt: Some(p), json: false, dep_cache: @mut HashMap::new() }
 }
 
-pub fn build_lib(sysroot: @Path, root: Path, dest: Path, name: ~str, version: Version,
+pub fn build_lib(sysroot: @Path, root: Path, name: ~str, version: Version,
                  lib: Path) {
 
     let pkg_src = PkgSrc {
         root: root,
-        dst_dir: dest.clone(),
-        id: PkgId{ version: version, ..PkgId::new(name, &dest.pop())},
+        id: PkgId{ version: version, ..PkgId::new(name)},
         libs: ~[mk_crate(lib)],
         mains: ~[],
         tests: ~[],
         benchs: ~[]
     };
-    pkg_src.build(&default_ctxt(sysroot), pkg_src.dst_dir, ~[]);
+    pkg_src.build(&default_ctxt(sysroot), ~[]);
 }
 
-pub fn build_exe(sysroot: @Path, root: Path, dest: Path, name: ~str, version: Version,
-                 main: Path) {
+pub fn build_exe(sysroot: @Path, root: Path, name: ~str, version: Version, main: Path) {
     let pkg_src = PkgSrc {
         root: root,
-        dst_dir: dest.clone(),
-        id: PkgId{ version: version, ..PkgId::new(name, &dest.pop())},
+        id: PkgId{ version: version, ..PkgId::new(name)},
         libs: ~[],
         mains: ~[mk_crate(main)],
         tests: ~[],
         benchs: ~[]
     };
-    pkg_src.build(&default_ctxt(sysroot), pkg_src.dst_dir, ~[]);
+    pkg_src.build(&default_ctxt(sysroot), ~[]);
 
 }
 
@@ -62,12 +59,9 @@ pub fn install_lib(sysroot: @Path,
     debug!("sysroot = %s", sysroot.to_str());
     debug!("workspace = %s", workspace.to_str());
     // make a PkgSrc
-    let pkg_id = PkgId{ version: version, ..PkgId::new(name, &workspace)};
-    let build_dir = workspace.push("build");
-    let dst_dir = build_dir.push_rel(&*pkg_id.local_path);
+    let pkg_id = PkgId{ version: version, ..PkgId::new(name)};
     let pkg_src = PkgSrc {
         root: workspace.clone(),
-        dst_dir: dst_dir.clone(),
         id: pkg_id.clone(),
         libs: ~[mk_crate(lib_path)],
         mains: ~[],
@@ -75,13 +69,13 @@ pub fn install_lib(sysroot: @Path,
         benchs: ~[]
     };
     let cx = default_ctxt(sysroot);
-    pkg_src.build(&cx, dst_dir, ~[]);
+    pkg_src.build(&cx, ~[]);
     cx.install_no_build(&workspace, &pkg_id);
 }
 
 pub fn install_exe(sysroot: @Path, workspace: Path, name: ~str, version: Version) {
     default_ctxt(sysroot).install(&workspace, &PkgId{ version: version,
-                                            ..PkgId::new(name, &workspace)});
+                                            ..PkgId::new(name)});
 
 }
 
index 230a0f915ac31bc6854d300f36f1953ce286a82d..f051be25f266da111c12f204e41b992200fc0c2e 100644 (file)
@@ -12,6 +12,7 @@
 
 
 use std::hashmap::HashMap;
+use std::os;
 
 pub struct Ctx {
     // Sysroot -- if this is None, uses rustc filesearch's
@@ -23,3 +24,26 @@ pub struct Ctx {
     // though I'm not sure why the value is a bool
     dep_cache: @mut HashMap<~str, bool>,
 }
+
+impl Ctx {
+    /// Debugging
+    pub fn sysroot_opt_str(&self) -> ~str {
+        match self.sysroot_opt {
+            None => ~"[none]",
+            Some(p) => p.to_str()
+        }
+    }
+}
+
+/// We assume that if ../../rustc exists, then we're running
+/// rustpkg from a Rust target directory. This is part of a
+/// kludgy hack used to adjust the sysroot.
+pub fn in_target(sysroot_opt: Option<@Path>) -> bool {
+    match sysroot_opt {
+        None => false,
+        Some(p) => {
+            debug!("Checking whether %s is in target", p.to_str());
+            os::path_is_dir(&p.pop().pop().push("rustc"))
+        }
+    }
+}
index cec64f36947e024d58bcb641348e40ccdec00907..7c3cde655173b49454d8cdfaf4cd5138b73744f8 100644 (file)
@@ -10,6 +10,7 @@
 
 // Listing installed packages
 
+use rustc::metadata::filesearch::rust_path;
 use path_util::*;
 use std::os;
 
@@ -20,21 +21,46 @@ pub fn list_installed_packages(f: &fn(&PkgId) -> bool) -> bool  {
         for exec in binfiles.iter() {
             let exec_path = Path(*exec).filestem();
             do exec_path.iter().advance |s| {
-                f(&PkgId::new(*s, p))
+                f(&PkgId::new(*s))
             };
         }
         let libfiles = os::list_dir(&p.push("lib"));
         for lib in libfiles.iter() {
-            debug!("Full name: %s", *lib);
-            let lib_path = Path(*lib).filestem();
-            do lib_path.iter().advance |s| {
-                f(&PkgId::new(*s, p))
-            };
-        }
+            let lib = Path(*lib);
+            debug!("Full name: %s", lib.to_str());
+            match has_library(&lib) {
+                Some(basename) => {
+                    debug!("parent = %s, child = %s",
+                           p.push("lib").to_str(), lib.to_str());
+                    let rel_p = p.push("lib/").get_relative_to(&lib);
+                    debug!("Rel: %s", rel_p.to_str());
+                    let rel_path = rel_p.push(basename).to_str();
+                    debug!("Rel name: %s", rel_path);
+                    f(&PkgId::new(rel_path));
+                }
+                None => ()
+            }
+        };
     }
     true
 }
 
+pub fn has_library(p: &Path) -> Option<~str> {
+    let files = os::list_dir(p);
+    for q in files.iter() {
+        let as_path = Path(*q);
+        if as_path.filetype() == Some(os::consts::DLL_SUFFIX.to_owned()) {
+            let stuff : ~str = as_path.filestem().expect("has_library: weird path");
+            let mut stuff2 = stuff.split_str_iter(&"-");
+            let stuff3: ~[&str] = stuff2.collect();
+            // argh
+            let chars_to_drop = os::consts::DLL_PREFIX.len();
+            return Some(stuff3[0].slice(chars_to_drop, stuff3[0].len()).to_owned());
+        }
+    }
+    None
+}
+
 pub fn package_is_installed(p: &PkgId) -> bool {
     let mut is_installed = false;
     do list_installed_packages() |installed| {
@@ -44,4 +70,4 @@ pub fn package_is_installed(p: &PkgId) -> bool {
         false
     };
     is_installed
-}
\ No newline at end of file
+}
index e1cf5b1fd35c57139c4426c416a877ecfbf28d9e..e3b3252587a082662f9258e33f98885a3302cfa1 100644 (file)
@@ -8,33 +8,37 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use package_path::{RemotePath, LocalPath, normalize, hash};
 use version::{try_getting_version, try_getting_local_version,
               Version, NoVersion, split_version};
+use std::rt::io::Writer;
+use std::hash::Streaming;
+use std::hash;
 
 /// Path-fragment identifier of a package such as
 /// 'github.com/graydon/test'; path must be a relative
 /// path with >=1 component.
 #[deriving(Clone)]
 pub struct PkgId {
-    /// Remote path: for example, github.com/mozilla/quux-whatever
-    remote_path: RemotePath,
-    /// Local path: for example, /home/quux/github.com/mozilla/quux_whatever
-    /// Note that '-' normalizes to '_' when mapping a remote path
-    /// onto a local path
-    /// Also, this will change when we implement #6407, though we'll still
-    /// need to keep track of separate local and remote paths
-    local_path: LocalPath,
-    /// Short name. This is the local path's filestem, but we store it
+    /// This is a path, on the local filesystem, referring to where the
+    /// files for this package live. For example:
+    /// github.com/mozilla/quux-whatever (it's assumed that if we're
+    /// working with a package ID of this form, rustpkg has already cloned
+    /// the sources into a local directory in the RUST_PATH).
+    path: Path,
+    /// Short name. This is the path's filestem, but we store it
     /// redundantly so as to not call get() everywhere (filestem() returns an
     /// option)
+    /// The short name does not need to be a valid Rust identifier.
+    /// Users can write: `extern mod foo = "...";` to get around the issue
+    /// of package IDs whose short names aren't valid Rust identifiers.
     short_name: ~str,
+    /// The requested package version.
     version: Version
 }
 
 impl Eq for PkgId {
     fn eq(&self, p: &PkgId) -> bool {
-        *p.local_path == *self.local_path && p.version == self.version
+        p.path == self.path && p.version == self.version
     }
     fn ne(&self, p: &PkgId) -> bool {
         !(self.eq(p))
@@ -42,10 +46,7 @@ fn ne(&self, p: &PkgId) -> bool {
 }
 
 impl PkgId {
-    // The PkgId constructor takes a Path argument so as
-    // to be able to infer the version if the path refers
-    // to a local git repository
-    pub fn new(s: &str, work_dir: &Path) -> PkgId {
+    pub fn new(s: &str) -> PkgId {
         use conditions::bad_pkg_id::cond;
 
         let mut given_version = None;
@@ -63,51 +64,64 @@ pub fn new(s: &str, work_dir: &Path) -> PkgId {
             }
         };
 
-        let p = Path(s);
-        if p.is_absolute {
-            return cond.raise((p, ~"absolute pkgid"));
+        let path = Path(s);
+        if path.is_absolute {
+            return cond.raise((path, ~"absolute pkgid"));
         }
-        if p.components.len() < 1 {
-            return cond.raise((p, ~"0-length pkgid"));
+        if path.components.len() < 1 {
+            return cond.raise((path, ~"0-length pkgid"));
         }
-        let remote_path = RemotePath(p);
-        let local_path = normalize(remote_path.clone());
-        let short_name = local_path.clone().filestem().expect(fmt!("Strange path! %s", s));
+        let short_name = path.clone().filestem().expect(fmt!("Strange path! %s", s));
 
         let version = match given_version {
             Some(v) => v,
-            None => match try_getting_local_version(&work_dir.push_rel(&*local_path)) {
+            None => match try_getting_local_version(&path) {
                 Some(v) => v,
-                None => match try_getting_version(&remote_path) {
+                None => match try_getting_version(&path) {
                     Some(v) => v,
                     None => NoVersion
                 }
             }
         };
 
-        debug!("local_path = %s, remote_path = %s", local_path.to_str(), remote_path.to_str());
+        debug!("path = %s", path.to_str());
         PkgId {
-            local_path: local_path,
-            remote_path: remote_path,
+            path: path,
             short_name: short_name,
             version: version
         }
     }
 
     pub fn hash(&self) -> ~str {
-        fmt!("%s-%s-%s", self.remote_path.to_str(),
-             hash(self.remote_path.to_str() + self.version.to_str()),
+        fmt!("%s-%s-%s", self.path.to_str(),
+             hash(self.path.to_str() + self.version.to_str()),
              self.version.to_str())
     }
 
     pub fn short_name_with_version(&self) -> ~str {
         fmt!("%s%s", self.short_name, self.version.to_str())
     }
+
+    /// True if the ID has multiple components
+    pub fn is_complex(&self) -> bool {
+        self.short_name != self.path.to_str()
+     }
 }
 
 impl ToStr for PkgId {
     fn to_str(&self) -> ~str {
         // should probably use the filestem and not the whole path
-        fmt!("%s-%s", self.local_path.to_str(), self.version.to_str())
+        fmt!("%s-%s", self.path.to_str(), self.version.to_str())
     }
 }
+
+
+pub fn write<W: Writer>(writer: &mut W, string: &str) {
+    writer.write(string.as_bytes());
+}
+
+pub fn hash(data: ~str) -> ~str {
+    let hasher = &mut hash::default_state();
+    write(hasher, data);
+    hasher.result_str()
+}
diff --git a/src/librustpkg/package_path.rs b/src/librustpkg/package_path.rs
deleted file mode 100644 (file)
index 4ba9c80..0000000
+++ /dev/null
@@ -1,68 +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.
-
-// rustpkg utilities having to do with local and remote paths
-
-use std::clone::Clone;
-use std::hash::Streaming;
-use std::hash;
-use std::option::Some;
-use std::path::Path;
-use std::rt::io::Writer;
-
-/// Wrappers to prevent local and remote paths from getting confused
-/// (These will go away after #6407)
-pub struct RemotePath (Path);
-
-impl Clone for RemotePath {
-    fn clone(&self) -> RemotePath {
-        RemotePath((**self).clone())
-    }
-}
-
-pub struct LocalPath (Path);
-
-impl Clone for LocalPath {
-    fn clone(&self) -> LocalPath {
-        LocalPath((**self).clone())
-    }
-}
-
-
-// normalize should be the only way to construct a LocalPath
-// (though this isn't enforced)
-/// Replace all occurrences of '-' in the stem part of path with '_'
-/// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux
-/// as the same name
-pub fn normalize(p_: RemotePath) -> LocalPath {
-    let RemotePath(p) = p_;
-    match p.filestem() {
-        None => LocalPath(p),
-        Some(st) => {
-            let replaced = st.replace("-", "_");
-            if replaced != st {
-                LocalPath(p.with_filestem(replaced))
-            }
-            else {
-                LocalPath(p)
-            }
-        }
-    }
-}
-
-pub fn write<W: Writer>(writer: &mut W, string: &str) {
-    writer.write(string.as_bytes());
-}
-
-pub fn hash(data: ~str) -> ~str {
-    let hasher = &mut hash::default_state();
-    write(hasher, data);
-    hasher.result_str()
-}
index bbe35ee5004f6235aa5b90e9652376e2b4be1eb3..ff485342fbe9871f51b2189379191dcfa8d666fc 100644 (file)
@@ -11,7 +11,7 @@
 use target::*;
 use package_id::PkgId;
 use std::path::Path;
-use std::{os, str};
+use std::os;
 use context::*;
 use crate::Crate;
 use messages::*;
@@ -23,7 +23,6 @@
 // This contains a list of files found in the source workspace.
 pub struct PkgSrc {
     root: Path, // root of where the package source code lives
-    dst_dir: Path, // directory where we will put the compiled output
     id: PkgId,
     libs: ~[Crate],
     mains: ~[Crate],
@@ -37,11 +36,9 @@ pub struct PkgSrc {
 
 impl PkgSrc {
 
-    pub fn new(src_dir: &Path, dst_dir: &Path,
-                  id: &PkgId) -> PkgSrc {
+    pub fn new(src_dir: &Path, id: &PkgId) -> PkgSrc {
         PkgSrc {
             root: (*src_dir).clone(),
-            dst_dir: (*dst_dir).clone(),
             id: (*id).clone(),
             libs: ~[],
             mains: ~[],
@@ -54,12 +51,11 @@ pub fn new(src_dir: &Path, dst_dir: &Path,
     fn check_dir(&self) -> Path {
         use conditions::nonexistent_package::cond;
 
-        debug!("Pushing onto root: %s | %s", self.id.remote_path.to_str(),
-               self.root.to_str());
+        debug!("Pushing onto root: %s | %s", self.id.path.to_str(), self.root.to_str());
         let dir;
         let dirs = pkgid_src_in_workspace(&self.id, &self.root);
         debug!("Checking dirs: %?", dirs);
-        let path = dirs.iter().find_(|&d| os::path_exists(d));
+        let path = dirs.iter().find(|&d| os::path_exists(d));
         match path {
             Some(d) => dir = (*d).clone(),
             None => dir = match self.fetch_git() {
@@ -89,18 +85,18 @@ pub fn fetch_git(&self) -> Option<Path> {
         os::remove_dir_recursive(&local);
 
         debug!("Checking whether %s exists locally. Cwd = %s, does it? %?",
-               self.id.local_path.to_str(),
+               self.id.path.to_str(),
                os::getcwd().to_str(),
-               os::path_exists(&*self.id.local_path));
+               os::path_exists(&self.id.path));
 
-        if os::path_exists(&*self.id.local_path) {
+        if os::path_exists(&self.id.path) {
             debug!("%s exists locally! Cloning it into %s",
-                   self.id.local_path.to_str(), local.to_str());
-            git_clone(&*self.id.local_path, &local, &self.id.version);
+                   self.id.path.to_str(), local.to_str());
+            git_clone(&self.id.path, &local, &self.id.version);
             return Some(local);
         }
 
-        let url = fmt!("https://%s", self.id.remote_path.to_str());
+        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) {
@@ -125,25 +121,8 @@ pub fn package_script_option(&self, cwd: &Path) -> Option<Path> {
     }
 
     /// True if the given path's stem is self's pkg ID's stem
-    /// or if the pkg ID's stem is <rust-foo> and the given path's
-    /// stem is foo
-    /// Requires that dashes in p have already been normalized to
-    /// underscores
     fn stem_matches(&self, p: &Path) -> bool {
-        let self_id = self.id.local_path.filestem();
-        if self_id == p.filestem() {
-            return true;
-        }
-        else {
-            for pth in self_id.iter() {
-                if pth.starts_with("rust_") // because p is already normalized
-                    && match p.filestem() {
-                           Some(s) => str::eq_slice(s, pth.slice(5, pth.len())),
-                           None => false
-                       } { return true; }
-            }
-        }
-        false
+        p.filestem().map_default(false, |p| { p == &self.id.short_name })
     }
 
     fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) {
@@ -164,7 +143,7 @@ pub fn find_crates(&mut self) {
         let dir = self.check_dir();
         debug!("Called check_dir, I'm in %s", dir.to_str());
         let prefix = dir.components.len();
-        debug!("Matching against %?", self.id.local_path.filestem());
+        debug!("Matching against %?", self.id.short_name);
         do os::walk_dir(&dir) |pth| {
             match pth.filename() {
                 Some(~"lib.rs") => PkgSrc::push_crate(&mut self.libs,
@@ -202,7 +181,6 @@ pub fn find_crates(&mut self) {
 
     fn build_crates(&self,
                     ctx: &Ctx,
-                    dst_dir: &Path,
                     src_dir: &Path,
                     crates: &[Crate],
                     cfgs: &[~str],
@@ -210,12 +188,13 @@ fn build_crates(&self,
         for crate in crates.iter() {
             let path = &src_dir.push_rel(&crate.file).normalize();
             note(fmt!("build_crates: compiling %s", path.to_str()));
-            note(fmt!("build_crates: destination dir is %s", dst_dir.to_str()));
+            note(fmt!("build_crates: using as workspace %s", self.root.to_str()));
 
             let result = compile_crate(ctx,
                                        &self.id,
                                        path,
-                                       dst_dir,
+                                       // compile_crate wants the workspace
+                                       &self.root,
                                        crate.flags,
                                        crate.cfgs + cfgs,
                                        false,
@@ -229,15 +208,15 @@ fn build_crates(&self,
         }
     }
 
-    pub fn build(&self, ctx: &Ctx, dst_dir: Path, cfgs: ~[~str]) {
+    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, &dst_dir, &dir, self.libs, cfgs, Lib);
+        self.build_crates(ctx, &dir, self.libs, cfgs, Lib);
         debug!("Building mains");
-        self.build_crates(ctx, &dst_dir, &dir, self.mains, cfgs, Main);
+        self.build_crates(ctx, &dir, self.mains, cfgs, Main);
         debug!("Building tests");
-        self.build_crates(ctx, &dst_dir, &dir, self.tests, cfgs, Test);
+        self.build_crates(ctx, &dir, self.tests, cfgs, Test);
         debug!("Building benches");
-        self.build_crates(ctx, &dst_dir, &dir, self.benchs, cfgs, Bench);
+        self.build_crates(ctx, &dir, self.benchs, cfgs, Bench);
     }
 }
index fdfa29b2f832b5077373358f31d9899e57d63aab..bbe84b2ecac4f8ddfa7539d5ca5961c3b102d3dd 100644 (file)
 
 // rustpkg utilities having to do with paths and directories
 
-pub use package_path::{RemotePath, LocalPath, normalize};
 pub use package_id::PkgId;
 pub use target::{OutputType, Main, Lib, Test, Bench, Target, Build, Install};
 pub use version::{Version, NoVersion, split_version_general};
+pub use rustc::metadata::filesearch::rust_path;
+
 use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
 use std::os::mkdir_recursive;
 use std::os;
-use std::iterator::IteratorUtil;
 use messages::*;
 use package_id::*;
 
-fn push_if_exists(vec: &mut ~[Path], p: &Path) {
-    let maybe_dir = p.push(".rust");
-    if os::path_exists(&maybe_dir) {
-        vec.push(maybe_dir);
-    }
-}
-
-#[cfg(windows)]
-static PATH_ENTRY_SEPARATOR: &'static str = ";";
-#[cfg(not(windows))]
-static PATH_ENTRY_SEPARATOR: &'static str = ":";
-
-/// Returns RUST_PATH as a string, without default paths added
-pub fn get_rust_path() -> Option<~str> {
-    os::getenv("RUST_PATH")
-}
-
-/// Returns the value of RUST_PATH, as a list
-/// of Paths. Includes default entries for, if they exist:
-/// $HOME/.rust
-/// DIR/.rust for any DIR that's the current working directory
-/// or an ancestor of it
-pub fn rust_path() -> ~[Path] {
-    let mut env_rust_path: ~[Path] = match get_rust_path() {
-        Some(env_path) => {
-            let env_path_components: ~[&str] =
-                env_path.split_str_iter(PATH_ENTRY_SEPARATOR).collect();
-            env_path_components.map(|&s| Path(s))
-        }
-        None => ~[]
-    };
-    debug!("RUST_PATH entries from environment: %?", env_rust_path);
-    let cwd = os::getcwd();
-    // now add in default entries
-    env_rust_path.push(cwd.clone());
-    do cwd.each_parent() |p| { push_if_exists(&mut env_rust_path, p) };
-    let h = os::homedir();
-    // Avoid adding duplicates
-    // could still add dups if someone puts one of these in the RUST_PATH
-    // manually, though...
-    for hdir in h.iter() {
-        if !(cwd.is_ancestor_of(hdir) || hdir.is_ancestor_of(&cwd)) {
-            push_if_exists(&mut env_rust_path, hdir);
-        }
-    }
-    env_rust_path
-}
-
 pub fn default_workspace() -> Path {
     let p = rust_path();
     if p.is_empty() {
@@ -99,39 +51,39 @@ pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, U_RWX) }
 /// pkgid's short name
 pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
     let src_dir = workspace.push("src");
-    let dirs = os::list_dir(&src_dir);
-    for p in dirs.iter() {
-        let p = Path((*p).clone());
+    let mut found = false;
+    do os::walk_dir(&src_dir) |p| {
         debug!("=> p = %s", p.to_str());
-        if !os::path_is_dir(&src_dir.push_rel(&p)) {
-            loop;
-        }
-        debug!("p = %s, remote_path = %s", p.to_str(), pkgid.remote_path.to_str());
+        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());
 
-        if p == *pkgid.remote_path {
-            return true;
-        }
-        else {
-            let pf = p.filename();
-            for pf in pf.iter() {
-                let f_ = (*pf).clone();
-                let g = f_.to_str();
-                match split_version_general(g, '-') {
-                    Some((ref might_match, ref vers)) => {
-                        debug!("might_match = %s, vers = %s", *might_match,
+            if *p == src_dir.push_rel(&pkgid.path) {
+                found = true;
+            }
+            else {
+                let pf = p.filename();
+                for pf in pf.iter() {
+                    let f_ = (*pf).clone();
+                    let g = f_.to_str();
+                    match split_version_general(g, '-') {
+                        Some((ref might_match, ref vers)) => {
+                            debug!("might_match = %s, vers = %s", *might_match,
                                vers.to_str());
-                        if *might_match == pkgid.short_name
-                            && (*vers == pkgid.version || pkgid.version == NoVersion)
-                        {
-                            return true;
+                            if *might_match == pkgid.short_name
+                                 && (*vers == pkgid.version || pkgid.version == NoVersion)
+                            {
+                                  found = true;
+                            }
                         }
-                    }
-                    None => ()
+                        None => ()
+                     }
                 }
             }
         }
-    }
-    false
+        true
+    };
+    found
 }
 
 /// Returns a list of possible directories
@@ -141,9 +93,9 @@ pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
 pub fn pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> ~[Path] {
     let mut results = ~[];
     let result = workspace.push("src").push(fmt!("%s-%s",
-                     pkgid.local_path.to_str(), pkgid.version.to_str()));
+                     pkgid.path.to_str(), pkgid.version.to_str()));
     results.push(result);
-    results.push(workspace.push("src").push_rel(&*pkgid.remote_path));
+    results.push(workspace.push("src").push_rel(&pkgid.path));
     results
 }
 
@@ -163,7 +115,7 @@ pub fn first_pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<P
 pub fn built_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
     let mut result = workspace.push("build");
     // should use a target-specific subdirectory
-    result = mk_output_path(Main, Build, pkgid, &result);
+    result = mk_output_path(Main, Build, pkgid, result);
     debug!("built_executable_in_workspace: checking whether %s exists",
            result.to_str());
     if os::path_exists(&result) {
@@ -191,7 +143,7 @@ pub fn built_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path>
 fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Option<Path> {
     let mut result = workspace.push("build");
     // should use a target-specific subdirectory
-    result = mk_output_path(what, Build, pkgid, &result);
+    result = mk_output_path(what, Build, pkgid, result);
     debug!("output_in_workspace: checking whether %s exists",
            result.to_str());
     if os::path_exists(&result) {
@@ -206,14 +158,12 @@ fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Opt
 /// Figure out what the library name for <pkgid> in <workspace>'s build
 /// directory is, and if the file exists, return it.
 pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
-    library_in_workspace(&pkgid.local_path, pkgid.short_name,
-                         Build, workspace, "build")
+    library_in_workspace(&pkgid.path, pkgid.short_name, Build, workspace, "build")
 }
 
 /// Does the actual searching stuff
 pub fn installed_library_in_workspace(short_name: &str, workspace: &Path) -> Option<Path> {
-    library_in_workspace(&normalize(RemotePath(Path(short_name))),
-                         short_name, Install, workspace, "lib")
+    library_in_workspace(&Path(short_name), short_name, Install, workspace, "lib")
 }
 
 
@@ -221,7 +171,7 @@ pub fn installed_library_in_workspace(short_name: &str, workspace: &Path) -> Opt
 /// don't know the entire package ID.
 /// `workspace` is used to figure out the directory to search.
 /// `short_name` is taken as the link name of the library.
-pub fn library_in_workspace(path: &LocalPath, short_name: &str, where: Target,
+pub fn library_in_workspace(path: &Path, short_name: &str, where: Target,
                         workspace: &Path, prefix: &str) -> Option<Path> {
     debug!("library_in_workspace: checking whether a library named %s exists",
            short_name);
@@ -233,7 +183,7 @@ pub fn library_in_workspace(path: &LocalPath, short_name: &str, where: Target,
             prefix = %s", short_name, where, workspace.to_str(), prefix);
 
     let dir_to_search = match where {
-        Build => workspace.push(prefix).push_rel(&**path),
+        Build => workspace.push(prefix).push_rel(path),
         Install => workspace.push(prefix)
     };
     debug!("Listing directory %s", dir_to_search.to_str());
@@ -349,7 +299,7 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
     // Artifacts in the build directory live in a package-ID-specific subdirectory,
     // but installed ones don't.
     let result = match where {
-                Build => workspace.push(subdir).push_rel(&*pkgid.local_path),
+                Build => workspace.push(subdir).push_rel(&pkgid.path),
                 _     => workspace.push(subdir)
     };
     if !os::path_exists(&result) && !mkdir_recursive(&result, U_RWX) {
@@ -357,7 +307,7 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
             create the %s dir (pkgid=%s, workspace=%s, what=%?, where=%?",
             subdir, pkgid.to_str(), workspace.to_str(), what, where)));
     }
-    mk_output_path(what, where, pkgid, &result)
+    mk_output_path(what, where, pkgid, result)
 }
 
 /// Return the directory for <pkgid>'s build artifacts in <workspace>.
@@ -368,7 +318,7 @@ pub fn build_pkg_id_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
     let mut result = workspace.push("build");
     // n.b. Should actually use a target-specific
     // subdirectory of build/
-    result = result.push_rel(&*pkgid.local_path);
+    result = result.push_rel(&pkgid.path);
     if os::path_exists(&result) || os::mkdir_recursive(&result, U_RWX) {
         result
     }
@@ -380,19 +330,16 @@ pub fn build_pkg_id_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
 /// Return the output file for a given directory name,
 /// given whether we're building a library and whether we're building tests
 pub fn mk_output_path(what: OutputType, where: Target,
-                      pkg_id: &PkgId, workspace: &Path) -> Path {
+                      pkg_id: &PkgId, workspace: Path) -> Path {
     let short_name_with_version = fmt!("%s-%s", pkg_id.short_name,
                                        pkg_id.version.to_str());
     // Not local_path.dir_path()! For package foo/bar/blat/, we want
     // the executable blat-0.5 to live under blat/
     let dir = match where {
         // If we're installing, it just goes under <workspace>...
-        Install => {
-            // bad copy, but I just couldn't make the borrow checker happy
-            (*workspace).clone()
-        }
+        Install => workspace,
         // and if we're just building, it goes in a package-specific subdir
-        Build => workspace.push_rel(&*pkg_id.local_path)
+        Build => workspace.push_rel(&pkg_id.path)
     };
     debug!("[%?:%?] mk_output_path: short_name = %s, path = %s", what, where,
            if what == Lib { short_name_with_version.clone() } else { pkg_id.short_name.clone() },
index fa03a5bbfc2fbf70eb47beea86951ae38971edd4..3ae2ad3751ffb0ddda5b09c0e128d7c74e3d3744 100644 (file)
 
 use rustc::driver::{driver, session};
 use rustc::metadata::filesearch;
+use rustc::metadata::filesearch::rust_path;
 use extra::{getopts};
 use syntax::{ast, diagnostic};
 use util::*;
 use messages::*;
 use path_util::{build_pkg_id_in_workspace, first_pkgid_src_in_workspace};
-use path_util::{U_RWX, rust_path, in_rust_path};
+use path_util::{U_RWX, in_rust_path};
 use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace};
 use path_util::{target_executable_in_workspace, target_library_in_workspace};
 use source_control::is_git_dir;
@@ -54,7 +55,6 @@
 mod installed_packages;
 mod messages;
 mod package_id;
-mod package_path;
 mod package_source;
 mod path_util;
 mod search;
@@ -138,35 +138,28 @@ fn run_custom(&self, sysroot: @Path) -> (~[~str], ExitCode) {
         let crate = util::ready_crate(sess, self.crate);
         debug!("Building output filenames with script name %s",
                driver::source_name(&self.input));
-        match filesearch::get_rustpkg_sysroot() {
-            Ok(r) => {
-                let root = r.pop().pop().pop().pop(); // :-\
-                debug!("Root is %s, calling compile_rest", root.to_str());
-                let exe = self.build_dir.push(~"pkg" + util::exe_suffix());
-                util::compile_crate_from_input(&self.input,
-                                               &self.build_dir,
-                                               sess,
-                                               crate);
-                debug!("Running program: %s %s %s %s", exe.to_str(),
-                       sysroot.to_str(), root.to_str(), "install");
-                // FIXME #7401 should support commands besides `install`
-                let status = run::process_status(exe.to_str(), [sysroot.to_str(), ~"install"]);
-                if status != 0 {
-                    return (~[], status);
-                }
-                else {
-                    debug!("Running program (configs): %s %s %s",
-                           exe.to_str(), root.to_str(), "configs");
-                    let output = run::process_output(exe.to_str(), [root.to_str(), ~"configs"]);
-                    // Run the configs() function to get the configs
-                    let cfgs = str::from_bytes_slice(output.output).word_iter()
-                        .transform(|w| w.to_owned()).collect();
-                    (cfgs, output.status)
-                }
-            }
-            Err(e) => {
-                fail!("Running package script, couldn't find rustpkg sysroot (%s)", e)
-            }
+        let root = filesearch::get_or_default_sysroot().pop().pop(); // :-\
+        debug!("Root is %s, calling compile_rest", root.to_str());
+        let exe = self.build_dir.push(~"pkg" + util::exe_suffix());
+        util::compile_crate_from_input(&self.input,
+                                       &self.build_dir,
+                                       sess,
+                                       crate);
+        debug!("Running program: %s %s %s %s", exe.to_str(),
+               sysroot.to_str(), root.to_str(), "install");
+        // FIXME #7401 should support commands besides `install`
+        let status = run::process_status(exe.to_str(), [sysroot.to_str(), ~"install"]);
+        if status != 0 {
+            return (~[], status);
+        }
+        else {
+            debug!("Running program (configs): %s %s %s",
+                   exe.to_str(), root.to_str(), "configs");
+            let output = run::process_output(exe.to_str(), [root.to_str(), ~"configs"]);
+            // Run the configs() function to get the configs
+            let cfgs = str::from_bytes_slice(output.output).word_iter()
+                .map(|w| w.to_owned()).collect();
+            (cfgs, output.status)
         }
     }
 
@@ -205,7 +198,7 @@ fn run(&self, cmd: &str, args: ~[~str]) {
                 else {
                     // The package id is presumed to be the first command-line
                     // argument
-                    let pkgid = PkgId::new(args[0].clone(), &os::getcwd());
+                    let pkgid = PkgId::new(args[0].clone());
                     do each_pkg_parent_workspace(&pkgid) |workspace| {
                         debug!("found pkg %s in workspace %s, trying to build",
                                pkgid.to_str(), workspace.to_str());
@@ -228,7 +221,7 @@ fn run(&self, cmd: &str, args: ~[~str]) {
                 else {
                     // The package id is presumed to be the first command-line
                     // argument
-                    let pkgid = PkgId::new(args[0].clone(), &os::getcwd());
+                    let pkgid = PkgId::new(args[0].clone());
                     let cwd = os::getcwd();
                     self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd
                 }
@@ -254,13 +247,12 @@ fn run(&self, cmd: &str, args: ~[~str]) {
                 else {
                     // The package id is presumed to be the first command-line
                     // argument
-                    let pkgid = PkgId::new(args[0], &os::getcwd());
+                    let pkgid = PkgId::new(args[0]);
                     let workspaces = pkg_parent_workspaces(&pkgid);
                     if workspaces.is_empty() {
                         let rp = rust_path();
                         assert!(!rp.is_empty());
-                        let src = PkgSrc::new(&rp[0], &build_pkg_id_in_workspace(&pkgid, &rp[0]),
-                                              &pkgid);
+                        let src = PkgSrc::new(&rp[0], &pkgid);
                         src.fetch_git();
                         self.install(&rp[0], &pkgid);
                     }
@@ -275,7 +267,7 @@ fn run(&self, cmd: &str, args: ~[~str]) {
             "list" => {
                 io::println("Installed packages:");
                 do installed_packages::list_installed_packages |pkg_id| {
-                    println(pkg_id.local_path.to_str());
+                    println(pkg_id.path.to_str());
                     true
                 };
             }
@@ -294,7 +286,7 @@ fn run(&self, cmd: &str, args: ~[~str]) {
                     return usage::uninstall();
                 }
 
-                let pkgid = PkgId::new(args[0], &os::getcwd()); // ??
+                let pkgid = PkgId::new(args[0]);
                 if !installed_packages::package_is_installed(&pkgid) {
                     warn(fmt!("Package %s doesn't seem to be installed! Doing nothing.", args[0]));
                     return;
@@ -329,20 +321,18 @@ fn do_cmd(&self, _cmd: &str, _pkgname: &str)  {
     fn build(&self, workspace: &Path, pkgid: &PkgId) {
         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.local_path)),
+               in_rust_path(workspace), is_git_dir(&workspace.push_rel(&pkgid.path)),
                pkgid.to_str());
         let src_dir   = first_pkgid_src_in_workspace(pkgid, workspace);
-        let build_dir = build_pkg_id_in_workspace(pkgid, workspace);
-        debug!("Destination dir = %s", build_dir.to_str());
 
         // If workspace isn't in the RUST_PATH, and it's a git repo,
         // then clone it into the first entry in RUST_PATH, and repeat
         debug!("%? %? %s", in_rust_path(workspace),
-               is_git_dir(&workspace.push_rel(&*pkgid.local_path)),
+               is_git_dir(&workspace.push_rel(&pkgid.path)),
                workspace.to_str());
-        if !in_rust_path(workspace) && is_git_dir(&workspace.push_rel(&*pkgid.local_path)) {
-            let out_dir = default_workspace().push("src").push_rel(&*pkgid.local_path);
-            source_control::git_clone(&workspace.push_rel(&*pkgid.local_path),
+        if !in_rust_path(workspace) && is_git_dir(&workspace.push_rel(&pkgid.path)) {
+            let out_dir = default_workspace().push("src").push_rel(&pkgid.path);
+            source_control::git_clone(&workspace.push_rel(&pkgid.path),
                                       &out_dir, &pkgid.version);
             let default_ws = default_workspace();
             debug!("Calling build recursively with %? and %?", default_ws.to_str(),
@@ -351,7 +341,7 @@ fn build(&self, workspace: &Path, pkgid: &PkgId) {
         }
 
         // Create the package source
-        let mut src = PkgSrc::new(workspace, &build_dir, pkgid);
+        let mut src = PkgSrc::new(workspace, pkgid);
         debug!("Package src = %?", src);
 
         // Is there custom build logic? If so, use it
@@ -385,7 +375,7 @@ fn build(&self, workspace: &Path, pkgid: &PkgId) {
             // Find crates inside the workspace
             src.find_crates();
             // Build it!
-            src.build(self, build_dir, cfgs);
+            src.build(self, cfgs);
         }
     }
 
@@ -444,6 +434,7 @@ fn install_no_build(&self, workspace: &Path, id: &PkgId) {
         for lib in maybe_library.iter() {
             let target_lib = target_lib.clone().expect(fmt!("I built %s but apparently \
                                                 didn't install it!", lib.to_str()));
+            let target_lib = target_lib.pop().push(lib.filename().expect("weird target lib"));
             debug!("Copying: %s -> %s", lib.to_str(), target_lib.to_str());
             if !(os::mkdir_recursive(&target_lib.dir_path(), U_RWX) &&
                  os::copy_file(lib, &target_lib)) {
@@ -518,9 +509,7 @@ pub fn main() {
         };
     }
 
-    let sroot = match filesearch::get_rustpkg_sysroot() {
-        Ok(r) => Some(@r.pop().pop()), Err(_) => None
-    };
+    let sroot = Some(@filesearch::get_or_default_sysroot());
     debug!("Using sysroot: %?", sroot);
     Ctx {
         sysroot_opt: sroot, // Currently, only tests override this
index e3b796a03bb256baeeb567569c87ad72a7df157b..caa004a53b22879363807268745510a0926659bf 100644 (file)
@@ -10,7 +10,7 @@
 
 // Utils for working with version control repositories. Just git right now.
 
-use std::{os, run, str};
+use std::{io, os, run, str};
 use std::run::{ProcessOutput, ProcessOptions, Process};
 use version::*;
 
@@ -19,14 +19,37 @@ pub fn git_clone(source: &Path, target: &Path, v: &Version) {
     assert!(os::path_is_dir(source));
     assert!(is_git_dir(source));
     if !os::path_exists(target) {
-        debug!("Running: git clone %s %s", source.to_str(),
-               target.to_str());
-        assert!(git_clone_general(source.to_str(), target, v));
+        debug!("Running: git clone %s %s", source.to_str(), target.to_str());
+        let outp = run::process_output("git", [~"clone", source.to_str(), target.to_str()]);
+        if outp.status != 0 {
+            io::println(str::from_bytes_owned(outp.output.clone()));
+            io::println(str::from_bytes_owned(outp.error));
+            fail!("Couldn't `git clone` %s", source.to_str());
+        }
+        else {
+            match v {
+                &ExactRevision(ref s) => {
+                    debug!("`Running: git --work-tree=%s --git-dir=%s checkout %s",
+                           *s, target.to_str(), target.push(".git").to_str());
+                    let outp = run::process_output("git",
+                                   [fmt!("--work-tree=%s", target.to_str()),
+                                    fmt!("--git-dir=%s", target.push(".git").to_str()),
+                                    ~"checkout", fmt!("%s", *s)]);
+                    if outp.status != 0 {
+                        io::println(str::from_bytes_owned(outp.output.clone()));
+                        io::println(str::from_bytes_owned(outp.error));
+                        fail!("Couldn't `git checkout %s` in %s",
+                              *s, target.to_str());
+                    }
+                }
+                _ => ()
+            }
+        }
     }
     else {
-        // Pull changes
-        // Note that this ignores tags, which is probably wrong. There are no tests for
-        // it, though.
+        // Check that no version was specified. There's no reason to not handle the
+        // case where a version was requested, but I haven't implemented it.
+        assert!(*v == NoVersion);
         debug!("Running: git --work-tree=%s --git-dir=%s pull --no-edit %s",
                target.to_str(), target.push(".git").to_str(), source.to_str());
         let outp = run::process_output("git", [fmt!("--work-tree=%s", target.to_str()),
index 9fea866212975c02335ead93f4121c9fb039d5ee..121dcf40150211f56aea9e52f9036b227a5a42df 100644 (file)
 
 use context::Ctx;
 use std::hashmap::HashMap;
-use std::{io, libc, os, result, run, str};
+use std::{io, libc, os, run, str};
 use extra::tempfile::mkdtemp;
 use std::run::ProcessOutput;
 use installed_packages::list_installed_packages;
-use package_path::*;
 use package_id::{PkgId};
 use version::{ExactRevision, NoVersion, Version, Tagged};
 use path_util::{target_executable_in_workspace, target_library_in_workspace,
@@ -24,7 +23,9 @@
                make_dir_rwx, U_RWX, library_in_workspace,
                built_bench_in_workspace, built_test_in_workspace,
                built_library_in_workspace, built_executable_in_workspace,
-                installed_library_in_workspace, rust_path};
+                installed_library_in_workspace};
+use rustc::metadata::filesearch::rust_path;
+use rustc::driver::driver::host_triple;
 use target::*;
 
 /// Returns the last-modified date as an Option
@@ -42,31 +43,25 @@ fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
 
 fn fake_pkg() -> PkgId {
     let sn = ~"bogus";
-    let remote = RemotePath(Path(sn));
     PkgId {
-        local_path: normalize(remote.clone()),
-        remote_path: remote,
+        path: Path(sn),
         short_name: sn,
         version: NoVersion
     }
 }
 
 fn git_repo_pkg() -> PkgId {
-    let remote = RemotePath(Path("mockgithub.com/catamorphism/test-pkg"));
     PkgId {
-        local_path: normalize(remote.clone()),
-        remote_path: remote,
-        short_name: ~"test_pkg",
+        path: Path("mockgithub.com/catamorphism/test-pkg"),
+        short_name: ~"test-pkg",
         version: NoVersion
     }
 }
 
 fn git_repo_pkg_with_tag(a_tag: ~str) -> PkgId {
-    let remote = RemotePath(Path("mockgithub.com/catamorphism/test-pkg"));
     PkgId {
-        local_path: normalize(remote.clone()),
-        remote_path: remote,
-        short_name: ~"test_pkg",
+        path: Path("mockgithub.com/catamorphism/test-pkg"),
+        short_name: ~"test-pkg",
         version: Tagged(a_tag)
     }
 }
@@ -76,13 +71,13 @@ fn writeFile(file_path: &Path, contents: &str) {
     out.write_line(contents);
 }
 
-fn mk_empty_workspace(short_name: &LocalPath, version: &Version) -> Path {
+fn mk_empty_workspace(short_name: &Path, version: &Version) -> Path {
     let workspace_dir = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
     mk_workspace(&workspace_dir, short_name, version);
     workspace_dir
 }
 
-fn mk_workspace(workspace: &Path, short_name: &LocalPath, version: &Version) -> Path {
+fn mk_workspace(workspace: &Path, short_name: &Path, version: &Version) -> Path {
     // include version number in directory name
     let package_dir = workspace.push("src").push(fmt!("%s-%s",
                                                       short_name.to_str(), version.to_str()));
@@ -90,7 +85,7 @@ fn mk_workspace(workspace: &Path, short_name: &LocalPath, version: &Version) ->
     package_dir
 }
 
-fn mk_temp_workspace(short_name: &LocalPath, 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",
                                                             short_name.to_str(),
@@ -116,6 +111,22 @@ fn mk_temp_workspace(short_name: &LocalPath, version: &Version) -> Path {
     package_dir
 }
 
+fn run_git(args: &[~str], env: Option<~[(~str, ~str)]>, cwd: &Path, err_msg: &str) {
+    let cwd = (*cwd).clone();
+    let mut prog = run::Process::new("git", args, run::ProcessOptions {
+        env: env.map(|v| v.slice(0, v.len())),
+        dir: Some(&cwd),
+        in_fd: None,
+        out_fd: None,
+        err_fd: None
+    });
+    let rslt = prog.finish_with_output();
+    if rslt.status != 0 {
+        fail!("%s [git returned %?, output = %s, error = %s]", err_msg,
+           rslt.status, str::from_bytes(rslt.output), str::from_bytes(rslt.error));
+    }
+}
+
 /// Should create an empty git repo in p, relative to the tmp dir, and return the new
 /// absolute path
 fn init_git_repo(p: &Path) -> Path {
@@ -125,37 +136,14 @@ fn init_git_repo(p: &Path) -> Path {
     let work_dir_for_opts = work_dir.clone();
     assert!(os::mkdir_recursive(&work_dir, U_RWX));
     debug!("Running: git init in %s", work_dir.to_str());
-    let opts = run::ProcessOptions {
-        env: None,
-        dir: Some(&work_dir_for_opts),
-        in_fd: None,
-        out_fd: None,
-        err_fd: None
-    };
-    let mut prog = run::Process::new("git", [~"init"], opts);
-    let mut output = prog.finish_with_output();
-    if output.status == 0 {
-        // Add stuff to the dir so that git tag succeeds
-        writeFile(&work_dir.push("README"), "");
-        prog = run::Process::new("git", [~"add", ~"README"], opts);
-        output = prog.finish_with_output();
-        if output.status == 0 {
-            prog = run::Process::new("git", [~"commit", ~"-m", ~"whatever"], opts);
-            output = prog.finish_with_output();
-            if output.status == 0 {
-                tmp
-            }
-            else {
-                fail!("Couldn't commit in %s", work_dir.to_str());
-            }
-        }
-        else {
-            fail!("Couldn't add in %s", work_dir.to_str());
-        }
-    }
-    else {
-        fail!("Couldn't initialize git repository in %s", work_dir.to_str())
-    }
+    let ws = work_dir.to_str();
+    run_git([~"init"], None, &work_dir_for_opts,
+        fmt!("Couldn't initialize git repository in %s", ws));
+    // Add stuff to the dir so that git tag succeeds
+    writeFile(&work_dir.push("README"), "");
+    run_git([~"add", ~"README"], None, &work_dir_for_opts, fmt!("Couldn't add in %s", ws));
+    git_commit(&work_dir_for_opts, ~"whatever");
+    tmp
 }
 
 fn add_all_and_commit(repo: &Path) {
@@ -164,51 +152,20 @@ fn add_all_and_commit(repo: &Path) {
 }
 
 fn git_commit(repo: &Path, msg: ~str) {
-    let mut prog = run::Process::new("git", [~"commit", ~"-m", msg],
-                                     run::ProcessOptions { env: None,
-                                                          dir: Some(repo),
-                                                          in_fd: None,
-                                                          out_fd: None,
-                                                          err_fd: None
-                                                         });
-    let output = prog.finish_with_output();
-    if output.status != 0 {
-        fail!("Couldn't commit in %s: output was %s", repo.to_str(),
-              str::from_bytes(output.output + output.error))
-    }
-
+    run_git([~"commit", ~"--author=tester <test@mozilla.com>", ~"-m", msg],
+            None, repo, fmt!("Couldn't commit in %s", repo.to_str()));
 }
 
 fn git_add_all(repo: &Path) {
-    let mut prog = run::Process::new("git", [~"add", ~"-A"],
-                                     run::ProcessOptions { env: None,
-                                                          dir: Some(repo),
-                                                          in_fd: None,
-                                                          out_fd: None,
-                                                          err_fd: None
-                                                         });
-    let output = prog.finish_with_output();
-    if output.status != 0 {
-        fail!("Couldn't add all files in %s: output was %s",
-              repo.to_str(), str::from_bytes(output.output + output.error))
-    }
+    run_git([~"add", ~"-A"], None, repo, fmt!("Couldn't add all files in %s", repo.to_str()));
 }
 
 fn add_git_tag(repo: &Path, tag: ~str) {
     assert!(repo.is_absolute());
     git_add_all(repo);
     git_commit(repo, ~"whatever");
-    let mut prog = run::Process::new("git", [~"tag", tag.clone()],
-                                     run::ProcessOptions { env: None,
-                                                          dir: Some(repo),
-                                                          in_fd: None,
-                                                          out_fd: None,
-                                                          err_fd: None
-                                                         });
-    let output = prog.finish_with_output();
-    if output.status != 0 {
-        fail!("Couldn't add git tag %s in %s", tag, repo.to_str())
-    }
+    run_git([~"tag", tag.clone()], None, repo,
+            fmt!("Couldn't add git tag %s in %s", tag, repo.to_str()));
 }
 
 fn is_rwx(p: &Path) -> bool {
@@ -231,6 +188,25 @@ fn test_sysroot() -> Path {
     self_path.pop()
 }
 
+// Returns the path to rustpkg
+fn rustpkg_exec() -> Path {
+    // Ugh
+    let first_try = test_sysroot().push("lib").push("rustc")
+        .push(host_triple()).push("bin").push("rustpkg");
+    if is_executable(&first_try) {
+        first_try
+    }
+    else {
+        let second_try = test_sysroot().push("bin").push("rustpkg");
+        if is_executable(&second_try) {
+            second_try
+        }
+        else {
+            fail!("in rustpkg test, can't find an installed rustpkg");
+        }
+    }
+}
+
 fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
     command_line_test_with_env(args, cwd, None)
 }
@@ -240,8 +216,9 @@ fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
 /// Returns the process's output.
 fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~str)]>)
     -> ProcessOutput {
-    let cmd = test_sysroot().push("bin").push("rustpkg").to_str();
-    debug!("About to run command: %? %? in %s", cmd, args, cwd.to_str());
+    let cmd = rustpkg_exec().to_str();
+    debug!("cd %s; %s %s",
+           cwd.to_str(), cmd, args.connect(" "));
     assert!(os::path_is_dir(&*cwd));
     let cwd = (*cwd).clone();
     let mut prog = run::Process::new(cmd, args, run::ProcessOptions {
@@ -263,14 +240,15 @@ fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~s
 to make sure the command succeeded
 */
     if output.status != 0 {
-        fail!("Command %s %? failed with exit code %?",
-              cmd, args, output.status);
+        fail!("Command %s %? failed with exit code %?; its output was {{{ %s }}}",
+              cmd, args, output.status,
+              str::from_bytes(output.output) + str::from_bytes(output.error));
     }
     output
 }
 
 fn create_local_package(pkgid: &PkgId) -> Path {
-    let parent_dir = mk_temp_workspace(&pkgid.local_path, &pkgid.version);
+    let parent_dir = mk_temp_workspace(&pkgid.path, &pkgid.version);
     debug!("Created empty package dir for %s, returning %s", pkgid.to_str(), parent_dir.to_str());
     parent_dir.pop().pop()
 }
@@ -327,26 +305,26 @@ fn create_local_package_with_custom_build_hook(pkgid: &PkgId,
 
 }
 
-fn assert_lib_exists(repo: &Path, short_name: &str, v: Version) {
+fn assert_lib_exists(repo: &Path, short_name: &str, _v: Version) { // ??? version?
     debug!("assert_lib_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
-    let lib = target_library_in_workspace(&(PkgId {
-        version: v, ..PkgId::new(short_name, repo)}
-                                           ), repo);
-    debug!("assert_lib_exists: checking whether %s exists", lib.to_str());
-    assert!(os::path_exists(&lib));
-    assert!(is_rwx(&lib));
+    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));
 }
 
 fn assert_executable_exists(repo: &Path, short_name: &str) {
     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), repo);
+    let exec = target_executable_in_workspace(&PkgId::new(short_name), repo);
     assert!(os::path_exists(&exec));
     assert!(is_rwx(&exec));
 }
 
 fn assert_built_executable_exists(repo: &Path, short_name: &str) {
     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),
+    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));
@@ -372,11 +350,11 @@ fn command_line_test_output_with_env(args: &[~str], env: ~[(~str, ~str)]) -> ~[~
     result
 }
 
-// assumes short_name and local_path are one and the same -- I should fix
+// assumes short_name and path are one and the same -- I should fix
 fn lib_output_file_name(workspace: &Path, parent: &str, short_name: &str) -> Path {
     debug!("lib_output_file_name: given %s and parent %s and short name %s",
            workspace.to_str(), parent, short_name);
-    library_in_workspace(&normalize(RemotePath(Path(short_name))),
+    library_in_workspace(&Path(short_name),
                          short_name,
                          Build,
                          workspace,
@@ -451,7 +429,7 @@ fn test_install_valid() {
     debug!("sysroot = %s", sysroot.to_str());
     let ctxt = fake_ctxt(Some(@sysroot));
     let temp_pkg_id = fake_pkg();
-    let temp_workspace = mk_temp_workspace(&temp_pkg_id.local_path, &NoVersion).pop().pop();
+    let temp_workspace = mk_temp_workspace(&temp_pkg_id.path, &NoVersion).pop().pop();
     debug!("temp_workspace = %s", temp_workspace.to_str());
     // should have test, bench, lib, and main
     ctxt.install(&temp_workspace, &temp_pkg_id);
@@ -504,7 +482,7 @@ fn test_install_git() {
     let sysroot = test_sysroot();
     debug!("sysroot = %s", sysroot.to_str());
     let temp_pkg_id = git_repo_pkg();
-    let repo = init_git_repo(&Path(temp_pkg_id.local_path.to_str()));
+    let repo = init_git_repo(&temp_pkg_id.path);
     let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg");
     writeFile(&repo_subdir.push("main.rs"),
               "fn main() { let _x = (); }");
@@ -517,9 +495,9 @@ fn test_install_git() {
     add_git_tag(&repo_subdir, ~"0.1"); // this has the effect of committing the files
 
     debug!("test_install_git: calling rustpkg install %s in %s",
-           temp_pkg_id.local_path.to_str(), repo.to_str());
+           temp_pkg_id.path.to_str(), repo.to_str());
     // should have test, bench, lib, and main
-    command_line_test([~"install", temp_pkg_id.local_path.to_str()], &repo);
+    command_line_test([~"install", temp_pkg_id.path.to_str()], &repo);
     // Check that all files exist
     debug!("Checking for files in %s", repo.to_str());
     let exec = target_executable_in_workspace(&temp_pkg_id, &repo);
@@ -563,18 +541,18 @@ fn test_package_ids_must_be_relative_path_like() {
 
     */
 
-    let whatever = PkgId::new("foo", &os::getcwd());
+    let whatever = PkgId::new("foo");
 
     assert_eq!(~"foo-0.1", whatever.to_str());
-    assert!("github.com/catamorphism/test_pkg-0.1" ==
-            PkgId::new("github.com/catamorphism/test-pkg", &os::getcwd()).to_str());
+    assert!("github.com/catamorphism/test-pkg-0.1" ==
+            PkgId::new("github.com/catamorphism/test-pkg").to_str());
 
     do cond.trap(|(p, e)| {
         assert!("" == p.to_str());
         assert!("0-length pkgid" == e);
         whatever.clone()
     }).inside {
-        let x = PkgId::new("", &os::getcwd());
+        let x = PkgId::new("");
         assert_eq!(~"foo-0.1", x.to_str());
     }
 
@@ -583,8 +561,7 @@ fn test_package_ids_must_be_relative_path_like() {
         assert!("absolute pkgid" == e);
         whatever.clone()
     }).inside {
-        let z = PkgId::new(os::make_absolute(&Path("foo/bar/quux")).to_str(),
-                           &os::getcwd());
+        let z = PkgId::new(os::make_absolute(&Path("foo/bar/quux")).to_str());
         assert_eq!(~"foo-0.1", z.to_str());
     }
 
@@ -607,7 +584,7 @@ fn test_package_version() {
               "#[bench] pub fn f() { (); }");
     add_git_tag(&repo_subdir, ~"0.4");
 
-    let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version", &repo);
+    let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version");
     match temp_pkg_id.version {
         ExactRevision(~"0.4") => (),
         _ => fail!(fmt!("test_package_version: package version was %?, expected Some(0.4)",
@@ -656,7 +633,7 @@ fn test_package_request_version() {
         }
         None    => false
     });
-    let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version#0.3", &repo);
+    let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version#0.3");
     assert!(target_executable_in_workspace(&temp_pkg_id, &repo.push(".rust"))
             == repo.push(".rust").push("bin").push("test_pkg_version"));
 
@@ -696,12 +673,12 @@ fn rustpkg_library_target() {
 
     add_git_tag(&package_dir, ~"1.0");
     command_line_test([~"install", ~"foo"], &foo_repo);
-    assert_lib_exists(&foo_repo, "foo", ExactRevision(~"1.0"));
+    assert_lib_exists(&foo_repo.push(".rust"), "foo", ExactRevision(~"1.0"));
 }
 
 #[test]
 fn rustpkg_local_pkg() {
-    let dir = create_local_package(&PkgId::new("foo", &os::getcwd()));
+    let dir = create_local_package(&PkgId::new("foo"));
     command_line_test([~"install", ~"foo"], &dir);
     assert_executable_exists(&dir, "foo");
 }
@@ -711,7 +688,7 @@ fn rustpkg_local_pkg() {
 #[test]
 #[ignore]
 fn package_script_with_default_build() {
-    let dir = create_local_package(&PkgId::new("fancy-lib", &os::getcwd()));
+    let dir = create_local_package(&PkgId::new("fancy-lib"));
     debug!("dir = %s", dir.to_str());
     let source = test_sysroot().pop().pop().pop().push("src").push("librustpkg").
         push("testsuite").push("pass").push("src").push("fancy-lib").push("pkg.rs");
@@ -763,7 +740,7 @@ fn rustpkg_clean_no_arg() {
     command_line_test([~"build"], &package_dir);
     assert_built_executable_exists(&tmp, "foo");
     command_line_test([~"clean"], &package_dir);
-    assert!(!built_executable_in_workspace(&PkgId::new("foo", &package_dir),
+    assert!(!built_executable_in_workspace(&PkgId::new("foo"),
                 &tmp).map_default(false, |m| { os::path_exists(m) }));
 }
 
@@ -771,14 +748,13 @@ fn rustpkg_clean_no_arg() {
 #[ignore (reason = "Specifying env doesn't work -- see #8028")]
 fn rust_path_test() {
     let dir_for_path = mkdtemp(&os::tmpdir(), "more_rust").expect("rust_path_test failed");
-    let dir = mk_workspace(&dir_for_path, &normalize(RemotePath(Path("foo"))), &NoVersion);
+    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 cwd = os::getcwd();
     debug!("cwd = %s", cwd.to_str());
-    debug!("Running command: cd %s; RUST_LOG=rustpkg RUST_PATH=%s rustpkg install foo",
-           cwd.to_str(), dir_for_path.to_str());
+                                     // use command_line_test_with_env
     let mut prog = run::Process::new("rustpkg",
                                      [~"install", ~"foo"],
                                      run::ProcessOptions { env: Some(&[(~"RUST_LOG",
@@ -830,39 +806,38 @@ fn rust_path_parse() {
 #[test]
 fn test_list() {
     let dir = mkdtemp(&os::tmpdir(), "test_list").expect("test_list failed");
-    let foo = PkgId::new("foo", &dir);
+    let foo = PkgId::new("foo");
     create_local_package_in(&foo, &dir);
-    let bar = PkgId::new("bar", &dir);
+    let bar = PkgId::new("bar");
     create_local_package_in(&bar, &dir);
-    let quux = PkgId::new("quux", &dir);
+    let quux = PkgId::new("quux");
     create_local_package_in(&quux, &dir);
 
-// NOTE Not really great output, though...
-// NOTE do any tests need to be unignored?
+// list doesn't output very much right now...
     command_line_test([~"install", ~"foo"], &dir);
     let env_arg = ~[(~"RUST_PATH", dir.to_str())];
     debug!("RUST_PATH = %s", dir.to_str());
     let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
-    assert!(list_output.iter().any(|x| x.starts_with("libfoo_")));
+    assert!(list_output.iter().any(|x| x.starts_with("foo")));
 
     command_line_test([~"install", ~"bar"], &dir);
     let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
-    assert!(list_output.iter().any(|x| x.starts_with("libfoo_")));
-    assert!(list_output.iter().any(|x| x.starts_with("libbar_")));
+    assert!(list_output.iter().any(|x| x.starts_with("foo")));
+    assert!(list_output.iter().any(|x| x.starts_with("bar")));
 
     command_line_test([~"install", ~"quux"], &dir);
     let list_output = command_line_test_output_with_env([~"list"], env_arg);
-    assert!(list_output.iter().any(|x| x.starts_with("libfoo_")));
-    assert!(list_output.iter().any(|x| x.starts_with("libbar_")));
-    assert!(list_output.iter().any(|x| x.starts_with("libquux_")));
+    assert!(list_output.iter().any(|x| x.starts_with("foo")));
+    assert!(list_output.iter().any(|x| x.starts_with("bar")));
+    assert!(list_output.iter().any(|x| x.starts_with("quux")));
 }
 
 #[test]
 fn install_remove() {
     let dir = mkdtemp(&os::tmpdir(), "install_remove").expect("install_remove");
-    let foo = PkgId::new("foo", &dir);
-    let bar = PkgId::new("bar", &dir);
-    let quux = PkgId::new("quux", &dir);
+    let foo = PkgId::new("foo");
+    let bar = PkgId::new("bar");
+    let quux = PkgId::new("quux");
     create_local_package_in(&foo, &dir);
     create_local_package_in(&bar, &dir);
     create_local_package_in(&quux, &dir);
@@ -887,7 +862,7 @@ fn install_check_duplicates() {
     // ("Is already installed -- doing nothing")
     // check invariant that there are no dups in the pkg database
     let dir = mkdtemp(&os::tmpdir(), "install_remove").expect("install_remove");
-    let foo = PkgId::new("foo", &dir);
+    let foo = PkgId::new("foo");
     create_local_package_in(&foo, &dir);
 
     command_line_test([~"install", ~"foo"], &dir);
@@ -895,7 +870,7 @@ fn install_check_duplicates() {
     let mut contents = ~[];
     let check_dups = |p: &PkgId| {
         if contents.contains(p) {
-            fail!("package %s appears in `list` output more than once", p.local_path.to_str());
+            fail!("package %s appears in `list` output more than once", p.path.to_str());
         }
         else {
             contents.push((*p).clone());
@@ -908,7 +883,7 @@ fn install_check_duplicates() {
 #[test]
 #[ignore(reason = "Workcache not yet implemented -- see #7075")]
 fn no_rebuilding() {
-    let p_id = PkgId::new("foo", &os::getcwd());
+    let p_id = PkgId::new("foo");
     let workspace = create_local_package(&p_id);
     command_line_test([~"build", ~"foo"], &workspace);
     let date = datestamp(&built_library_in_workspace(&p_id,
@@ -922,8 +897,8 @@ fn no_rebuilding() {
 #[test]
 #[ignore(reason = "Workcache not yet implemented -- see #7075")]
 fn no_rebuilding_dep() {
-    let p_id = PkgId::new("foo", &os::getcwd());
-    let dep_id = PkgId::new("bar", &os::getcwd());
+    let p_id = PkgId::new("foo");
+    let dep_id = PkgId::new("bar");
     let workspace = create_local_package_with_dep(&p_id, &dep_id);
     command_line_test([~"build", ~"foo"], &workspace);
     let bar_date = datestamp(&lib_output_file_name(&workspace,
@@ -935,8 +910,8 @@ fn no_rebuilding_dep() {
 
 #[test]
 fn do_rebuild_dep_dates_change() {
-    let p_id = PkgId::new("foo", &os::getcwd());
-    let dep_id = PkgId::new("bar", &os::getcwd());
+    let p_id = PkgId::new("foo");
+    let dep_id = PkgId::new("bar");
     let workspace = create_local_package_with_dep(&p_id, &dep_id);
     command_line_test([~"build", ~"foo"], &workspace);
     let bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
@@ -948,8 +923,8 @@ fn do_rebuild_dep_dates_change() {
 
 #[test]
 fn do_rebuild_dep_only_contents_change() {
-    let p_id = PkgId::new("foo", &os::getcwd());
-    let dep_id = PkgId::new("bar", &os::getcwd());
+    let p_id = PkgId::new("foo");
+    let dep_id = PkgId::new("bar");
     let workspace = create_local_package_with_dep(&p_id, &dep_id);
     command_line_test([~"build", ~"foo"], &workspace);
     let bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
@@ -962,8 +937,8 @@ fn do_rebuild_dep_only_contents_change() {
 
 #[test]
 fn test_versions() {
-    let workspace = create_local_package(&PkgId::new("foo#0.1", &os::getcwd()));
-    create_local_package(&PkgId::new("foo#0.2", &os::getcwd()));
+    let workspace = create_local_package(&PkgId::new("foo#0.1"));
+    create_local_package(&PkgId::new("foo#0.2"));
     command_line_test([~"install", ~"foo#0.1"], &workspace);
     let output = command_line_test_output([~"list"]);
     // make sure output includes versions
@@ -973,7 +948,7 @@ fn test_versions() {
 #[test]
 #[ignore(reason = "do not yet implemented")]
 fn test_build_hooks() {
-    let workspace = create_local_package_with_custom_build_hook(&PkgId::new("foo", &os::getcwd()),
+    let workspace = create_local_package_with_custom_build_hook(&PkgId::new("foo"),
                                                                 "frob");
     command_line_test([~"do", ~"foo", ~"frob"], &workspace);
 }
@@ -983,7 +958,7 @@ fn test_build_hooks() {
 #[ignore(reason = "info not yet implemented")]
 fn test_info() {
     let expected_info = ~"package foo"; // fill in
-    let workspace = create_local_package(&PkgId::new("foo", &os::getcwd()));
+    let workspace = create_local_package(&PkgId::new("foo"));
     let output = command_line_test([~"info", ~"foo"], &workspace);
     assert_eq!(str::from_bytes(output.output), expected_info);
 }
@@ -992,7 +967,7 @@ fn test_info() {
 #[ignore(reason = "test not yet implemented")]
 fn test_rustpkg_test() {
     let expected_results = ~"1 out of 1 tests passed"; // fill in
-    let workspace = create_local_package_with_test(&PkgId::new("foo", &os::getcwd()));
+    let workspace = create_local_package_with_test(&PkgId::new("foo"));
     let output = command_line_test([~"test", ~"foo"], &workspace);
     assert_eq!(str::from_bytes(output.output), expected_results);
 }
@@ -1000,7 +975,7 @@ fn test_rustpkg_test() {
 #[test]
 #[ignore(reason = "test not yet implemented")]
 fn test_uninstall() {
-    let workspace = create_local_package(&PkgId::new("foo", &os::getcwd()));
+    let workspace = create_local_package(&PkgId::new("foo"));
     let _output = command_line_test([~"info", ~"foo"], &workspace);
     command_line_test([~"uninstall", ~"foo"], &workspace);
     let output = command_line_test([~"list"], &workspace);
@@ -1010,8 +985,8 @@ fn test_uninstall() {
 #[test]
 fn test_non_numeric_tag() {
     let temp_pkg_id = git_repo_pkg();
-    let repo = init_git_repo(&Path(temp_pkg_id.local_path.to_str()));
-    let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg");
+    let repo = init_git_repo(&temp_pkg_id.path);
+    let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test-pkg");
     writeFile(&repo_subdir.push("foo"), "foo");
     writeFile(&repo_subdir.push("lib.rs"),
               "pub fn f() { let _x = (); }");
@@ -1021,13 +996,70 @@ fn test_non_numeric_tag() {
     writeFile(&repo_subdir.push("not_on_testbranch_only"), "bye bye");
     add_all_and_commit(&repo_subdir);
 
-
-    command_line_test([~"install", fmt!("%s#testbranch", temp_pkg_id.remote_path.to_str())],
-                      &repo);
+    command_line_test([~"install", fmt!("%s#testbranch", temp_pkg_id.path.to_str())], &repo);
     let file1 = repo.push_many(["mockgithub.com", "catamorphism",
-                                "test_pkg", "testbranch_only"]);
-    let file2 = repo.push_many(["mockgithub.com", "catamorphism", "test_pkg",
+                                "test-pkg", "testbranch_only"]);
+    let file2 = repo.push_many(["mockgithub.com", "catamorphism", "test-pkg",
                                 "master_only"]);
     assert!(os::path_exists(&file1));
     assert!(!os::path_exists(&file2));
 }
+
+#[test]
+fn test_extern_mod() {
+    let dir = mkdtemp(&os::tmpdir(), "test_extern_mod").expect("test_extern_mod");
+    let main_file = dir.push("main.rs");
+    let lib_depend_dir = mkdtemp(&os::tmpdir(), "foo").expect("test_extern_mod");
+    let aux_dir = lib_depend_dir.push_many(["src", "mockgithub.com", "catamorphism", "test_pkg"]);
+    assert!(os::mkdir_recursive(&aux_dir, U_RWX));
+    let aux_pkg_file = aux_dir.push("lib.rs");
+
+    writeFile(&aux_pkg_file, "pub mod bar { pub fn assert_true() {  assert!(true); } }\n");
+    assert!(os::path_exists(&aux_pkg_file));
+
+    writeFile(&main_file,
+              "extern mod test = \"mockgithub.com/catamorphism/test_pkg\";\nuse test::bar;\
+               fn main() { bar::assert_true(); }\n");
+
+    command_line_test([~"install", ~"mockgithub.com/catamorphism/test_pkg"], &lib_depend_dir);
+
+    let exec_file = dir.push("out");
+    // Be sure to extend the existing environment
+    let env = Some([(~"RUST_PATH", lib_depend_dir.to_str())] + os::env());
+    let rustpkg_exec = rustpkg_exec();
+    let rustc = rustpkg_exec.with_filename("rustc");
+    debug!("RUST_PATH=%s %s %s \n --sysroot %s -o %s",
+                     lib_depend_dir.to_str(),
+                     rustc.to_str(),
+                     main_file.to_str(),
+                     test_sysroot().to_str(),
+                     exec_file.to_str());
+
+    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.map(|v| v.slice(0, v.len())),
+        dir: Some(&dir),
+        in_fd: None,
+        out_fd: None,
+        err_fd: None
+    });
+    let outp = prog.finish_with_output();
+    if outp.status != 0 {
+        fail!("output was %s, error was %s",
+              str::from_bytes(outp.output),
+              str::from_bytes(outp.error));
+    }
+    assert!(os::path_exists(&exec_file) && is_executable(&exec_file));
+}
+
+/// Returns true if p exists and is executable
+fn is_executable(p: &Path) -> bool {
+    use std::libc::consts::os::posix88::{S_IXUSR};
+
+    match p.get_mode() {
+        None => false,
+        Some(mode) => mode & S_IXUSR as uint == S_IXUSR as uint
+    }
+}
index 81b47d6a16c0ad8ec9640ed6d988b88364a62a3b..afac9423fba66027da5112787412f681a96f3bb2 100644 (file)
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::{os, result};
+use std::os;
 use rustc::driver::{driver, session};
-use rustc::metadata::filesearch;
 use extra::getopts::groups::getopts;
 use syntax::ast_util::*;
 use syntax::codemap::{dummy_sp, spanned};
 use syntax::attr::AttrMetaMethods;
 use rustc::back::link::output_type_exe;
 use rustc::driver::session::{lib_crate, bin_crate};
-use context::Ctx;
+use context::{Ctx, in_target};
 use package_id::PkgId;
 use search::find_library_in_search_path;
-use path_util::target_library_in_workspace;
+use path_util::{target_library_in_workspace, U_RWX};
 pub use target::{OutputType, Main, Lib, Bench, Test};
 
 // It would be nice to have the list of commands in just one place -- for example,
@@ -47,13 +46,6 @@ fn to_str(&self) -> ~str {
     }
 }
 
-pub fn root() -> Path {
-    match filesearch::get_rustpkg_root() {
-        result::Ok(path) => path,
-        result::Err(err) => fail!(err)
-    }
-}
-
 pub fn is_cmd(cmd: &str) -> bool {
     COMMANDS.iter().any(|&c| c == cmd)
 }
@@ -162,25 +154,25 @@ pub fn ready_crate(sess: session::Session,
 pub fn compile_input(ctxt: &Ctx,
                      pkg_id: &PkgId,
                      in_file: &Path,
-                     out_dir: &Path,
+                     workspace: &Path,
                      flags: &[~str],
                      cfgs: &[~str],
                      opt: bool,
                      what: OutputType) -> bool {
 
-    let workspace = out_dir.pop().pop();
-
     assert!(in_file.components.len() > 1);
     let input = driver::file_input((*in_file).clone());
     debug!("compile_input: %s / %?", in_file.to_str(), what);
     // tjc: by default, use the package ID name as the link name
     // not sure if we should support anything else
 
+    let out_dir = workspace.push("build").push_rel(&pkg_id.path);
+
     let binary = os::args()[0].to_managed();
 
     debug!("flags: %s", flags.connect(" "));
     debug!("cfgs: %s", cfgs.connect(" "));
-    debug!("compile_input's sysroot = %?", ctxt.sysroot_opt);
+    debug!("out_dir = %s", out_dir.to_str());
 
     let crate_type = match what {
         Lib => lib_crate,
@@ -196,12 +188,22 @@ pub fn compile_input(ctxt: &Ctx,
                           + flags
                           + cfgs.flat_map(|c| { ~[~"--cfg", (*c).clone()] }),
                           driver::optgroups()).unwrap();
+    // Hack so that rustpkg can run either out of a rustc target dir,
+    // or the host dir
+    let sysroot_to_use = if !in_target(ctxt.sysroot_opt) {
+        ctxt.sysroot_opt
+    }
+    else {
+        ctxt.sysroot_opt.map(|p| { @p.pop().pop().pop() })
+    };
+    debug!("compile_input's sysroot = %?", ctxt.sysroot_opt_str());
+    debug!("sysroot_to_use = %?", sysroot_to_use);
     let options = @session::options {
         crate_type: crate_type,
         optimize: if opt { session::Aggressive } else { session::No },
         test: what == Test || what == Bench,
-        maybe_sysroot: ctxt.sysroot_opt,
-        addl_lib_search_paths: @mut (~[(*out_dir).clone()]),
+        maybe_sysroot: sysroot_to_use,
+        addl_lib_search_paths: @mut (~[out_dir.clone()]),
         // output_type should be conditional
         output_type: output_type_exe, // Use this to get a library? That's weird
         .. (*driver::build_session_options(binary, &matches, diagnostic::emit)).clone()
@@ -211,7 +213,12 @@ pub fn compile_input(ctxt: &Ctx,
     // Make sure all the library directories actually exist, since the linker will complain
     // otherwise
     for p in addl_lib_search_paths.iter() {
-        assert!(os::path_is_dir(p));
+        if os::path_exists(p) {
+            assert!(os::path_is_dir(p));
+        }
+        else {
+            assert!(os::mkdir_recursive(p, U_RWX));
+        }
     }
 
     let sess = driver::build_session(options, diagnostic::emit);
@@ -224,35 +231,44 @@ pub fn compile_input(ctxt: &Ctx,
 
     // Not really right. Should search other workspaces too, and the installed
     // database (which doesn't exist yet)
-    find_and_install_dependencies(ctxt, sess, &workspace, crate,
+    find_and_install_dependencies(ctxt, sess, workspace, crate,
                                   |p| {
                                       debug!("a dependency: %s", p.to_str());
                                       // Pass the directory containing a dependency
                                       // as an additional lib search path
-                                      addl_lib_search_paths.push(p);
+                                      if !addl_lib_search_paths.contains(&p) {
+                                          // Might be inefficient, but this set probably
+                                          // won't get too large -- tjc
+                                          addl_lib_search_paths.push(p);
+                                      }
                                   });
 
     // Inject the link attributes so we get the right package name and version
     if attr::find_linkage_metas(crate.attrs).is_empty() {
-        let short_name_to_use = match what {
-            Test  => fmt!("%stest", pkg_id.short_name),
-            Bench => fmt!("%sbench", pkg_id.short_name),
-            _     => pkg_id.short_name.clone()
+        let name_to_use = match what {
+            Test  => fmt!("%stest", pkg_id.short_name).to_managed(),
+            Bench => fmt!("%sbench", pkg_id.short_name).to_managed(),
+            _     => pkg_id.short_name.to_managed()
         };
-        debug!("Injecting link name: %s", short_name_to_use);
+        debug!("Injecting link name: %s", name_to_use);
         let link_options =
-            ~[attr::mk_name_value_item_str(@"name", short_name_to_use.to_managed()),
-              attr::mk_name_value_item_str(@"vers", pkg_id.version.to_str().to_managed())];
-
+            ~[attr::mk_name_value_item_str(@"name", name_to_use),
+              attr::mk_name_value_item_str(@"vers", pkg_id.version.to_str().to_managed())] +
+                        if pkg_id.is_complex() {
+                        ~[attr::mk_name_value_item_str(@"package_id",
+                                                       pkg_id.path.to_str().to_managed())]
+                } else { ~[] };
+
+        debug!("link options: %?", link_options);
         crate = @ast::Crate {
             attrs: ~[attr::mk_attr(attr::mk_list_item(@"link", link_options))],
             .. (*crate).clone()
-        };
+        }
     }
 
-    debug!("calling compile_crate_from_input, out_dir = %s,
+    debug!("calling compile_crate_from_input, workspace = %s,
            building_library = %?", out_dir.to_str(), sess.building_library);
-    compile_crate_from_input(&input, out_dir, sess, crate);
+    compile_crate_from_input(&input, &out_dir, sess, crate);
     true
 }
 
@@ -262,17 +278,22 @@ pub fn compile_input(ctxt: &Ctx,
 // call compile_upto and return the crate
 // also, too many arguments
 pub fn compile_crate_from_input(input: &driver::input,
-                                build_dir: &Path,
+ // should be of the form <workspace>/build/<pkg id's path>
+                                out_dir: &Path,
                                 sess: session::Session,
                                 crate: @ast::Crate) {
     debug!("Calling build_output_filenames with %s, building library? %?",
-           build_dir.to_str(), sess.building_library);
+           out_dir.to_str(), sess.building_library);
 
     // bad copy
-    let outputs = driver::build_output_filenames(input, &Some((*build_dir).clone()), &None,
+    debug!("out_dir = %s", out_dir.to_str());
+    let outputs = driver::build_output_filenames(input, &Some(out_dir.clone()), &None,
                                                  crate.attrs, sess);
 
-    debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type);
+    debug!("Outputs are out_filename: %s and obj_filename: %s and output type = %?",
+           outputs.out_filename.to_str(),
+           outputs.obj_filename.to_str(),
+           sess.opts.output_type);
     debug!("additional libraries:");
     for lib in sess.opts.addl_lib_search_paths.iter() {
         debug!("an additional library: %s", lib.to_str());
@@ -298,15 +319,15 @@ pub fn exe_suffix() -> ~str { ~"" }
 // Called by build_crates
 // FIXME (#4432): Use workcache to only compile when needed
 pub fn compile_crate(ctxt: &Ctx, pkg_id: &PkgId,
-                     crate: &Path, dir: &Path,
+                     crate: &Path, workspace: &Path,
                      flags: &[~str], cfgs: &[~str], opt: bool,
                      what: OutputType) -> bool {
-    debug!("compile_crate: crate=%s, dir=%s", crate.to_str(), dir.to_str());
+    debug!("compile_crate: crate=%s, workspace=%s", crate.to_str(), workspace.to_str());
     debug!("compile_crate: short_name = %s, flags =...", pkg_id.to_str());
     for fl in flags.iter() {
         debug!("+++ %s", *fl);
     }
-    compile_input(ctxt, pkg_id, crate, dir, flags, cfgs, opt, what)
+    compile_input(ctxt, pkg_id, crate, workspace, flags, cfgs, opt, what)
 }
 
 
@@ -327,19 +348,20 @@ pub fn find_and_install_dependencies(ctxt: &Ctx,
         debug!("A view item!");
         match vi.node {
             // ignore metadata, I guess
-            ast::view_item_extern_mod(lib_ident, _, _) => {
+            ast::view_item_extern_mod(lib_ident, path_opt, _, _) => {
                 match my_ctxt.sysroot_opt {
-                    Some(ref x) => debug!("sysroot: %s", x.to_str()),
+                    Some(ref x) => debug!("*** sysroot: %s", x.to_str()),
                     None => debug!("No sysroot given")
                 };
-                let lib_name = sess.str_of(lib_ident);
+                let lib_name = match path_opt { // ???
+                    Some(p) => p, None => sess.str_of(lib_ident) };
                 match find_library_in_search_path(my_ctxt.sysroot_opt, lib_name) {
                     Some(installed_path) => {
                         debug!("It exists: %s", installed_path.to_str());
                     }
                     None => {
                         // Try to install it
-                        let pkg_id = PkgId::new(lib_name, &os::getcwd());
+                        let pkg_id = PkgId::new(lib_name);
                         my_ctxt.install(&my_workspace, &pkg_id);
                         // Also, add an additional search path
                         debug!("let installed_path...")
@@ -372,10 +394,12 @@ pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
 #[cfg(target_os = "freebsd")]
 #[cfg(target_os = "macos")]
 pub fn link_exe(src: &Path, dest: &Path) -> bool {
+    use std::c_str::ToCStr;
     use std::libc;
+
     unsafe {
-        do src.to_str().as_c_str |src_buf| {
-            do dest.to_str().as_c_str |dest_buf| {
+        do src.to_c_str().with_ref |src_buf| {
+            do dest.to_c_str().with_ref |dest_buf| {
                 libc::link(src_buf, dest_buf) == 0 as libc::c_int &&
                     libc::chmod(dest_buf, 755) == 0 as libc::c_int
             }
index 8839185089116ee78f30fc44d5c1a5b3ac1a0d19..44cb8065b382b2503749be7a168eae84c34fc7ab 100644 (file)
@@ -15,8 +15,8 @@
 
 use extra::semver;
 use std::{char, os, result, run, str};
-use package_path::RemotePath;
 use extra::tempfile::mkdtemp;
+use path_util::rust_path;
 
 #[deriving(Clone)]
 pub enum Version {
@@ -92,19 +92,22 @@ pub fn parse_vers(vers: ~str) -> result::Result<semver::Version, ~str> {
     }
 }
 
-/// If `local_path` is a git repo, and the most recent tag in that repo denotes a version,
-/// return it; otherwise, `None`
+/// If `local_path` is a git repo in the RUST_PATH, and the most recent tag
+/// in that repo denotes a version, return it; otherwise, `None`
 pub fn try_getting_local_version(local_path: &Path) -> Option<Version> {
-    debug!("in try_getting_local_version");
-    let outp = run::process_output("git",
+    let rustpath = rust_path();
+    for rp in rustpath.iter() {
+        let local_path = rp.push_rel(local_path);
+        debug!("in try_getting_local_version");
+        let outp = run::process_output("git",
                                    [fmt!("--git-dir=%s", local_path.push(".git").to_str()),
                                     ~"tag", ~"-l"]);
 
-    debug!("git --git-dir=%s tag -l ~~~> %?", local_path.push(".git").to_str(), outp.status);
+        debug!("git --git-dir=%s tag -l ~~~> %?", local_path.push(".git").to_str(), outp.status);
 
-    if outp.status != 0 {
-        return None;
-    }
+        if outp.status != 0 {
+            loop;
+        }
 
     let mut output = None;
     let output_text = str::from_bytes(outp.output);
@@ -112,14 +115,19 @@ pub fn try_getting_local_version(local_path: &Path) -> Option<Version> {
         if !l.is_whitespace() {
             output = Some(l);
         }
+        match output.chain(try_parsing_version) {
+            Some(v) => return Some(v),
+            None    => ()
+        }
     }
-    output.chain(try_parsing_version)
+  }
+  None
 }
 
 /// If `remote_path` refers to a git repo that can be downloaded,
 /// and the most recent tag in that repo denotes a version, return it;
 /// otherwise, `None`
-pub fn try_getting_version(remote_path: &RemotePath) -> Option<Version> {
+pub fn try_getting_version(remote_path: &Path) -> Option<Version> {
     debug!("try_getting_version: %s", remote_path.to_str());
     if is_url_like(remote_path) {
         debug!("Trying to fetch its sources..");
@@ -190,9 +198,9 @@ fn try_parsing_version(s: &str) -> Option<Version> {
 }
 
 /// Just an approximation
-fn is_url_like(p: &RemotePath) -> bool {
+fn is_url_like(p: &Path) -> bool {
     let str = p.to_str();
-    str.split_iter('/').len_() > 2
+    str.split_iter('/').len() > 2
 }
 
 /// If s is of the form foo#bar, where bar is a valid version
@@ -207,7 +215,7 @@ pub fn split_version_general<'a>(s: &'a str, sep: char) -> Option<(&'a str, Vers
     for st in s.split_iter(sep) {
         debug!("whole = %s part = %s", s, st);
     }
-    if s.split_iter(sep).len_() > 2 {
+    if s.split_iter(sep).len() > 2 {
         return None;
     }
     match s.rfind(sep) {
index d877b4ff489cf9d7075fa0aa1d7fb10896770cc9..6ac959e4a3260fc8c4e97628f1322037ecf160e8 100644 (file)
 
 use std::os;
 use std::path::Path;
-use path_util::{rust_path, workspace_contains_package_id};
+use path_util::workspace_contains_package_id;
 use package_id::PkgId;
 
+use rustc::metadata::filesearch::rust_path;
+
 pub fn each_pkg_parent_workspace(pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool {
     // Using the RUST_PATH, find workspaces that contain
     // this package ID
@@ -23,7 +25,7 @@ pub fn each_pkg_parent_workspace(pkgid: &PkgId, action: &fn(&Path) -> bool) -> b
         // tjc: make this a condition
         fail!("Package %s not found in any of \
                     the following workspaces: %s",
-                   pkgid.remote_path.to_str(),
+                   pkgid.path.to_str(),
                    rust_path().to_str());
     }
     for ws in workspaces.iter() {
@@ -35,7 +37,7 @@ pub fn each_pkg_parent_workspace(pkgid: &PkgId, action: &fn(&Path) -> bool) -> b
 }
 
 pub fn pkg_parent_workspaces(pkgid: &PkgId) -> ~[Path] {
-    rust_path().consume_iter()
+    rust_path().move_iter()
         .filter(|ws| workspace_contains_package_id(pkgid, ws))
         .collect()
 }
@@ -58,5 +60,5 @@ pub fn cwd_to_workspace() -> (Path, PkgId) {
     let ws = cwd.pop().pop();
     let cwd_ = cwd.clone();
     let pkgid = cwd_.components.last().to_str();
-    (ws, PkgId::new(pkgid, &cwd))
+    (ws, PkgId::new(pkgid))
 }
index f2470bed7329e81fcd1df99620574989f49607cd..c948074990a36824c9c8e9c10b09ff4eeba34cc5 100644 (file)
@@ -141,11 +141,11 @@ pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> @[T] {
  * Creates and initializes an immutable managed vector by moving all the
  * elements from an owned vector.
  */
-pub fn to_managed_consume<T>(v: ~[T]) -> @[T] {
+pub fn to_managed_move<T>(v: ~[T]) -> @[T] {
     let mut av = @[];
     unsafe {
         raw::reserve(&mut av, v.len());
-        for x in v.consume_iter() {
+        for x in v.move_iter() {
             raw::push(&mut av, x);
         }
         av
@@ -275,24 +275,11 @@ pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut Box<Vec<()>>, n: uint) {
         }
 
         fn local_realloc(ptr: *(), size: uint) -> *() {
-            use rt;
-            use rt::OldTaskContext;
             use rt::local::Local;
             use rt::task::Task;
 
-            if rt::context() == OldTaskContext {
-                unsafe {
-                    return rust_local_realloc(ptr, size as libc::size_t);
-                }
-
-                extern {
-                    #[fast_ffi]
-                    fn rust_local_realloc(ptr: *(), size: libc::size_t) -> *();
-                }
-            } else {
-                do Local::borrow::<Task, *()> |task| {
-                    task.heap.realloc(ptr as *libc::c_void, size) as *()
-                }
+            do Local::borrow::<Task, *()> |task| {
+                task.heap.realloc(ptr as *libc::c_void, size) as *()
             }
         }
     }
@@ -344,12 +331,12 @@ fn append_test() {
     }
 
     #[test]
-    fn test_to_managed_consume() {
-        assert_eq!(to_managed_consume::<int>(~[]), @[]);
-        assert_eq!(to_managed_consume(~[true]), @[true]);
-        assert_eq!(to_managed_consume(~[1, 2, 3, 4, 5]), @[1, 2, 3, 4, 5]);
-        assert_eq!(to_managed_consume(~[~"abc", ~"123"]), @[~"abc", ~"123"]);
-        assert_eq!(to_managed_consume(~[~[42]]), @[~[42]]);
+    fn test_to_managed_move() {
+        assert_eq!(to_managed_move::<int>(~[]), @[]);
+        assert_eq!(to_managed_move(~[true]), @[true]);
+        assert_eq!(to_managed_move(~[1, 2, 3, 4, 5]), @[1, 2, 3, 4, 5]);
+        assert_eq!(to_managed_move(~[~"abc", ~"123"]), @[~"abc", ~"123"]);
+        assert_eq!(to_managed_move(~[~[42]]), @[~[42]]);
     }
 
     #[test]
index eeaea6a2cffa92f2f2e28ffb70c08359ac60d04d..598e808061839f683c0fac6a3d8ec74afb54b4ac 100644 (file)
@@ -284,12 +284,6 @@ fn not(&self) -> bool { !*self }
 impl Ord for bool {
     #[inline]
     fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) }
-    #[inline]
-    fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) }
-    #[inline]
-    fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) }
-    #[inline]
-    fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) }
 }
 
 #[cfg(not(test))]
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
new file mode 100644 (file)
index 0000000..7e31354
--- /dev/null
@@ -0,0 +1,233 @@
+// 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.
+
+use cast;
+use iterator::Iterator;
+use libc;
+use ops::Drop;
+use option::{Option, Some, None};
+use ptr::RawPtr;
+use ptr;
+use str::StrSlice;
+use vec::ImmutableVector;
+
+/// The representation of a C String.
+///
+/// This structure wraps a `*libc::c_char`, and will automatically free the
+/// memory it is pointing to when it goes out of scope.
+pub struct CString {
+    priv buf: *libc::c_char,
+    priv owns_buffer_: bool,
+}
+
+impl CString {
+    /// Create a C String from a pointer.
+    pub unsafe fn new(buf: *libc::c_char, owns_buffer: bool) -> CString {
+        CString { buf: buf, owns_buffer_: owns_buffer }
+    }
+
+    /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
+    pub unsafe fn unwrap(self) -> *libc::c_char {
+        let mut c_str = self;
+        c_str.owns_buffer_ = false;
+        c_str.buf
+    }
+
+    /// Calls a closure with a reference to the underlying `*libc::c_char`.
+    ///
+    /// # Failure
+    ///
+    /// Fails if the CString is null.
+    pub fn with_ref<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
+        if self.buf.is_null() { fail!("CString is null!"); }
+        f(self.buf)
+    }
+
+    /// Calls a closure with a mutable reference to the underlying `*libc::c_char`.
+    ///
+    /// # Failure
+    ///
+    /// Fails if the CString is null.
+    pub fn with_mut_ref<T>(&mut self, f: &fn(*mut libc::c_char) -> T) -> T {
+        if self.buf.is_null() { fail!("CString is null!"); }
+        f(unsafe { cast::transmute_mut_unsafe(self.buf) })
+    }
+
+    /// Returns true if the CString is a null.
+    pub fn is_null(&self) -> bool {
+        self.buf.is_null()
+    }
+
+    /// Returns true if the CString is not null.
+    pub fn is_not_null(&self) -> bool {
+        self.buf.is_not_null()
+    }
+
+    /// Returns whether or not the `CString` owns the buffer.
+    pub fn owns_buffer(&self) -> bool {
+        self.owns_buffer_
+    }
+
+    /// Converts the CString into a `&[u8]` without copying.
+    ///
+    /// # Failure
+    ///
+    /// Fails if the CString is null.
+    pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
+        if self.buf.is_null() { fail!("CString is null!"); }
+        unsafe {
+            let len = libc::strlen(self.buf) as uint;
+            cast::transmute((self.buf, len + 1))
+        }
+    }
+
+    /// Return a CString iterator.
+    fn iter<'a>(&'a self) -> CStringIterator<'a> {
+        CStringIterator {
+            ptr: self.buf,
+            lifetime: unsafe { cast::transmute(self.buf) },
+        }
+    }
+}
+
+impl Drop for CString {
+    fn drop(&self) {
+        if self.owns_buffer_ {
+            unsafe {
+                libc::free(self.buf as *libc::c_void)
+            }
+        }
+    }
+}
+
+/// A generic trait for converting a value to a CString.
+pub trait ToCStr {
+    /// Create a C String.
+    fn to_c_str(&self) -> CString;
+}
+
+impl<'self> ToCStr for &'self str {
+    #[inline]
+    fn to_c_str(&self) -> CString {
+        self.as_bytes().to_c_str()
+    }
+}
+
+impl<'self> ToCStr for &'self [u8] {
+    fn to_c_str(&self) -> CString {
+        do self.as_imm_buf |self_buf, self_len| {
+            unsafe {
+                let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
+                if buf.is_null() {
+                    fail!("failed to allocate memory!");
+                }
+
+                ptr::copy_memory(buf, self_buf, self_len);
+                *ptr::mut_offset(buf, self_len as int) = 0;
+
+                CString::new(buf as *libc::c_char, true)
+            }
+        }
+    }
+}
+
+/// External iterator for a CString's bytes.
+///
+/// Use with the `std::iterator` module.
+pub struct CStringIterator<'self> {
+    priv ptr: *libc::c_char,
+    priv lifetime: &'self libc::c_char, // FIXME: #5922
+}
+
+impl<'self> Iterator<libc::c_char> for CStringIterator<'self> {
+    fn next(&mut self) -> Option<libc::c_char> {
+        let ch = unsafe { *self.ptr };
+        if ch == 0 {
+            None
+        } else {
+            self.ptr = ptr::offset(self.ptr, 1);
+            Some(ch)
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use libc;
+    use ptr;
+    use option::{Some, None};
+
+    #[test]
+    fn test_to_c_str() {
+        do "".to_c_str().with_ref |buf| {
+            unsafe {
+                assert_eq!(*ptr::offset(buf, 0), 0);
+            }
+        }
+
+        do "hello".to_c_str().with_ref |buf| {
+            unsafe {
+                assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 5), 0);
+            }
+        }
+    }
+
+    #[test]
+    fn test_is_null() {
+        let c_str = unsafe { CString::new(ptr::null(), false) };
+        assert!(c_str.is_null());
+        assert!(!c_str.is_not_null());
+    }
+
+    #[test]
+    fn test_unwrap() {
+        let c_str = "hello".to_c_str();
+        unsafe { libc::free(c_str.unwrap() as *libc::c_void) }
+    }
+
+    #[test]
+    fn test_with_ref() {
+        let c_str = "hello".to_c_str();
+        let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
+        assert!(!c_str.is_null());
+        assert!(c_str.is_not_null());
+        assert_eq!(len, 5);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_with_ref_empty_fail() {
+        let c_str = unsafe { CString::new(ptr::null(), false) };
+        c_str.with_ref(|_| ());
+    }
+
+    #[test]
+    fn test_iterator() {
+        let c_str = "".to_c_str();
+        let mut iter = c_str.iter();
+        assert_eq!(iter.next(), None);
+
+        let c_str = "hello".to_c_str();
+        let mut iter = c_str.iter();
+        assert_eq!(iter.next(), Some('h' as libc::c_char));
+        assert_eq!(iter.next(), Some('e' as libc::c_char));
+        assert_eq!(iter.next(), Some('l' as libc::c_char));
+        assert_eq!(iter.next(), Some('l' as libc::c_char));
+        assert_eq!(iter.next(), Some('o' as libc::c_char));
+        assert_eq!(iter.next(), None);
+    }
+}
index ee91d12790953214b49a0c25327a141e8cd03ee9..ff9057afb55fc47dfb1b10f88d8b7b958d757f34 100644 (file)
@@ -165,10 +165,20 @@ fn test_transmute() {
         }
     }
 
+    #[cfg(stage0)]
     #[test]
     fn test_transmute2() {
         unsafe {
             assert_eq!(~[76u8, 0u8], transmute(~"L"));
         }
     }
+
+    #[cfg(not(stage0))]
+    #[test]
+    fn test_transmute2() {
+        unsafe {
+            assert_eq!(~[76u8], transmute(~"L"));
+        }
+    }
+
 }
index 8505385543213720901ea1fcae0b0b46da83329d..9c55e22b1f833794a0cd70548de8140c757021d8 100644 (file)
@@ -322,12 +322,6 @@ fn ne(&self, other: &char) -> bool { (*self) != (*other) }
 impl Ord for char {
     #[inline]
     fn lt(&self, other: &char) -> bool { *self < *other }
-    #[inline]
-    fn le(&self, other: &char) -> bool { *self <= *other }
-    #[inline]
-    fn gt(&self, other: &char) -> bool { *self > *other }
-    #[inline]
-    fn ge(&self, other: &char) -> bool { *self >= *other }
 }
 
 #[cfg(not(test))]
index b9535091ed810927859f60b340fdd9fcecc3efab..7c2348a3533df83f9748ab5e07683f3e40faffd3 100644 (file)
@@ -56,13 +56,8 @@ unsafe fn each_live_alloc(read_next_before: bool,
 
 #[cfg(unix)]
 fn debug_mem() -> bool {
-    use rt;
-    use rt::OldTaskContext;
     // XXX: Need to port the environment struct to newsched
-    match rt::context() {
-        OldTaskContext => ::rt::env::get().debug_mem,
-        _ => false
-    }
+    false
 }
 
 #[cfg(windows)]
@@ -147,15 +142,3 @@ pub unsafe fn annihilate() {
         dbg.write_str("\n");
     }
 }
-
-/// Bindings to the runtime
-pub mod rustrt {
-    use libc::c_void;
-
-    #[link_name = "rustrt"]
-    extern {
-        #[rust_stack]
-        // FIXME (#4386): Unable to make following method private.
-        pub fn rust_get_task() -> *c_void;
-    }
-}
index b66f89e83415e1b22ad0a575f950f1855057460f..28d45abb6881f0dc8190c96f5a97865273f031f5 100644 (file)
@@ -101,12 +101,6 @@ fn cmp(&self, other: &Ordering) -> Ordering {
 impl Ord for Ordering {
     #[inline]
     fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) }
-    #[inline]
-    fn le(&self, other: &Ordering) -> bool { (*self as int) <= (*other as int) }
-    #[inline]
-    fn gt(&self, other: &Ordering) -> bool { (*self as int) > (*other as int) }
-    #[inline]
-    fn ge(&self, other: &Ordering) -> bool { (*self as int) >= (*other as int) }
 }
 
 macro_rules! totalord_impl(
@@ -174,8 +168,11 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
 #[lang="ord"]
 pub trait Ord {
     fn lt(&self, other: &Self) -> bool;
+    #[inline]
     fn le(&self, other: &Self) -> bool { !other.lt(self) }
+    #[inline]
     fn gt(&self, other: &Self) -> bool {  other.lt(self) }
+    #[inline]
     fn ge(&self, other: &Self) -> bool { !self.lt(other) }
 }
 
index a4de10f8c7760aae76a718f95a74aab086ad7cb7..18c7674873f1685f4ff7cbe823ab3bda5f51e1c7 100644 (file)
 
 #[allow(missing_doc)];
 
-use either::{Either, Left, Right};
+use clone::Clone;
 use kinds::Send;
-use option::{Option, Some};
-use unstable::sync::Exclusive;
+use option::Option;
 pub use rt::comm::SendDeferred;
 use rtcomm = rt::comm;
-use rt;
 
 /// A trait for things that can send multiple messages.
 pub trait GenericChan<T> {
@@ -52,614 +50,146 @@ pub trait Peekable<T> {
     fn peek(&self) -> bool;
 }
 
-/// An endpoint that can send many messages.
-pub struct Chan<T> {
-    inner: Either<pipesy::Chan<T>, rtcomm::Chan<T>>
-}
-
-/// An endpoint that can receive many messages.
-pub struct Port<T> {
-    inner: Either<pipesy::Port<T>, rtcomm::Port<T>>
-}
-
-/** Creates a `(Port, Chan)` pair.
-
-These allow sending or receiving an unlimited number of messages.
-
-*/
-pub fn stream<T:Send>() -> (Port<T>, Chan<T>) {
-    let (port, chan) = match rt::context() {
-        rt::OldTaskContext => match pipesy::stream() {
-            (p, c) => (Left(p), Left(c))
-        },
-        _ => match rtcomm::stream() {
-            (p, c) => (Right(p), Right(c))
-        }
-    };
-    let port = Port { inner: port };
-    let chan = Chan { inner: chan };
-    return (port, chan);
-}
+pub struct PortOne<T> { x: rtcomm::PortOne<T> }
+pub struct ChanOne<T> { x: rtcomm::ChanOne<T> }
 
-impl<T: Send> GenericChan<T> for Chan<T> {
-    fn send(&self, x: T) {
-        match self.inner {
-            Left(ref chan) => chan.send(x),
-            Right(ref chan) => chan.send(x)
-        }
-    }
-}
-
-impl<T: Send> GenericSmartChan<T> for Chan<T> {
-    fn try_send(&self, x: T) -> bool {
-        match self.inner {
-            Left(ref chan) => chan.try_send(x),
-            Right(ref chan) => chan.try_send(x)
-        }
-    }
-}
-
-impl<T: Send> SendDeferred<T> for Chan<T> {
-    fn send_deferred(&self, x: T) {
-        match self.inner {
-            Left(ref chan) => chan.send(x),
-            Right(ref chan) => chan.send_deferred(x)
-        }
-    }
-    fn try_send_deferred(&self, x: T) -> bool {
-        match self.inner {
-            Left(ref chan) => chan.try_send(x),
-            Right(ref chan) => chan.try_send_deferred(x)
-        }
-    }
+pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
+    let (p, c) = rtcomm::oneshot();
+    (PortOne { x: p }, ChanOne { x: c })
 }
 
-impl<T: Send> GenericPort<T> for Port<T> {
-    fn recv(&self) -> T {
-        match self.inner {
-            Left(ref port) => port.recv(),
-            Right(ref port) => port.recv()
-        }
-    }
-
-    fn try_recv(&self) -> Option<T> {
-        match self.inner {
-            Left(ref port) => port.try_recv(),
-            Right(ref port) => port.try_recv()
-        }
-    }
-}
+pub struct Port<T> { x: rtcomm::Port<T> }
+pub struct Chan<T> { x: rtcomm::Chan<T> }
 
-impl<T: Send> Peekable<T> for Port<T> {
-    fn peek(&self) -> bool {
-        match self.inner {
-            Left(ref port) => port.peek(),
-            Right(ref port) => port.peek()
-        }
-    }
+pub fn stream<T: Send>() -> (Port<T>, Chan<T>) {
+    let (p, c) = rtcomm::stream();
+    (Port { x: p }, Chan { x: c })
 }
 
-/// A channel that can be shared between many senders.
-pub struct SharedChan<T> {
-    inner: Either<Exclusive<pipesy::Chan<T>>, rtcomm::SharedChan<T>>
-}
+pub struct SharedChan<T> { x: rtcomm::SharedChan<T> }
 
 impl<T: Send> SharedChan<T> {
-    /// Converts a `chan` into a `shared_chan`.
     pub fn new(c: Chan<T>) -> SharedChan<T> {
-        let Chan { inner } = c;
-        let c = match inner {
-            Left(c) => Left(Exclusive::new(c)),
-            Right(c) => Right(rtcomm::SharedChan::new(c))
-        };
-        SharedChan { inner: c }
+        let Chan { x: c } = c;
+        SharedChan { x: rtcomm::SharedChan::new(c) }
     }
 }
 
-impl<T: Send> GenericChan<T> for SharedChan<T> {
-    fn send(&self, x: T) {
-        match self.inner {
-            Left(ref chan) => {
-                unsafe {
-                    let mut xx = Some(x);
-                    do chan.with_imm |chan| {
-                        chan.send(xx.take_unwrap())
-                    }
-                }
-            }
-            Right(ref chan) => chan.send(x)
-        }
+impl<T: Send> ChanOne<T> {
+    pub fn send(self, val: T) {
+        let ChanOne { x: c } = self;
+        c.send(val)
     }
-}
 
-impl<T: Send> GenericSmartChan<T> for SharedChan<T> {
-    fn try_send(&self, x: T) -> bool {
-        match self.inner {
-            Left(ref chan) => {
-                unsafe {
-                    let mut xx = Some(x);
-                    do chan.with_imm |chan| {
-                        chan.try_send(xx.take_unwrap())
-                    }
-                }
-            }
-            Right(ref chan) => chan.try_send(x)
-        }
+    pub fn try_send(self, val: T) -> bool {
+        let ChanOne { x: c } = self;
+        c.try_send(val)
     }
-}
 
-impl<T: Send> ::clone::Clone for SharedChan<T> {
-    fn clone(&self) -> SharedChan<T> {
-        SharedChan { inner: self.inner.clone() }
+    pub fn send_deferred(self, val: T) {
+        let ChanOne { x: c } = self;
+        c.send_deferred(val)
     }
-}
 
-pub struct PortOne<T> {
-    inner: Either<pipesy::PortOne<T>, rtcomm::PortOne<T>>
-}
-
-pub struct ChanOne<T> {
-    inner: Either<pipesy::ChanOne<T>, rtcomm::ChanOne<T>>
-}
-
-pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
-    let (port, chan) = match rt::context() {
-        rt::OldTaskContext => match pipesy::oneshot() {
-            (p, c) => (Left(p), Left(c)),
-        },
-        _ => match rtcomm::oneshot() {
-            (p, c) => (Right(p), Right(c))
-        }
-    };
-    let port = PortOne { inner: port };
-    let chan = ChanOne { inner: chan };
-    return (port, chan);
+    pub fn try_send_deferred(self, val: T) -> bool {
+        let ChanOne{ x: c } = self;
+        c.try_send_deferred(val)
+    }
 }
 
 impl<T: Send> PortOne<T> {
     pub fn recv(self) -> T {
-        let PortOne { inner } = self;
-        match inner {
-            Left(p) => p.recv(),
-            Right(p) => p.recv()
-        }
+        let PortOne { x: p } = self;
+        p.recv()
     }
 
     pub fn try_recv(self) -> Option<T> {
-        let PortOne { inner } = self;
-        match inner {
-            Left(p) => p.try_recv(),
-            Right(p) => p.try_recv()
-        }
+        let PortOne { x: p } = self;
+        p.try_recv()
     }
 }
 
-impl<T: Send> ChanOne<T> {
-    pub fn send(self, data: T) {
-        let ChanOne { inner } = self;
-        match inner {
-            Left(p) => p.send(data),
-            Right(p) => p.send(data)
-        }
-    }
-
-    pub fn try_send(self, data: T) -> bool {
-        let ChanOne { inner } = self;
-        match inner {
-            Left(p) => p.try_send(data),
-            Right(p) => p.try_send(data)
-        }
-    }
-    pub fn send_deferred(self, data: T) {
-        let ChanOne { inner } = self;
-        match inner {
-            Left(p) => p.send(data),
-            Right(p) => p.send_deferred(data)
-        }
-    }
-    pub fn try_send_deferred(self, data: T) -> bool {
-        let ChanOne { inner } = self;
-        match inner {
-            Left(p) => p.try_send(data),
-            Right(p) => p.try_send_deferred(data)
-        }
+impl<T: Send> Peekable<T>  for PortOne<T> {
+    fn peek(&self) -> bool {
+        let &PortOne { x: ref p } = self;
+        p.peek()
     }
 }
 
-pub fn recv_one<T: Send>(port: PortOne<T>) -> T {
-    let PortOne { inner } = port;
-    match inner {
-        Left(p) => pipesy::recv_one(p),
-        Right(p) => p.recv()
+impl<T: Send> GenericChan<T> for Chan<T> {
+    fn send(&self, val: T) {
+        let &Chan { x: ref c } = self;
+        c.send(val)
     }
 }
 
-pub fn try_recv_one<T: Send>(port: PortOne<T>) -> Option<T> {
-    let PortOne { inner } = port;
-    match inner {
-        Left(p) => pipesy::try_recv_one(p),
-        Right(p) => p.try_recv()
+impl<T: Send> GenericSmartChan<T> for Chan<T> {
+    fn try_send(&self, val: T) -> bool {
+        let &Chan { x: ref c } = self;
+        c.try_send(val)
     }
 }
 
-pub fn send_one<T: Send>(chan: ChanOne<T>, data: T) {
-    let ChanOne { inner } = chan;
-    match inner {
-        Left(c) => pipesy::send_one(c, data),
-        Right(c) => c.send(data)
+impl<T: Send> SendDeferred<T> for Chan<T> {
+    fn send_deferred(&self, val: T) {
+        let &Chan { x: ref c } = self;
+        c.send_deferred(val)
     }
-}
 
-pub fn try_send_one<T: Send>(chan: ChanOne<T>, data: T) -> bool {
-    let ChanOne { inner } = chan;
-    match inner {
-        Left(c) => pipesy::try_send_one(c, data),
-        Right(c) => c.try_send(data)
+    fn try_send_deferred(&self, val: T) -> bool {
+        let &Chan { x: ref c } = self;
+        c.try_send_deferred(val)
     }
 }
 
-mod pipesy {
-
-    use kinds::Send;
-    use option::{Option, Some, None};
-    use pipes::{recv, try_recv, peek};
-    use super::{GenericChan, GenericSmartChan, GenericPort, Peekable};
-    use cast::transmute_mut;
-
-    /*proto! oneshot (
-        Oneshot:send<T:Send> {
-            send(T) -> !
-        }
-    )*/
-
-    #[allow(non_camel_case_types)]
-    pub mod oneshot {
-        use std::kinds::Send;
-        use ptr::to_mut_unsafe_ptr;
-
-        pub fn init<T: Send>() -> (server::Oneshot<T>, client::Oneshot<T>) {
-            pub use std::pipes::HasBuffer;
-
-            let buffer = ~::std::pipes::Buffer {
-                header: ::std::pipes::BufferHeader(),
-                data: __Buffer {
-                    Oneshot: ::std::pipes::mk_packet::<Oneshot<T>>()
-                },
-            };
-            do ::std::pipes::entangle_buffer(buffer) |buffer, data| {
-                data.Oneshot.set_buffer(buffer);
-                to_mut_unsafe_ptr(&mut data.Oneshot)
-            }
-        }
-        #[allow(non_camel_case_types)]
-        pub enum Oneshot<T> { pub send(T), }
-        #[allow(non_camel_case_types)]
-        pub struct __Buffer<T> {
-            Oneshot: ::std::pipes::Packet<Oneshot<T>>,
-        }
-
-        #[allow(non_camel_case_types)]
-        pub mod client {
-
-            use std::kinds::Send;
-
-            #[allow(non_camel_case_types)]
-            pub fn try_send<T: Send>(pipe: Oneshot<T>, x_0: T) ->
-                ::std::option::Option<()> {
-                {
-                    use super::send;
-                    let message = send(x_0);
-                    if ::std::pipes::send(pipe, message) {
-                        ::std::pipes::rt::make_some(())
-                    } else { ::std::pipes::rt::make_none() }
-                }
-            }
-
-            #[allow(non_camel_case_types)]
-            pub fn send<T: Send>(pipe: Oneshot<T>, x_0: T) {
-                {
-                    use super::send;
-                    let message = send(x_0);
-                    ::std::pipes::send(pipe, message);
-                }
-            }
-
-            #[allow(non_camel_case_types)]
-            pub type Oneshot<T> =
-                ::std::pipes::SendPacketBuffered<super::Oneshot<T>,
-            super::__Buffer<T>>;
-        }
-
-        #[allow(non_camel_case_types)]
-        pub mod server {
-            #[allow(non_camel_case_types)]
-            pub type Oneshot<T> =
-                ::std::pipes::RecvPacketBuffered<super::Oneshot<T>,
-            super::__Buffer<T>>;
-        }
-    }
-
-    /// The send end of a oneshot pipe.
-    pub struct ChanOne<T> {
-        contents: oneshot::client::Oneshot<T>
-    }
-
-    impl<T> ChanOne<T> {
-        pub fn new(contents: oneshot::client::Oneshot<T>) -> ChanOne<T> {
-            ChanOne {
-                contents: contents
-            }
-        }
-    }
-
-    /// The receive end of a oneshot pipe.
-    pub struct PortOne<T> {
-        contents: oneshot::server::Oneshot<T>
-    }
-
-    impl<T> PortOne<T> {
-        pub fn new(contents: oneshot::server::Oneshot<T>) -> PortOne<T> {
-            PortOne {
-                contents: contents
-            }
-        }
-    }
-
-    /// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair.
-    pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
-        let (port, chan) = oneshot::init();
-        (PortOne::new(port), ChanOne::new(chan))
-    }
-
-    impl<T: Send> PortOne<T> {
-        pub fn recv(self) -> T { recv_one(self) }
-        pub fn try_recv(self) -> Option<T> { try_recv_one(self) }
-        pub fn unwrap(self) -> oneshot::server::Oneshot<T> {
-            match self {
-                PortOne { contents: s } => s
-            }
-        }
-    }
-
-    impl<T: Send> ChanOne<T> {
-        pub fn send(self, data: T) { send_one(self, data) }
-        pub fn try_send(self, data: T) -> bool { try_send_one(self, data) }
-        pub fn unwrap(self) -> oneshot::client::Oneshot<T> {
-            match self {
-                ChanOne { contents: s } => s
-            }
-        }
-    }
-
-    /**
-    * Receive a message from a oneshot pipe, failing if the connection was
-    * closed.
-    */
-    pub fn recv_one<T: Send>(port: PortOne<T>) -> T {
-        match port {
-            PortOne { contents: port } => {
-                let oneshot::send(message) = recv(port);
-                message
-            }
-        }
-    }
-
-    /// Receive a message from a oneshot pipe unless the connection was closed.
-    pub fn try_recv_one<T: Send> (port: PortOne<T>) -> Option<T> {
-        match port {
-            PortOne { contents: port } => {
-                let message = try_recv(port);
-
-                if message.is_none() {
-                    None
-                } else {
-                    let oneshot::send(message) = message.unwrap();
-                    Some(message)
-                }
-            }
-        }
-    }
-
-    /// Send a message on a oneshot pipe, failing if the connection was closed.
-    pub fn send_one<T: Send>(chan: ChanOne<T>, data: T) {
-        match chan {
-            ChanOne { contents: chan } => oneshot::client::send(chan, data),
-        }
-    }
-
-    /**
-    * Send a message on a oneshot pipe, or return false if the connection was
-    * closed.
-    */
-    pub fn try_send_one<T: Send>(chan: ChanOne<T>, data: T) -> bool {
-        match chan {
-            ChanOne { contents: chan } => {
-                oneshot::client::try_send(chan, data).is_some()
-            }
-        }
-    }
-
-    // Streams - Make pipes a little easier in general.
-
-    /*proto! streamp (
-        Open:send<T: Send> {
-            data(T) -> Open<T>
-        }
-    )*/
-
-    #[allow(non_camel_case_types)]
-    pub mod streamp {
-        use std::kinds::Send;
-
-        pub fn init<T: Send>() -> (server::Open<T>, client::Open<T>) {
-            pub use std::pipes::HasBuffer;
-            ::std::pipes::entangle()
-        }
-
-        #[allow(non_camel_case_types)]
-        pub enum Open<T> { pub data(T, server::Open<T>), }
-
-        #[allow(non_camel_case_types)]
-        pub mod client {
-            use std::kinds::Send;
-
-            #[allow(non_camel_case_types)]
-            pub fn try_data<T: Send>(pipe: Open<T>, x_0: T) ->
-                ::std::option::Option<Open<T>> {
-                {
-                    use super::data;
-                    let (s, c) = ::std::pipes::entangle();
-                    let message = data(x_0, s);
-                    if ::std::pipes::send(pipe, message) {
-                        ::std::pipes::rt::make_some(c)
-                    } else { ::std::pipes::rt::make_none() }
-                }
-            }
-
-            #[allow(non_camel_case_types)]
-            pub fn data<T: Send>(pipe: Open<T>, x_0: T) -> Open<T> {
-                {
-                    use super::data;
-                    let (s, c) = ::std::pipes::entangle();
-                    let message = data(x_0, s);
-                    ::std::pipes::send(pipe, message);
-                    c
-                }
-            }
-
-            #[allow(non_camel_case_types)]
-            pub type Open<T> = ::std::pipes::SendPacket<super::Open<T>>;
-        }
-
-        #[allow(non_camel_case_types)]
-        pub mod server {
-            #[allow(non_camel_case_types)]
-            pub type Open<T> = ::std::pipes::RecvPacket<super::Open<T>>;
-        }
-    }
-
-    /// An endpoint that can send many messages.
-    #[unsafe_mut_field(endp)]
-    pub struct Chan<T> {
-        endp: Option<streamp::client::Open<T>>
+impl<T: Send> GenericPort<T> for Port<T> {
+    fn recv(&self) -> T {
+        let &Port { x: ref p } = self;
+        p.recv()
     }
 
-    /// An endpoint that can receive many messages.
-    #[unsafe_mut_field(endp)]
-    pub struct Port<T> {
-        endp: Option<streamp::server::Open<T>>,
+    fn try_recv(&self) -> Option<T> {
+        let &Port { x: ref p } = self;
+        p.try_recv()
     }
+}
 
-    /** Creates a `(Port, Chan)` pair.
-
-    These allow sending or receiving an unlimited number of messages.
-
-    */
-    pub fn stream<T:Send>() -> (Port<T>, Chan<T>) {
-        let (s, c) = streamp::init();
-
-        (Port {
-            endp: Some(s)
-        }, Chan {
-            endp: Some(c)
-        })
+impl<T: Send> Peekable<T> for Port<T> {
+    fn peek(&self) -> bool {
+        let &Port { x: ref p } = self;
+        p.peek()
     }
+}
 
-    impl<T: Send> GenericChan<T> for Chan<T> {
-        #[inline]
-        fn send(&self, x: T) {
-            unsafe {
-                let self_endp = transmute_mut(&self.endp);
-                *self_endp = Some(streamp::client::data(self_endp.take_unwrap(), x))
-            }
-        }
+impl<T: Send> GenericChan<T> for SharedChan<T> {
+    fn send(&self, val: T) {
+        let &SharedChan { x: ref c } = self;
+        c.send(val)
     }
+}
 
-    impl<T: Send> GenericSmartChan<T> for Chan<T> {
-        #[inline]
-        fn try_send(&self, x: T) -> bool {
-            unsafe {
-                let self_endp = transmute_mut(&self.endp);
-                match streamp::client::try_data(self_endp.take_unwrap(), x) {
-                    Some(next) => {
-                        *self_endp = Some(next);
-                        true
-                    }
-                    None => false
-                }
-            }
-        }
+impl<T: Send> GenericSmartChan<T> for SharedChan<T> {
+    fn try_send(&self, val: T) -> bool {
+        let &SharedChan { x: ref c } = self;
+        c.try_send(val)
     }
+}
 
-    impl<T: Send> GenericPort<T> for Port<T> {
-        #[inline]
-        fn recv(&self) -> T {
-            unsafe {
-                let self_endp = transmute_mut(&self.endp);
-                let endp = self_endp.take();
-                let streamp::data(x, endp) = recv(endp.unwrap());
-                *self_endp = Some(endp);
-                x
-            }
-        }
-
-        #[inline]
-        fn try_recv(&self) -> Option<T> {
-            unsafe {
-                let self_endp = transmute_mut(&self.endp);
-                let endp = self_endp.take();
-                match try_recv(endp.unwrap()) {
-                    Some(streamp::data(x, endp)) => {
-                        *self_endp = Some(endp);
-                        Some(x)
-                    }
-                    None => None
-                }
-            }
-        }
+impl<T: Send> SendDeferred<T> for SharedChan<T> {
+    fn send_deferred(&self, val: T) {
+        let &SharedChan { x: ref c } = self;
+        c.send_deferred(val)
     }
 
-    impl<T: Send> Peekable<T> for Port<T> {
-        #[inline]
-        fn peek(&self) -> bool {
-            unsafe {
-                let self_endp = transmute_mut(&self.endp);
-                let mut endp = self_endp.take();
-                let peek = match endp {
-                    Some(ref mut endp) => peek(endp),
-                    None => fail!("peeking empty stream")
-                };
-                *self_endp = endp;
-                peek
-            }
-        }
+    fn try_send_deferred(&self, val: T) -> bool {
+        let &SharedChan { x: ref c } = self;
+        c.try_send_deferred(val)
     }
-
 }
 
-#[cfg(test)]
-mod test {
-    use either::Right;
-    use super::{Chan, Port, oneshot, stream};
-
-    #[test]
-    fn test_oneshot() {
-        let (p, c) = oneshot();
-
-        c.send(());
-
-        p.recv()
-    }
-
-    #[test]
-    fn test_peek_terminated() {
-        let (port, chan): (Port<int>, Chan<int>) = stream();
-
-        {
-            // Destroy the channel
-            let _chan = chan;
-        }
-
-        assert!(!port.peek());
+impl<T> Clone for SharedChan<T> {
+    fn clone(&self) -> SharedChan<T> {
+        let &SharedChan { x: ref c } = self;
+        SharedChan { x: c.clone() }
     }
 }
index bb74d9b3ec484b1d3730d74837359891c03ef4f5..132ebc72960117763498599345c2f41b9d632efe 100644 (file)
@@ -150,7 +150,7 @@ pub fn rights<L, R: Clone>(eithers: &[Either<L, R>]) -> ~[R] {
 pub fn partition<L, R>(eithers: ~[Either<L, R>]) -> (~[L], ~[R]) {
     let mut lefts: ~[L] = ~[];
     let mut rights: ~[R] = ~[];
-    for elt in eithers.consume_iter() {
+    for elt in eithers.move_iter() {
         match elt {
             Left(l) => lefts.push(l),
             Right(r) => rights.push(r)
index 84cba254dcf23599258f50f64fdbfdc1637cff30..7a22477685911cf9ee0a52afdc9f882b1ce3f49d 100644 (file)
@@ -19,7 +19,7 @@
 use clone::Clone;
 use cmp::{Eq, Equiv};
 use hash::Hash;
-use iterator::{Iterator, IteratorUtil, FromIterator, Extendable};
+use iterator::{Iterator, FromIterator, Extendable};
 use iterator::{FilterMap, Chain, Repeat, Zip};
 use num;
 use option::{None, Option, Some};
@@ -159,8 +159,8 @@ fn resize(&mut self, new_capacity: uint) {
                                   vec::from_fn(new_capacity, |_| None));
 
         self.size = 0;
-        // consume_rev_iter is more efficient
-        for bucket in old_buckets.consume_rev_iter() {
+        // move_rev_iter is more efficient
+        for bucket in old_buckets.move_rev_iter() {
             self.insert_opt_bucket(bucket);
         }
     }
@@ -470,9 +470,9 @@ pub fn mut_iter<'a>(&'a mut self) -> HashMapMutIterator<'a, K, V> {
     /// Creates a consuming iterator, that is, one that moves each key-value
     /// pair out of the map in arbitrary order. The map cannot be used after
     /// calling this.
-    pub fn consume(self) -> HashMapConsumeIterator<K, V> {
-        // `consume_rev_iter` is more efficient than `consume_iter` for vectors
-        HashMapConsumeIterator {iter: self.buckets.consume_rev_iter()}
+    pub fn move_iter(self) -> HashMapMoveIterator<K, V> {
+        // `move_rev_iter` is more efficient than `move_iter` for vectors
+        HashMapMoveIterator {iter: self.buckets.move_rev_iter()}
     }
 }
 
@@ -524,9 +524,9 @@ pub struct HashMapMutIterator<'self, K, V> {
     priv iter: vec::VecMutIterator<'self, Option<Bucket<K, V>>>,
 }
 
-/// HashMap consume iterator
-pub struct HashMapConsumeIterator<K, V> {
-    priv iter: vec::ConsumeRevIterator<Option<Bucket<K, V>>>,
+/// HashMap move iterator
+pub struct HashMapMoveIterator<K, V> {
+    priv iter: vec::MoveRevIterator<Option<Bucket<K, V>>>,
 }
 
 /// HashSet iterator
@@ -535,9 +535,9 @@ pub struct HashSetIterator<'self, K> {
     priv iter: vec::VecIterator<'self, Option<Bucket<K, ()>>>,
 }
 
-/// HashSet consume iterator
-pub struct HashSetConsumeIterator<K> {
-    priv iter: vec::ConsumeRevIterator<Option<Bucket<K, ()>>>,
+/// HashSet move iterator
+pub struct HashSetMoveIterator<K> {
+    priv iter: vec::MoveRevIterator<Option<Bucket<K, ()>>>,
 }
 
 impl<'self, K, V> Iterator<(&'self K, &'self V)> for HashMapIterator<'self, K, V> {
@@ -566,7 +566,7 @@ fn next(&mut self) -> Option<(&'self K, &'self mut V)> {
     }
 }
 
-impl<K, V> Iterator<(K, V)> for HashMapConsumeIterator<K, V> {
+impl<K, V> Iterator<(K, V)> for HashMapMoveIterator<K, V> {
     #[inline]
     fn next(&mut self) -> Option<(K, V)> {
         for elt in self.iter {
@@ -592,7 +592,7 @@ fn next(&mut self) -> Option<&'self K> {
     }
 }
 
-impl<K> Iterator<K> for HashSetConsumeIterator<K> {
+impl<K> Iterator<K> for HashSetMoveIterator<K> {
     #[inline]
     fn next(&mut self) -> Option<K> {
         for elt in self.iter {
@@ -707,9 +707,9 @@ pub fn iter<'a>(&'a self) -> HashSetIterator<'a, T> {
     /// Creates a consuming iterator, that is, one that moves each value out
     /// of the set in arbitrary order. The set cannot be used after calling
     /// this.
-    pub fn consume(self) -> HashSetConsumeIterator<T> {
-        // `consume_rev_iter` is more efficient than `consume_iter` for vectors
-        HashSetConsumeIterator {iter: self.map.buckets.consume_rev_iter()}
+    pub fn move_iter(self) -> HashSetMoveIterator<T> {
+        // `move_rev_iter` is more efficient than `move_iter` for vectors
+        HashSetMoveIterator {iter: self.map.buckets.move_rev_iter()}
     }
 
     /// Visit the values representing the difference
@@ -724,7 +724,7 @@ pub fn difference_iter<'a>(&'a self, other: &'a HashSet<T>) -> SetAlgebraIter<'a
     /// Visit the values representing the symmetric difference
     pub fn symmetric_difference_iter<'a>(&'a self, other: &'a HashSet<T>)
         -> Chain<SetAlgebraIter<'a, T>, SetAlgebraIter<'a, T>> {
-        self.difference_iter(other).chain_(other.difference_iter(self))
+        self.difference_iter(other).chain(other.difference_iter(self))
     }
 
     /// Visit the values representing the intersection
@@ -740,7 +740,7 @@ pub fn intersection_iter<'a>(&'a self, other: &'a HashSet<T>)
     /// Visit the values representing the union
     pub fn union_iter<'a>(&'a self, other: &'a HashSet<T>)
         -> Chain<HashSetIterator<'a, T>, SetAlgebraIter<'a, T>> {
-        self.iter().chain_(other.difference_iter(self))
+        self.iter().chain(other.difference_iter(self))
     }
 
 }
@@ -881,7 +881,7 @@ fn test_insert_or_update_with() {
     }
 
     #[test]
-    fn test_consume() {
+    fn test_move_iter() {
         let hm = {
             let mut hm = HashMap::new();
 
@@ -891,7 +891,7 @@ fn test_consume() {
             hm
         };
 
-        let v = hm.consume().collect::<~[(char, int)]>();
+        let v = hm.move_iter().collect::<~[(char, int)]>();
         assert!([('a', 1), ('b', 2)] == v || [('b', 2), ('a', 1)] == v);
     }
 
@@ -977,7 +977,7 @@ fn test_find_equiv() {
     fn test_from_iter() {
         let xs = ~[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
 
-        let map: HashMap<int, int> = xs.iter().transform(|&x| x).collect();
+        let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
 
         for &(k, v) in xs.iter() {
             assert_eq!(map.find(&k), Some(&v));
@@ -1169,7 +1169,7 @@ fn test_union() {
     fn test_from_iter() {
         let xs = ~[1, 2, 3, 4, 5, 6, 7, 8, 9];
 
-        let set: HashSet<int> = xs.iter().transform(|&x| x).collect();
+        let set: HashSet<int> = xs.iter().map(|&x| x).collect();
 
         for x in xs.iter() {
             assert!(set.contains(x));
@@ -1177,7 +1177,7 @@ fn test_from_iter() {
     }
 
     #[test]
-    fn test_consume() {
+    fn test_move_iter() {
         let hs = {
             let mut hs = HashSet::new();
 
@@ -1187,7 +1187,7 @@ fn test_consume() {
             hs
         };
 
-        let v = hs.consume().collect::<~[char]>();
+        let v = hs.move_iter().collect::<~[char]>();
         assert!(['a', 'b'] == v || ['b', 'a'] == v);
     }
 }
index 55e60f03ea9c694f6126780a90ee3f951e0e69e4..07572d60917a0246c6f24be086ae26a64b52697f 100644 (file)
@@ -48,6 +48,7 @@
 
 use cast;
 use clone::Clone;
+use c_str::ToCStr;
 use container::Container;
 use int;
 use iterator::Iterator;
@@ -1040,8 +1041,8 @@ pub fn stdin() -> @Reader {
 }
 
 pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
-    let f = do path.to_str().as_c_str |pathbuf| {
-        do "rb".as_c_str |modebuf| {
+    let f = do path.to_c_str().with_ref |pathbuf| {
+        do "rb".to_c_str().with_ref |modebuf| {
             unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) }
         }
     };
@@ -1290,9 +1291,8 @@ fn wb() -> c_int { O_WRONLY as c_int }
         }
     }
     let fd = unsafe {
-        do path.to_str().as_c_str |pathbuf| {
-            libc::open(pathbuf, fflags,
-                       (S_IRUSR | S_IWUSR) as c_int)
+        do path.to_c_str().with_ref |pathbuf| {
+            libc::open(pathbuf, fflags, (S_IRUSR | S_IWUSR) as c_int)
         }
     };
     if fd < (0 as c_int) {
@@ -1574,8 +1574,8 @@ pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
 // FIXME: fileflags // #2004
 pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> {
     unsafe {
-        let f = do path.to_str().as_c_str |pathbuf| {
-            do "w".as_c_str |modebuf| {
+        let f = do path.to_c_str().with_ref |pathbuf| {
+            do "w".to_c_str().with_ref |modebuf| {
                 libc::fopen(pathbuf, modebuf)
             }
         };
@@ -1707,6 +1707,7 @@ pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
     (*bytes).clone()
 }
 
+#[cfg(stage0)]
 pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
     let mut v = with_bytes_writer(f);
 
@@ -1719,6 +1720,11 @@ pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
     }
 }
 
+#[cfg(not(stage0))]
+pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
+    str::from_bytes(with_bytes_writer(f))
+}
+
 // Utility functions
 pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
    uint {
index d10a5541e41a683fef643f9c02aa2957abf2a15c..a7a1c0bede8dbabf761920061f0bb30ffb8da38a 100644 (file)
@@ -49,89 +49,7 @@ pub trait Iterator<A> {
     /// The common use case for the estimate is pre-allocating space to store the results.
     #[inline]
     fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
-}
-
-/// A range iterator able to yield elements from both ends
-pub trait DoubleEndedIterator<A>: Iterator<A> {
-    /// Yield an element from the end of the range, returning `None` if the range is empty.
-    fn next_back(&mut self) -> Option<A>;
-}
-
-/// An object implementing random access indexing by `uint`
-///
-/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.
-pub trait RandomAccessIterator<A>: Iterator<A> {
-    /// Return the number of indexable elements. At most `std::uint::max_value`
-    /// elements are indexable, even if the iterator represents a longer range.
-    fn indexable(&self) -> uint;
-
-    /// Return an element at an index
-    fn idx(&self, index: uint) -> Option<A>;
-}
-
-/// Iterator adaptors provided for every `DoubleEndedIterator` implementation.
-///
-/// In the future these will be default methods instead of a utility trait.
-pub trait DoubleEndedIteratorUtil {
-    /// Flip the direction of the iterator
-    fn invert(self) -> Invert<Self>;
-}
-
-/// Iterator adaptors provided for every `DoubleEndedIterator` implementation.
-///
-/// In the future these will be default methods instead of a utility trait.
-impl<A, T: DoubleEndedIterator<A>> DoubleEndedIteratorUtil for T {
-    /// Flip the direction of the iterator
-    ///
-    /// The inverted iterator flips the ends on an iterator that can already
-    /// be iterated from the front and from the back.
-    ///
-    ///
-    /// If the iterator also implements RandomAccessIterator, the inverted
-    /// iterator is also random access, with the indices starting at the back
-    /// of the original iterator.
-    ///
-    /// Note: Random access with inverted indices still only applies to the first
-    /// `uint::max_value` elements of the original iterator.
-    #[inline]
-    fn invert(self) -> Invert<T> {
-        Invert{iter: self}
-    }
-}
-
-/// An double-ended iterator with the direction inverted
-#[deriving(Clone)]
-pub struct Invert<T> {
-    priv iter: T
-}
 
-impl<A, T: DoubleEndedIterator<A>> Iterator<A> for Invert<T> {
-    #[inline]
-    fn next(&mut self) -> Option<A> { self.iter.next_back() }
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
-}
-
-impl<A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Invert<T> {
-    #[inline]
-    fn next_back(&mut self) -> Option<A> { self.iter.next() }
-}
-
-impl<A, T: DoubleEndedIterator<A> + RandomAccessIterator<A>> RandomAccessIterator<A>
-    for Invert<T> {
-    #[inline]
-    fn indexable(&self) -> uint { self.iter.indexable() }
-    #[inline]
-    fn idx(&self, index: uint) -> Option<A> {
-        self.iter.idx(self.indexable() - index - 1)
-    }
-}
-
-/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
-/// implementations of the `Iterator` trait.
-///
-/// In the future these will be default methods instead of a utility trait.
-pub trait IteratorUtil<A> {
     /// Chain this iterator with another, returning a new iterator which will
     /// finish iterating over the current iterator, and then it will iterate
     /// over the other specified iterator.
@@ -141,12 +59,15 @@ pub trait IteratorUtil<A> {
     /// ~~~ {.rust}
     /// let a = [0];
     /// let b = [1];
-    /// let mut it = a.iter().chain_(b.iter());
+    /// let mut it = a.iter().chain(b.iter());
     /// assert_eq!(it.next().get(), &0);
     /// assert_eq!(it.next().get(), &1);
     /// assert!(it.next().is_none());
     /// ~~~
-    fn chain_<U: Iterator<A>>(self, other: U) -> Chain<Self, U>;
+    #[inline]
+    fn chain<U: Iterator<A>>(self, other: U) -> Chain<Self, U> {
+        Chain{a: self, b: other, flag: false}
+    }
 
     /// Creates an iterator which iterates over both this and the specified
     /// iterators simultaneously, yielding the two elements as pairs. When
@@ -162,9 +83,11 @@ pub trait IteratorUtil<A> {
     /// assert_eq!(it.next().get(), (&0, &1));
     /// assert!(it.next().is_none());
     /// ~~~
-    fn zip<B, U: Iterator<B>>(self, other: U) -> Zip<Self, U>;
+    #[inline]
+    fn zip<B, U: Iterator<B>>(self, other: U) -> Zip<Self, U> {
+        Zip{a: self, b: other}
+    }
 
-    // FIXME: #5898: should be called map
     /// Creates a new iterator which will apply the specified function to each
     /// element returned by the first, yielding the mapped element instead.
     ///
@@ -172,12 +95,15 @@ pub trait IteratorUtil<A> {
     ///
     /// ~~~ {.rust}
     /// let a = [1, 2];
-    /// let mut it = a.iter().transform(|&x| 2 * x);
+    /// let mut it = a.iter().map(|&x| 2 * x);
     /// assert_eq!(it.next().get(), 2);
     /// assert_eq!(it.next().get(), 4);
     /// assert!(it.next().is_none());
     /// ~~~
-    fn transform<'r, B>(self, f: &'r fn(A) -> B) -> Map<'r, A, B, Self>;
+    #[inline]
+    fn map<'r, B>(self, f: &'r fn(A) -> B) -> Map<'r, A, B, Self> {
+        Map{iter: self, f: f}
+    }
 
     /// Creates an iterator which applies the predicate to each element returned
     /// by this iterator. Only elements which have the predicate evaluate to
@@ -191,7 +117,10 @@ pub trait IteratorUtil<A> {
     /// assert_eq!(it.next().get(), &2);
     /// assert!(it.next().is_none());
     /// ~~~
-    fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> Filter<'r, A, Self>;
+    #[inline]
+    fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> Filter<'r, A, Self> {
+        Filter{iter: self, predicate: predicate}
+    }
 
     /// Creates an iterator which both filters and maps elements.
     /// If the specified function returns None, the element is skipped.
@@ -205,7 +134,10 @@ pub trait IteratorUtil<A> {
     /// assert_eq!(it.next().get(), 4);
     /// assert!(it.next().is_none());
     /// ~~~
-    fn filter_map<'r,  B>(self, f: &'r fn(A) -> Option<B>) -> FilterMap<'r, A, B, Self>;
+    #[inline]
+    fn filter_map<'r, B>(self, f: &'r fn(A) -> Option<B>) -> FilterMap<'r, A, B, Self> {
+        FilterMap { iter: self, f: f }
+    }
 
     /// Creates an iterator which yields a pair of the value returned by this
     /// iterator plus the current index of iteration.
@@ -219,7 +151,10 @@ pub trait IteratorUtil<A> {
     /// assert_eq!(it.next().get(), (1, &200));
     /// assert!(it.next().is_none());
     /// ~~~
-    fn enumerate(self) -> Enumerate<Self>;
+    #[inline]
+    fn enumerate(self) -> Enumerate<Self> {
+        Enumerate{iter: self, count: 0}
+    }
 
     /// Creates an iterator which invokes the predicate on elements until it
     /// returns false. Once the predicate returns false, all further elements are
@@ -235,7 +170,10 @@ pub trait IteratorUtil<A> {
     /// assert_eq!(it.next().get(), &1);
     /// assert!(it.next().is_none());
     /// ~~~
-    fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhile<'r, A, Self>;
+    #[inline]
+    fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhile<'r, A, Self> {
+        SkipWhile{iter: self, flag: false, predicate: predicate}
+    }
 
     /// Creates an iterator which yields elements so long as the predicate
     /// returns true. After the predicate returns false for the first time, no
@@ -250,7 +188,10 @@ pub trait IteratorUtil<A> {
     /// assert_eq!(it.next().get(), &2);
     /// assert!(it.next().is_none());
     /// ~~~
-    fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhile<'r, A, Self>;
+    #[inline]
+    fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhile<'r, A, Self> {
+        TakeWhile{iter: self, flag: false, predicate: predicate}
+    }
 
     /// Creates an iterator which skips the first `n` elements of this iterator,
     /// and then it yields all further items.
@@ -264,9 +205,11 @@ pub trait IteratorUtil<A> {
     /// assert_eq!(it.next().get(), &5);
     /// assert!(it.next().is_none());
     /// ~~~
-    fn skip(self, n: uint) -> Skip<Self>;
+    #[inline]
+    fn skip(self, n: uint) -> Skip<Self> {
+        Skip{iter: self, n: n}
+    }
 
-    // FIXME: #5898: should be called take
     /// Creates an iterator which yields the first `n` elements of this
     /// iterator, and then it will always return None.
     ///
@@ -274,13 +217,16 @@ pub trait IteratorUtil<A> {
     ///
     /// ~~~ {.rust}
     /// let a = [1, 2, 3, 4, 5];
-    /// let mut it = a.iter().take_(3);
+    /// let mut it = a.iter().take(3);
     /// assert_eq!(it.next().get(), &1);
     /// assert_eq!(it.next().get(), &2);
     /// assert_eq!(it.next().get(), &3);
     /// assert!(it.next().is_none());
     /// ~~~
-    fn take_(self, n: uint) -> Take<Self>;
+    #[inline]
+    fn take(self, n: uint) -> Take<Self> {
+        Take{iter: self, n: n}
+    }
 
     /// Creates a new iterator which behaves in a similar fashion to foldl.
     /// There is a state which is passed between each iteration and can be
@@ -302,8 +248,11 @@ pub trait IteratorUtil<A> {
     /// assert_eq!(it.next().get(), 120);
     /// assert!(it.next().is_none());
     /// ~~~
+    #[inline]
     fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
-        -> Scan<'r, A, B, Self, St>;
+        -> Scan<'r, A, B, Self, St> {
+        Scan{iter: self, f: f, state: initial_state}
+    }
 
     /// Creates an iterator that maps each element to an iterator,
     /// and yields the elements of the produced iterators
@@ -313,7 +262,7 @@ fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
     /// ~~~ {.rust}
     /// let xs = [2u, 3];
     /// let ys = [0u, 1, 0, 1, 2];
-    /// let mut it = xs.iter().flat_map_(|&x| count(0u, 1).take_(x));
+    /// let mut it = xs.iter().flat_map(|&x| count(0u, 1).take(x));
     /// // Check that `it` has the same elements as `ys`
     /// let mut i = 0;
     /// for x: uint in it {
@@ -321,9 +270,11 @@ fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
     ///     i += 1;
     /// }
     /// ~~~
-    // FIXME: #5898: should be called `flat_map`
-    fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
-        -> FlatMap<'r, A, Self, U>;
+    #[inline]
+    fn flat_map<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
+        -> FlatMap<'r, A, Self, U> {
+        FlatMap{iter: self, f: f, frontiter: None, backiter: None }
+    }
 
     /// Creates an iterator that calls a function with a reference to each
     /// element before yielding it. This is often useful for debugging an
@@ -334,15 +285,17 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     /// ~~~ {.rust}
     ///let xs = [1u, 4, 2, 3, 8, 9, 6];
     ///let sum = xs.iter()
-    ///            .transform(|&x| x)
-    ///            .peek_(|&x| debug!("filtering %u", x))
+    ///            .map(|&x| x)
+    ///            .peek(|&x| debug!("filtering %u", x))
     ///            .filter(|&x| x % 2 == 0)
-    ///            .peek_(|&x| debug!("%u made it through", x))
+    ///            .peek(|&x| debug!("%u made it through", x))
     ///            .sum();
     ///println(sum.to_str());
     /// ~~~
-    // FIXME: #5898: should be called `peek`
-    fn peek_<'r>(self, f: &'r fn(&A)) -> Peek<'r, A, Self>;
+    #[inline]
+    fn peek<'r>(self, f: &'r fn(&A)) -> Peek<'r, A, Self> {
+        Peek{iter: self, f: f}
+    }
 
     /// An adaptation of an external iterator to the for-loop protocol of rust.
     ///
@@ -355,7 +308,17 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     ///     printfln!("%d", i);
     /// }
     /// ~~~
-    fn advance(&mut self, f: &fn(A) -> bool) -> bool;
+    #[inline]
+    fn advance(&mut self, f: &fn(A) -> bool) -> bool {
+        loop {
+            match self.next() {
+                Some(x) => {
+                    if !f(x) { return false; }
+                }
+                None => { return true; }
+            }
+        }
+    }
 
     /// Loops through the entire iterator, collecting all of the elements into
     /// a container implementing `FromIterator`.
@@ -364,10 +327,13 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     ///
     /// ~~~ {.rust}
     /// let a = [1, 2, 3, 4, 5];
-    /// let b: ~[int] = a.iter().transform(|&x| x).collect();
+    /// let b: ~[int] = a.iter().map(|&x| x).collect();
     /// assert!(a == b);
     /// ~~~
-    fn collect<B: FromIterator<A, Self>>(&mut self) -> B;
+    #[inline]
+    fn collect<B: FromIterator<A, Self>>(&mut self) -> B {
+        FromIterator::from_iterator(self)
+    }
 
     /// Loops through the entire iterator, collecting all of the elements into
     /// a unique vector. This is simply collect() specialized for vectors.
@@ -376,10 +342,13 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     ///
     /// ~~~ {.rust}
     /// let a = [1, 2, 3, 4, 5];
-    /// let b: ~[int] = a.iter().transform(|&x| x).to_owned_vec();
+    /// let b: ~[int] = a.iter().map(|&x| x).to_owned_vec();
     /// assert!(a == b);
     /// ~~~
-    fn to_owned_vec(&mut self) -> ~[A];
+    #[inline]
+    fn to_owned_vec(&mut self) -> ~[A] {
+        self.collect()
+    }
 
     /// Loops through `n` iterations, returning the `n`th element of the
     /// iterator.
@@ -392,7 +361,16 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     /// assert!(it.nth(2).get() == &3);
     /// assert!(it.nth(2) == None);
     /// ~~~
-    fn nth(&mut self, n: uint) -> Option<A>;
+    #[inline]
+    fn nth(&mut self, mut n: uint) -> Option<A> {
+        loop {
+            match self.next() {
+                Some(x) => if n == 0 { return Some(x) },
+                None => return None
+            }
+            n -= 1;
+        }
+    }
 
     /// Loops through the entire iterator, returning the last element of the
     /// iterator.
@@ -403,8 +381,12 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     /// let a = [1, 2, 3, 4, 5];
     /// assert!(a.iter().last().get() == &5);
     /// ~~~
-    // FIXME: #5898: should be called `last`
-    fn last_(&mut self) -> Option<A>;
+    #[inline]
+    fn last(&mut self) -> Option<A> {
+        let mut last = None;
+        for x in *self { last = Some(x); }
+        last
+    }
 
     /// Performs a fold operation over the entire iterator, returning the
     /// eventual state at the end of the iteration.
@@ -415,9 +397,18 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     /// let a = [1, 2, 3, 4, 5];
     /// assert!(a.iter().fold(0, |a, &b| a + b) == 15);
     /// ~~~
-    fn fold<B>(&mut self, start: B, f: &fn(B, A) -> B) -> B;
+    #[inline]
+    fn fold<B>(&mut self, init: B, f: &fn(B, A) -> B) -> B {
+        let mut accum = init;
+        loop {
+            match self.next() {
+                Some(x) => { accum = f(accum, x); }
+                None    => { break; }
+            }
+        }
+        accum
+    }
 
-    // FIXME: #5898: should be called len
     /// Counts the number of elements in this iterator.
     ///
     /// # Example
@@ -425,10 +416,13 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     /// ~~~ {.rust}
     /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter();
-    /// assert!(it.len_() == 5);
-    /// assert!(it.len_() == 0);
+    /// assert!(it.len() == 5);
+    /// assert!(it.len() == 0);
     /// ~~~
-    fn len_(&mut self) -> uint;
+    #[inline]
+    fn len(&mut self) -> uint {
+        self.fold(0, |cnt, _x| cnt + 1)
+    }
 
     /// Tests whether the predicate holds true for all elements in the iterator.
     ///
@@ -439,7 +433,11 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     /// assert!(a.iter().all(|&x| *x > 0));
     /// assert!(!a.iter().all(|&x| *x > 2));
     /// ~~~
-    fn all(&mut self, f: &fn(A) -> bool) -> bool;
+    #[inline]
+    fn all(&mut self, f: &fn(A) -> bool) -> bool {
+        for x in *self { if !f(x) { return false; } }
+        true
+    }
 
     /// Tests whether any element of an iterator satisfies the specified
     /// predicate.
@@ -452,179 +450,6 @@ fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
     /// assert!(it.any(|&x| *x == 3));
     /// assert!(!it.any(|&x| *x == 3));
     /// ~~~
-    fn any(&mut self, f: &fn(A) -> bool) -> bool;
-
-    /// Return the first element satisfying the specified predicate
-    fn find_(&mut self, predicate: &fn(&A) -> bool) -> Option<A>;
-
-    /// Return the index of the first element satisfying the specified predicate
-    fn position(&mut self, predicate: &fn(A) -> bool) -> Option<uint>;
-
-    /// Count the number of elements satisfying the specified predicate
-    fn count(&mut self, predicate: &fn(A) -> bool) -> uint;
-
-    /// Return the element that gives the maximum value from the specfied function
-    ///
-    /// # Example
-    ///
-    /// ~~~ {.rust}
-    /// let xs = [-3, 0, 1, 5, -10];
-    /// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
-    /// ~~~
-    fn max_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A>;
-
-    /// Return the element that gives the minimum value from the specfied function
-    ///
-    /// # Example
-    ///
-    /// ~~~ {.rust}
-    /// let xs = [-3, 0, 1, 5, -10];
-    /// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
-    /// ~~~
-    fn min_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A>;
-}
-
-/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
-/// implementations of the `Iterator` trait.
-///
-/// In the future these will be default methods instead of a utility trait.
-impl<A, T: Iterator<A>> IteratorUtil<A> for T {
-    #[inline]
-    fn chain_<U: Iterator<A>>(self, other: U) -> Chain<T, U> {
-        Chain{a: self, b: other, flag: false}
-    }
-
-    #[inline]
-    fn zip<B, U: Iterator<B>>(self, other: U) -> Zip<T, U> {
-        Zip{a: self, b: other}
-    }
-
-    // FIXME: #5898: should be called map
-    #[inline]
-    fn transform<'r, B>(self, f: &'r fn(A) -> B) -> Map<'r, A, B, T> {
-        Map{iter: self, f: f}
-    }
-
-    #[inline]
-    fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> Filter<'r, A, T> {
-        Filter{iter: self, predicate: predicate}
-    }
-
-    #[inline]
-    fn filter_map<'r, B>(self, f: &'r fn(A) -> Option<B>) -> FilterMap<'r, A, B, T> {
-        FilterMap { iter: self, f: f }
-    }
-
-    #[inline]
-    fn enumerate(self) -> Enumerate<T> {
-        Enumerate{iter: self, count: 0}
-    }
-
-    #[inline]
-    fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhile<'r, A, T> {
-        SkipWhile{iter: self, flag: false, predicate: predicate}
-    }
-
-    #[inline]
-    fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhile<'r, A, T> {
-        TakeWhile{iter: self, flag: false, predicate: predicate}
-    }
-
-    #[inline]
-    fn skip(self, n: uint) -> Skip<T> {
-        Skip{iter: self, n: n}
-    }
-
-    // FIXME: #5898: should be called take
-    #[inline]
-    fn take_(self, n: uint) -> Take<T> {
-        Take{iter: self, n: n}
-    }
-
-    #[inline]
-    fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
-        -> Scan<'r, A, B, T, St> {
-        Scan{iter: self, f: f, state: initial_state}
-    }
-
-    #[inline]
-    fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
-        -> FlatMap<'r, A, T, U> {
-        FlatMap{iter: self, f: f, frontiter: None, backiter: None }
-    }
-
-    // FIXME: #5898: should be called `peek`
-    #[inline]
-    fn peek_<'r>(self, f: &'r fn(&A)) -> Peek<'r, A, T> {
-        Peek{iter: self, f: f}
-    }
-
-    /// A shim implementing the `for` loop iteration protocol for iterator objects
-    #[inline]
-    fn advance(&mut self, f: &fn(A) -> bool) -> bool {
-        loop {
-            match self.next() {
-                Some(x) => {
-                    if !f(x) { return false; }
-                }
-                None => { return true; }
-            }
-        }
-    }
-
-    #[inline]
-    fn collect<B: FromIterator<A, T>>(&mut self) -> B {
-        FromIterator::from_iterator(self)
-    }
-
-    #[inline]
-    fn to_owned_vec(&mut self) -> ~[A] {
-        self.collect()
-    }
-
-    /// Return the `n`th item yielded by an iterator.
-    #[inline]
-    fn nth(&mut self, mut n: uint) -> Option<A> {
-        loop {
-            match self.next() {
-                Some(x) => if n == 0 { return Some(x) },
-                None => return None
-            }
-            n -= 1;
-        }
-    }
-
-    /// Return the last item yielded by an iterator.
-    #[inline]
-    fn last_(&mut self) -> Option<A> {
-        let mut last = None;
-        for x in *self { last = Some(x); }
-        last
-    }
-
-    /// Reduce an iterator to an accumulated value
-    #[inline]
-    fn fold<B>(&mut self, init: B, f: &fn(B, A) -> B) -> B {
-        let mut accum = init;
-        loop {
-            match self.next() {
-                Some(x) => { accum = f(accum, x); }
-                None    => { break; }
-            }
-        }
-        accum
-    }
-
-    /// Count the number of items yielded by an iterator
-    #[inline]
-    fn len_(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) }
-
-    #[inline]
-    fn all(&mut self, f: &fn(A) -> bool) -> bool {
-        for x in *self { if !f(x) { return false; } }
-        true
-    }
-
     #[inline]
     fn any(&mut self, f: &fn(A) -> bool) -> bool {
         for x in *self { if f(x) { return true; } }
@@ -633,7 +458,7 @@ fn any(&mut self, f: &fn(A) -> bool) -> bool {
 
     /// Return the first element satisfying the specified predicate
     #[inline]
-    fn find_(&mut self, predicate: &fn(&A) -> bool) -> Option<A> {
+    fn find(&mut self, predicate: &fn(&A) -> bool) -> Option<A> {
         for x in *self {
             if predicate(&x) { return Some(x) }
         }
@@ -653,6 +478,7 @@ fn position(&mut self, predicate: &fn(A) -> bool) -> Option<uint> {
         None
     }
 
+    /// Count the number of elements satisfying the specified predicate
     #[inline]
     fn count(&mut self, predicate: &fn(A) -> bool) -> uint {
         let mut i = 0;
@@ -662,6 +488,14 @@ fn count(&mut self, predicate: &fn(A) -> bool) -> uint {
         i
     }
 
+    /// Return the element that gives the maximum value from the specfied function
+    ///
+    /// # Example
+    ///
+    /// ~~~ {.rust}
+    /// let xs = [-3, 0, 1, 5, -10];
+    /// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
+    /// ~~~
     #[inline]
     fn max_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
         self.fold(None, |max: Option<(A, B)>, x| {
@@ -677,6 +511,14 @@ fn max_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
         }).map_move(|(x, _)| x)
     }
 
+    /// Return the element that gives the minimum value from the specfied function
+    ///
+    /// # Example
+    ///
+    /// ~~~ {.rust}
+    /// let xs = [-3, 0, 1, 5, -10];
+    /// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
+    /// ~~~
     #[inline]
     fn min_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
         self.fold(None, |min: Option<(A, B)>, x| {
@@ -693,6 +535,69 @@ fn min_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
     }
 }
 
+/// A range iterator able to yield elements from both ends
+pub trait DoubleEndedIterator<A>: Iterator<A> {
+    /// Yield an element from the end of the range, returning `None` if the range is empty.
+    fn next_back(&mut self) -> Option<A>;
+
+    /// Flip the direction of the iterator
+    ///
+    /// The inverted iterator flips the ends on an iterator that can already
+    /// be iterated from the front and from the back.
+    ///
+    ///
+    /// If the iterator also implements RandomAccessIterator, the inverted
+    /// iterator is also random access, with the indices starting at the back
+    /// of the original iterator.
+    ///
+    /// Note: Random access with inverted indices still only applies to the first
+    /// `uint::max_value` elements of the original iterator.
+    #[inline]
+    fn invert(self) -> Invert<Self> {
+        Invert{iter: self}
+    }
+}
+
+/// An object implementing random access indexing by `uint`
+///
+/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.
+pub trait RandomAccessIterator<A>: Iterator<A> {
+    /// Return the number of indexable elements. At most `std::uint::max_value`
+    /// elements are indexable, even if the iterator represents a longer range.
+    fn indexable(&self) -> uint;
+
+    /// Return an element at an index
+    fn idx(&self, index: uint) -> Option<A>;
+}
+
+/// An double-ended iterator with the direction inverted
+#[deriving(Clone)]
+pub struct Invert<T> {
+    priv iter: T
+}
+
+impl<A, T: DoubleEndedIterator<A>> Iterator<A> for Invert<T> {
+    #[inline]
+    fn next(&mut self) -> Option<A> { self.iter.next_back() }
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Invert<T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<A> { self.iter.next() }
+}
+
+impl<A, T: DoubleEndedIterator<A> + RandomAccessIterator<A>> RandomAccessIterator<A>
+    for Invert<T> {
+    #[inline]
+    fn indexable(&self) -> uint { self.iter.indexable() }
+    #[inline]
+    fn idx(&self, index: uint) -> Option<A> {
+        self.iter.idx(self.indexable() - index - 1)
+    }
+}
+
 /// A trait for iterators over elements which can be added together
 pub trait AdditiveIterator<A> {
     /// Iterates over the entire iterator, summing up all the elements
@@ -701,7 +606,7 @@ pub trait AdditiveIterator<A> {
     ///
     /// ~~~ {.rust}
     /// let a = [1, 2, 3, 4, 5];
-    /// let mut it = a.iter().transform(|&x| x);
+    /// let mut it = a.iter().map(|&x| x);
     /// assert!(it.sum() == 15);
     /// ~~~
     fn sum(&mut self) -> A;
@@ -790,7 +695,7 @@ pub trait ClonableIterator {
     /// # Example
     ///
     /// ~~~ {.rust}
-    /// let a = count(1,1).take_(1);
+    /// let a = count(1,1).take(1);
     /// let mut cy = a.cycle();
     /// assert_eq!(cy.next(), Some(1));
     /// assert_eq!(cy.next(), Some(1));
@@ -1617,7 +1522,7 @@ mod tests {
 
     #[test]
     fn test_counter_from_iter() {
-        let mut it = count(0, 5).take_(10);
+        let mut it = count(0, 5).take(10);
         let xs: ~[int] = FromIterator::from_iterator(&mut it);
         assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
     }
@@ -1627,7 +1532,7 @@ fn test_iterator_chain() {
         let xs = [0u, 1, 2, 3, 4, 5];
         let ys = [30u, 40, 50, 60];
         let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
-        let mut it = xs.iter().chain_(ys.iter());
+        let mut it = xs.iter().chain(ys.iter());
         let mut i = 0;
         for &x in it {
             assert_eq!(x, expected[i]);
@@ -1635,8 +1540,8 @@ fn test_iterator_chain() {
         }
         assert_eq!(i, expected.len());
 
-        let ys = count(30u, 10).take_(4);
-        let mut it = xs.iter().transform(|&x| x).chain_(ys);
+        let ys = count(30u, 10).take(4);
+        let mut it = xs.iter().map(|&x| x).chain(ys);
         let mut i = 0;
         for x in it {
             assert_eq!(x, expected[i]);
@@ -1647,7 +1552,7 @@ fn test_iterator_chain() {
 
     #[test]
     fn test_filter_map() {
-        let mut it = count(0u, 1u).take_(10)
+        let mut it = count(0u, 1u).take(10)
             .filter_map(|x| if x.is_even() { Some(x*x) } else { None });
         assert_eq!(it.collect::<~[uint]>(), ~[0*0, 2*2, 4*4, 6*6, 8*8]);
     }
@@ -1704,7 +1609,7 @@ fn test_iterator_skip() {
     fn test_iterator_take() {
         let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
         let ys = [0u, 1, 2, 3, 5];
-        let mut it = xs.iter().take_(5);
+        let mut it = xs.iter().take(5);
         let mut i = 0;
         for &x in it {
             assert_eq!(x, ys[i]);
@@ -1736,7 +1641,7 @@ fn add(old: &mut int, new: &uint) -> Option<float> {
     fn test_iterator_flat_map() {
         let xs = [0u, 3, 6];
         let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8];
-        let mut it = xs.iter().flat_map_(|&x| count(x, 1).take_(3));
+        let mut it = xs.iter().flat_map(|&x| count(x, 1).take(3));
         let mut i = 0;
         for x in it {
             assert_eq!(x, ys[i]);
@@ -1751,8 +1656,8 @@ fn test_peek() {
         let mut n = 0;
 
         let ys = xs.iter()
-                   .transform(|&x| x)
-                   .peek_(|_| n += 1)
+                   .map(|&x| x)
+                   .peek(|_| n += 1)
                    .collect::<~[uint]>();
 
         assert_eq!(n, xs.len());
@@ -1783,13 +1688,13 @@ fn count(st: &mut uint) -> Option<uint> {
     #[test]
     fn test_cycle() {
         let cycle_len = 3;
-        let it = count(0u, 1).take_(cycle_len).cycle();
+        let it = count(0u, 1).take(cycle_len).cycle();
         assert_eq!(it.size_hint(), (uint::max_value, None));
-        for (i, x) in it.take_(100).enumerate() {
+        for (i, x) in it.take(100).enumerate() {
             assert_eq!(i % cycle_len, x);
         }
 
-        let mut it = count(0u, 1).take_(0).cycle();
+        let mut it = count(0u, 1).take(0).cycle();
         assert_eq!(it.size_hint(), (0, Some(0)));
         assert_eq!(it.next(), None);
     }
@@ -1805,48 +1710,48 @@ fn test_iterator_nth() {
     #[test]
     fn test_iterator_last() {
         let v = &[0, 1, 2, 3, 4];
-        assert_eq!(v.iter().last_().unwrap(), &4);
-        assert_eq!(v.slice(0, 1).iter().last_().unwrap(), &0);
+        assert_eq!(v.iter().last().unwrap(), &4);
+        assert_eq!(v.slice(0, 1).iter().last().unwrap(), &0);
     }
 
     #[test]
     fn test_iterator_len() {
         let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        assert_eq!(v.slice(0, 4).iter().len_(), 4);
-        assert_eq!(v.slice(0, 10).iter().len_(), 10);
-        assert_eq!(v.slice(0, 0).iter().len_(), 0);
+        assert_eq!(v.slice(0, 4).iter().len(), 4);
+        assert_eq!(v.slice(0, 10).iter().len(), 10);
+        assert_eq!(v.slice(0, 0).iter().len(), 0);
     }
 
     #[test]
     fn test_iterator_sum() {
         let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        assert_eq!(v.slice(0, 4).iter().transform(|&x| x).sum(), 6);
-        assert_eq!(v.iter().transform(|&x| x).sum(), 55);
-        assert_eq!(v.slice(0, 0).iter().transform(|&x| x).sum(), 0);
+        assert_eq!(v.slice(0, 4).iter().map(|&x| x).sum(), 6);
+        assert_eq!(v.iter().map(|&x| x).sum(), 55);
+        assert_eq!(v.slice(0, 0).iter().map(|&x| x).sum(), 0);
     }
 
     #[test]
     fn test_iterator_product() {
         let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        assert_eq!(v.slice(0, 4).iter().transform(|&x| x).product(), 0);
-        assert_eq!(v.slice(1, 5).iter().transform(|&x| x).product(), 24);
-        assert_eq!(v.slice(0, 0).iter().transform(|&x| x).product(), 1);
+        assert_eq!(v.slice(0, 4).iter().map(|&x| x).product(), 0);
+        assert_eq!(v.slice(1, 5).iter().map(|&x| x).product(), 24);
+        assert_eq!(v.slice(0, 0).iter().map(|&x| x).product(), 1);
     }
 
     #[test]
     fn test_iterator_max() {
         let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        assert_eq!(v.slice(0, 4).iter().transform(|&x| x).max(), Some(3));
-        assert_eq!(v.iter().transform(|&x| x).max(), Some(10));
-        assert_eq!(v.slice(0, 0).iter().transform(|&x| x).max(), None);
+        assert_eq!(v.slice(0, 4).iter().map(|&x| x).max(), Some(3));
+        assert_eq!(v.iter().map(|&x| x).max(), Some(10));
+        assert_eq!(v.slice(0, 0).iter().map(|&x| x).max(), None);
     }
 
     #[test]
     fn test_iterator_min() {
         let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        assert_eq!(v.slice(0, 4).iter().transform(|&x| x).min(), Some(0));
-        assert_eq!(v.iter().transform(|&x| x).min(), Some(0));
-        assert_eq!(v.slice(0, 0).iter().transform(|&x| x).min(), None);
+        assert_eq!(v.slice(0, 4).iter().map(|&x| x).min(), Some(0));
+        assert_eq!(v.iter().map(|&x| x).min(), Some(0));
+        assert_eq!(v.slice(0, 0).iter().map(|&x| x).min(), None);
     }
 
     #[test]
@@ -1859,43 +1764,43 @@ fn test_iterator_size_hint() {
         assert_eq!(c.size_hint(), (uint::max_value, None));
         assert_eq!(vi.size_hint(), (10, Some(10)));
 
-        assert_eq!(c.take_(5).size_hint(), (5, Some(5)));
+        assert_eq!(c.take(5).size_hint(), (5, Some(5)));
         assert_eq!(c.skip(5).size_hint().second(), None);
         assert_eq!(c.take_while(|_| false).size_hint(), (0, None));
         assert_eq!(c.skip_while(|_| false).size_hint(), (0, None));
         assert_eq!(c.enumerate().size_hint(), (uint::max_value, None));
-        assert_eq!(c.chain_(vi.transform(|&i| i)).size_hint(), (uint::max_value, None));
+        assert_eq!(c.chain(vi.map(|&i| i)).size_hint(), (uint::max_value, None));
         assert_eq!(c.zip(vi).size_hint(), (10, Some(10)));
         assert_eq!(c.scan(0, |_,_| Some(0)).size_hint(), (0, None));
         assert_eq!(c.filter(|_| false).size_hint(), (0, None));
-        assert_eq!(c.transform(|_| 0).size_hint(), (uint::max_value, None));
+        assert_eq!(c.map(|_| 0).size_hint(), (uint::max_value, None));
         assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
 
-        assert_eq!(vi.take_(5).size_hint(), (5, Some(5)));
-        assert_eq!(vi.take_(12).size_hint(), (10, Some(10)));
+        assert_eq!(vi.take(5).size_hint(), (5, Some(5)));
+        assert_eq!(vi.take(12).size_hint(), (10, Some(10)));
         assert_eq!(vi.skip(3).size_hint(), (7, Some(7)));
         assert_eq!(vi.skip(12).size_hint(), (0, Some(0)));
         assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10)));
         assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10)));
         assert_eq!(vi.enumerate().size_hint(), (10, Some(10)));
-        assert_eq!(vi.chain_(v2.iter()).size_hint(), (13, Some(13)));
+        assert_eq!(vi.chain(v2.iter()).size_hint(), (13, Some(13)));
         assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3)));
         assert_eq!(vi.scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
         assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10)));
-        assert_eq!(vi.transform(|i| i+1).size_hint(), (10, Some(10)));
+        assert_eq!(vi.map(|i| i+1).size_hint(), (10, Some(10)));
         assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10)));
     }
 
     #[test]
     fn test_collect() {
         let a = ~[1, 2, 3, 4, 5];
-        let b: ~[int] = a.iter().transform(|&x| x).collect();
+        let b: ~[int] = a.iter().map(|&x| x).collect();
         assert_eq!(a, b);
     }
 
     #[test]
     fn test_all() {
-        let v = ~&[1, 2, 3, 4, 5];
+        let v: ~&[int] = ~&[1, 2, 3, 4, 5];
         assert!(v.iter().all(|&x| x < 10));
         assert!(!v.iter().all(|&x| x.is_even()));
         assert!(!v.iter().all(|&x| x > 100));
@@ -1904,7 +1809,7 @@ fn test_all() {
 
     #[test]
     fn test_any() {
-        let v = ~&[1, 2, 3, 4, 5];
+        let v: ~&[int] = ~&[1, 2, 3, 4, 5];
         assert!(v.iter().any(|&x| x < 10));
         assert!(v.iter().any(|&x| x.is_even()));
         assert!(!v.iter().any(|&x| x > 100));
@@ -1913,10 +1818,10 @@ fn test_any() {
 
     #[test]
     fn test_find() {
-        let v = &[1, 3, 9, 27, 103, 14, 11];
-        assert_eq!(*v.iter().find_(|x| *x & 1 == 0).unwrap(), 14);
-        assert_eq!(*v.iter().find_(|x| *x % 3 == 0).unwrap(), 3);
-        assert!(v.iter().find_(|x| *x % 12 == 0).is_none());
+        let v: &[int] = &[1, 3, 9, 27, 103, 14, 11];
+        assert_eq!(*v.iter().find(|x| *x & 1 == 0).unwrap(), 14);
+        assert_eq!(*v.iter().find(|x| *x % 3 == 0).unwrap(), 3);
+        assert!(v.iter().find(|x| *x % 12 == 0).is_none());
     }
 
     #[test]
@@ -1937,13 +1842,13 @@ fn test_count() {
 
     #[test]
     fn test_max_by() {
-        let xs = [-3, 0, 1, 5, -10];
+        let xs: &[int] = &[-3, 0, 1, 5, -10];
         assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
     }
 
     #[test]
     fn test_min_by() {
-        let xs = [-3, 0, 1, 5, -10];
+        let xs: &[int] = &[-3, 0, 1, 5, -10];
         assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
     }
 
@@ -1953,13 +1858,13 @@ fn test_invert() {
         let mut it = xs.iter();
         it.next();
         it.next();
-        assert_eq!(it.invert().transform(|&x| x).collect::<~[int]>(), ~[16, 14, 12, 10, 8, 6]);
+        assert_eq!(it.invert().map(|&x| x).collect::<~[int]>(), ~[16, 14, 12, 10, 8, 6]);
     }
 
     #[test]
     fn test_double_ended_map() {
         let xs = [1, 2, 3, 4, 5, 6];
-        let mut it = xs.iter().transform(|&x| x * -1);
+        let mut it = xs.iter().map(|&x| x * -1);
         assert_eq!(it.next(), Some(-1));
         assert_eq!(it.next(), Some(-2));
         assert_eq!(it.next_back(), Some(-6));
@@ -1993,7 +1898,7 @@ fn test_double_ended_filter_map() {
     fn test_double_ended_chain() {
         let xs = [1, 2, 3, 4, 5];
         let ys = ~[7, 9, 11];
-        let mut it = xs.iter().chain_(ys.iter()).invert();
+        let mut it = xs.iter().chain(ys.iter()).invert();
         assert_eq!(it.next().unwrap(), &11)
         assert_eq!(it.next().unwrap(), &9)
         assert_eq!(it.next_back().unwrap(), &1)
@@ -2029,7 +1934,7 @@ fn check_randacc_iter<A: Eq, T: Clone + RandomAccessIterator<A>>(a: T, len: uint
     fn test_double_ended_flat_map() {
         let u = [0u,1];
         let v = [5,6,7,8];
-        let mut it = u.iter().flat_map_(|x| v.slice(*x, v.len()).iter());
+        let mut it = u.iter().flat_map(|x| v.slice(*x, v.len()).iter());
         assert_eq!(it.next_back().unwrap(), &8);
         assert_eq!(it.next().unwrap(),      &5);
         assert_eq!(it.next_back().unwrap(), &7);
@@ -2046,7 +1951,7 @@ fn test_double_ended_flat_map() {
     fn test_random_access_chain() {
         let xs = [1, 2, 3, 4, 5];
         let ys = ~[7, 9, 11];
-        let mut it = xs.iter().chain_(ys.iter());
+        let mut it = xs.iter().chain(ys.iter());
         assert_eq!(it.idx(0).unwrap(), &1);
         assert_eq!(it.idx(5).unwrap(), &7);
         assert_eq!(it.idx(7).unwrap(), &11);
@@ -2091,10 +1996,10 @@ fn test_random_access_zip() {
     fn test_random_access_take() {
         let xs = [1, 2, 3, 4, 5];
         let empty: &[int] = [];
-        check_randacc_iter(xs.iter().take_(3), 3);
-        check_randacc_iter(xs.iter().take_(20), xs.len());
-        check_randacc_iter(xs.iter().take_(0), 0);
-        check_randacc_iter(empty.iter().take_(2), 0);
+        check_randacc_iter(xs.iter().take(3), 3);
+        check_randacc_iter(xs.iter().take(20), xs.len());
+        check_randacc_iter(xs.iter().take(0), 0);
+        check_randacc_iter(empty.iter().take(2), 0);
     }
 
     #[test]
@@ -2109,8 +2014,8 @@ fn test_random_access_skip() {
     fn test_random_access_peek() {
         let xs = [1, 2, 3, 4, 5];
 
-        // test .transform and .peek_ that don't implement Clone
-        let it = xs.iter().peek_(|_| {});
+        // test .map and .peek that don't implement Clone
+        let it = xs.iter().peek(|_| {});
         assert_eq!(xs.len(), it.indexable());
         for (i, elt) in xs.iter().enumerate() {
             assert_eq!(Some(elt), it.idx(i));
@@ -2119,11 +2024,11 @@ fn test_random_access_peek() {
     }
 
     #[test]
-    fn test_random_access_transform() {
+    fn test_random_access_map() {
         let xs = [1, 2, 3, 4, 5];
 
-        // test .transform and .peek_ that don't implement Clone
-        let it = xs.iter().transform(|x| *x);
+        // test .map and .peek that don't implement Clone
+        let it = xs.iter().map(|x| *x);
         assert_eq!(xs.len(), it.indexable());
         for (i, elt) in xs.iter().enumerate() {
             assert_eq!(Some(*elt), it.idx(i));
@@ -2134,7 +2039,7 @@ fn test_random_access_transform() {
     fn test_random_access_cycle() {
         let xs = [1, 2, 3, 4, 5];
         let empty: &[int] = [];
-        check_randacc_iter(xs.iter().cycle().take_(27), 27);
+        check_randacc_iter(xs.iter().cycle().take(27), 27);
         check_randacc_iter(empty.iter().cycle(), 0);
     }
 
index f96d3ce263ec109aa5542f53c61ef184e9313099..678704fe0983308ee45bd5a6afbc051f76834721 100644 (file)
@@ -2652,7 +2652,7 @@ pub fn execve(prog: *c_char, argv: **c_char, envp: **c_char)
                 pub fn execvpe(c: *c_char, argv: **c_char, envp: **c_char)
                                -> c_int;
                 #[link_name = "_getcwd"]
-                pub fn getcwd(buf: *c_char, size: size_t) -> *c_char;
+                pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char;
                 #[link_name = "_getpid"]
                 pub fn getpid() -> c_int;
                 #[link_name = "_isatty"]
@@ -2804,7 +2804,7 @@ pub fn execve(prog: *c_char, argv: **c_char, envp: **c_char)
                 pub fn execvp(c: *c_char, argv: **c_char) -> c_int;
                 pub fn fork() -> pid_t;
                 pub fn fpathconf(filedes: c_int, name: c_int) -> c_long;
-                pub fn getcwd(buf: *c_char, size: size_t) -> *c_char;
+                pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char;
                 pub fn getegid() -> gid_t;
                 pub fn geteuid() -> uid_t;
                 pub fn getgid() -> gid_t ;
index 6e11d14aea9a316d069403083e9e97af069a6115..7de55f48317a556d8c66067fc0b010e5552779ca 100644 (file)
 use os;
 use either::*;
 use rt;
-use rt::OldTaskContext;
 use rt::logging::{Logger, StdErrLogger};
 
 /// Turns on logging to stdout globally
 pub fn console_on() {
-    if rt::context() == OldTaskContext {
-        unsafe {
-            rustrt::rust_log_console_on();
-        }
-    } else {
-        rt::logging::console_on();
-    }
+    rt::logging::console_on();
 }
 
 /**
@@ -41,45 +34,24 @@ pub fn console_off() {
         return;
     }
 
-    if rt::context() == OldTaskContext {
-        unsafe {
-            rustrt::rust_log_console_off();
-        }
-    } else {
-        rt::logging::console_off();
-    }
+    rt::logging::console_off();
 }
 
 #[cfg(not(test))]
 #[lang="log_type"]
 #[allow(missing_doc)]
-pub fn log_type<T>(level: u32, object: &T) {
-    use cast;
-    use container::Container;
+pub fn log_type<T>(_level: u32, object: &T) {
     use io;
-    use libc;
     use repr;
-    use rt;
     use str;
-    use vec;
 
     let bytes = do io::with_bytes_writer |writer| {
         repr::write_repr(writer, object);
     };
 
-    match rt::context() {
-        rt::OldTaskContext => {
-            unsafe {
-                let len = bytes.len() as libc::size_t;
-                rustrt::rust_log_str(level, cast::transmute(vec::raw::to_ptr(bytes)), len);
-            }
-        }
-        _ => {
-            // XXX: Bad allocation
-            let msg = str::from_bytes(bytes);
-            newsched_log_str(msg);
-        }
-    }
+    // XXX: Bad allocation
+    let msg = str::from_bytes(bytes);
+    newsched_log_str(msg);
 }
 
 fn newsched_log_str(msg: ~str) {
@@ -100,15 +72,3 @@ fn newsched_log_str(msg: ~str) {
         }
     }
 }
-
-pub mod rustrt {
-    use libc;
-
-    extern {
-        pub fn rust_log_console_on();
-        pub fn rust_log_console_off();
-        pub fn rust_log_str(level: u32,
-                            string: *libc::c_char,
-                            size: libc::size_t);
-    }
-}
index 81b7662e58168e6b86ea6a759471800a3af9b6e6..3507dc9d2b233543bdf76c6f2cb31f43d2cfd548 100644 (file)
@@ -33,12 +33,6 @@ fn ne(&self, _other: &()) -> bool { false }
 impl Ord for () {
     #[inline]
     fn lt(&self, _other: &()) -> bool { false }
-    #[inline]
-    fn le(&self, _other: &()) -> bool { true }
-    #[inline]
-    fn ge(&self, _other: &()) -> bool { true }
-    #[inline]
-    fn gt(&self, _other: &()) -> bool { false }
 }
 
 #[cfg(not(test))]
index b692bedebfd54f0ed17b39f5fcc99701abec5d32..41da9a6ccbe481a3a559e588a9bc4de5d642ca55 100644 (file)
@@ -130,12 +130,6 @@ impl Num for $T {}
 impl Ord for $T {
     #[inline]
     fn lt(&self, other: &$T) -> bool { return (*self) < (*other); }
-    #[inline]
-    fn le(&self, other: &$T) -> bool { return (*self) <= (*other); }
-    #[inline]
-    fn ge(&self, other: &$T) -> bool { return (*self) >= (*other); }
-    #[inline]
-    fn gt(&self, other: &$T) -> bool { return (*self) > (*other); }
 }
 
 #[cfg(not(test))]
index 29b8f29d87d3f866a37bff576ea9e408be768687..86b5b4ddfc09f4318f5fd94dc2f9ad859014c5ac 100644 (file)
@@ -131,12 +131,6 @@ impl Num for $T {}
 impl Ord for $T {
     #[inline]
     fn lt(&self, other: &$T) -> bool { (*self) < (*other) }
-    #[inline]
-    fn le(&self, other: &$T) -> bool { (*self) <= (*other) }
-    #[inline]
-    fn ge(&self, other: &$T) -> bool { (*self) >= (*other) }
-    #[inline]
-    fn gt(&self, other: &$T) -> bool { (*self) > (*other) }
 }
 
 #[cfg(not(test))]
index 66b30d8dd031c288eb2200fd4f35d69553f5a35b..c1999ae47d61a79df63c9b3f43ffbe90b08fd240 100644 (file)
@@ -134,7 +134,7 @@ pub fn mut_iter<'r>(&'r mut self) -> OptionIterator<&'r mut T> {
 
     /// Return a consuming iterator over the possibly contained value
     #[inline]
-    pub fn consume(self) -> OptionIterator<T> {
+    pub fn move_iter(self) -> OptionIterator<T> {
         OptionIterator{opt: self}
     }
 
index f246a61a4d580d8308aaa93e0885a37a6842a7f5..c916be79c53e5a3fa13c5e0d072c3139e3a149ad 100644 (file)
 
 #[allow(missing_doc)];
 
-use cast;
+use c_str::ToCStr;
 use clone::Clone;
 use container::Container;
 use io;
-use iterator::{IteratorUtil, range};
+use iterator::range;
 use libc;
 use libc::{c_char, c_void, c_int, size_t};
 use libc::FILE;
@@ -61,11 +61,8 @@ pub mod rustrt {
     use libc;
 
     extern {
-        pub fn rust_get_argc() -> c_int;
-        pub fn rust_get_argv() -> **c_char;
         pub fn rust_path_is_dir(path: *libc::c_char) -> c_int;
         pub fn rust_path_exists(path: *libc::c_char) -> c_int;
-        pub fn rust_set_exit_status(code: libc::intptr_t);
     }
 }
 
@@ -73,14 +70,15 @@ pub mod rustrt {
 static BUF_BYTES : uint = 2048u;
 
 pub fn getcwd() -> Path {
-    let buf = [0 as libc::c_char, ..BUF_BYTES];
-    unsafe {
-        if(0 as *libc::c_char == libc::getcwd(
-            &buf[0],
-            BUF_BYTES as libc::size_t)) {
-            fail!();
+    let mut buf = [0 as libc::c_char, ..BUF_BYTES];
+    do buf.as_mut_buf |buf, len| {
+        unsafe {
+            if libc::getcwd(buf, len as size_t).is_null() {
+                fail!()
+            }
+
+            Path(str::raw::from_c_str(buf as *c_char))
         }
-        Path(str::raw::from_c_str(&buf[0]))
     }
 }
 
@@ -91,7 +89,7 @@ pub fn fill_charp_buf(f: &fn(*mut c_char, size_t) -> bool) -> Option<~str> {
     do buf.as_mut_buf |b, sz| {
         if f(b, sz as size_t) {
             unsafe {
-                Some(str::raw::from_buf(b as *u8))
+                Some(str::raw::from_c_str(b as *c_char))
             }
         } else {
             None
@@ -241,11 +239,13 @@ fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] {
 pub fn getenv(n: &str) -> Option<~str> {
     unsafe {
         do with_env_lock {
-            let s = n.as_c_str(|s| libc::getenv(s as *libc::c_char));
-            if ptr::null::<u8>() == cast::transmute(s) {
+            let s = do n.to_c_str().with_ref |buf| {
+                libc::getenv(buf)
+            };
+            if s.is_null() {
                 None
             } else {
-                Some(str::raw::from_buf(cast::transmute(s)))
+                Some(str::raw::from_c_str(s))
             }
         }
     }
@@ -274,8 +274,8 @@ pub fn getenv(n: &str) -> Option<~str> {
 pub fn setenv(n: &str, v: &str) {
     unsafe {
         do with_env_lock {
-            do n.to_str().as_c_str |nbuf| {
-                do v.to_str().as_c_str |vbuf| {
+            do n.to_c_str().with_ref |nbuf| {
+                do v.to_c_str().with_ref |vbuf| {
                     libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
                 }
             }
@@ -306,7 +306,7 @@ pub fn unsetenv(n: &str) {
     fn _unsetenv(n: &str) {
         unsafe {
             do with_env_lock {
-                do n.to_str().as_c_str |nbuf| {
+                do n.to_c_str().with_ref |nbuf| {
                     libc::funcs::posix01::unistd::unsetenv(nbuf);
                 }
             }
@@ -328,7 +328,7 @@ fn _unsetenv(n: &str) {
 }
 
 pub fn fdopen(fd: c_int) -> *FILE {
-    do "r".as_c_str |modebuf| {
+    do "r".to_c_str().with_ref |modebuf| {
         unsafe {
             libc::fdopen(fd, modebuf)
         }
@@ -461,18 +461,18 @@ fn load_self() -> Option<~str> {
         unsafe {
             use libc::funcs::posix01::unistd::readlink;
 
-            let mut path_str = str::with_capacity(TMPBUF_SZ);
-            let len = do path_str.as_c_str |buf| {
-                let buf = buf as *mut c_char;
-                do "/proc/self/exe".as_c_str |proc_self_buf| {
-                    readlink(proc_self_buf, buf, TMPBUF_SZ as size_t)
+            let mut path = [0 as c_char, .. TMPBUF_SZ];
+
+            do path.as_mut_buf |buf, len| {
+                let len = do "/proc/self/exe".to_c_str().with_ref |proc_self_buf| {
+                    readlink(proc_self_buf, buf, len as size_t) as uint
+                };
+
+                if len == -1 {
+                    None
+                } else {
+                    Some(str::raw::from_buf_len(buf as *u8, len))
                 }
-            };
-            if len == -1 {
-                None
-            } else {
-                str::raw::set_len(&mut path_str, len as uint);
-                Some(path_str)
             }
         }
     }
@@ -593,7 +593,7 @@ pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
 /// Indicates whether a path represents a directory
 pub fn path_is_dir(p: &Path) -> bool {
     unsafe {
-        do p.to_str().as_c_str |buf| {
+        do p.to_c_str().with_ref |buf| {
             rustrt::rust_path_is_dir(buf) != 0 as c_int
         }
     }
@@ -602,7 +602,7 @@ pub fn path_is_dir(p: &Path) -> bool {
 /// Indicates whether a path exists
 pub fn path_exists(p: &Path) -> bool {
     unsafe {
-        do p.to_str().as_c_str |buf| {
+        do p.to_c_str().with_ref |buf| {
             rustrt::rust_path_exists(buf) != 0 as c_int
         }
     }
@@ -637,7 +637,7 @@ fn mkdir(p: &Path, _mode: c_int) -> bool {
             use os::win32::as_utf16_p;
             // FIXME: turn mode into something useful? #2623
             do as_utf16_p(p.to_str()) |buf| {
-                libc::CreateDirectoryW(buf, cast::transmute(0))
+                libc::CreateDirectoryW(buf, ptr::mut_null())
                     != (0 as libc::BOOL)
             }
         }
@@ -645,7 +645,7 @@ fn mkdir(p: &Path, _mode: c_int) -> bool {
 
     #[cfg(unix)]
     fn mkdir(p: &Path, mode: c_int) -> bool {
-        do p.to_str().as_c_str |buf| {
+        do p.to_c_str().with_ref |buf| {
             unsafe {
                 libc::mkdir(buf, mode as libc::mode_t) == (0 as c_int)
             }
@@ -694,13 +694,15 @@ unsafe fn get_list(p: &Path) -> ~[~str] {
             extern {
                 fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
             }
-            let input = p.to_str();
             let mut strings = ~[];
-            let input_ptr = ::cast::transmute(&input[0]);
             debug!("os::list_dir -- BEFORE OPENDIR");
-            let dir_ptr = opendir(input_ptr);
+
+            let dir_ptr = do p.to_c_str().with_ref |buf| {
+                opendir(buf)
+            };
+
             if (dir_ptr as uint != 0) {
-        debug!("os::list_dir -- opendir() SUCCESS");
+                debug!("os::list_dir -- opendir() SUCCESS");
                 let mut entry_ptr = readdir(dir_ptr);
                 while (entry_ptr as uint != 0) {
                     strings.push(str::raw::from_c_str(rust_list_dir_val(
@@ -710,7 +712,7 @@ unsafe fn get_list(p: &Path) -> ~[~str] {
                 closedir(dir_ptr);
             }
             else {
-        debug!("os::list_dir -- opendir() FAILURE");
+                debug!("os::list_dir -- opendir() FAILURE");
             }
             debug!(
                 "os::list_dir -- AFTER -- #: %?",
@@ -726,6 +728,7 @@ unsafe fn get_list(p: &Path) -> ~[~str] {
                 FindNextFileW,
                 FindClose,
             };
+            use libc::types::os::arch::extra::HANDLE;
             use os::win32::{
                 as_utf16_p
             };
@@ -740,10 +743,7 @@ fn star(p: &Path) -> Path { p.push("*") }
             do as_utf16_p(star(p).to_str()) |path_ptr| {
                 let mut strings = ~[];
                 let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
-                let find_handle =
-                    FindFirstFileW(
-                        path_ptr,
-                        ::cast::transmute(wfd_ptr));
+                let find_handle = FindFirstFileW(path_ptr, wfd_ptr as HANDLE);
                 if find_handle as libc::c_int != INVALID_HANDLE_VALUE {
                     let mut more_files = 1 as libc::c_int;
                     while more_files != 0 {
@@ -757,9 +757,7 @@ fn star(p: &Path) -> Path { p.push("*") }
                             let fp_str = str::from_utf16(fp_vec);
                             strings.push(fp_str);
                         }
-                        more_files = FindNextFileW(
-                            find_handle,
-                            ::cast::transmute(wfd_ptr));
+                        more_files = FindNextFileW(find_handle, wfd_ptr as HANDLE);
                     }
                     FindClose(find_handle);
                     free(wfd_ptr)
@@ -767,7 +765,7 @@ fn star(p: &Path) -> Path { p.push("*") }
                 strings
             }
         }
-        do get_list(p).consume_iter().filter |filename| {
+        do get_list(p).move_iter().filter |filename| {
             "." != *filename && ".." != *filename
         }.collect()
     }
@@ -821,7 +819,7 @@ fn rmdir(p: &Path) -> bool {
 
     #[cfg(unix)]
     fn rmdir(p: &Path) -> bool {
-        do p.to_str().as_c_str |buf| {
+        do p.to_c_str().with_ref |buf| {
             unsafe {
                 libc::rmdir(buf) == (0 as c_int)
             }
@@ -846,7 +844,7 @@ fn chdir(p: &Path) -> bool {
 
     #[cfg(unix)]
     fn chdir(p: &Path) -> bool {
-        do p.to_str().as_c_str |buf| {
+        do p.to_c_str().with_ref |buf| {
             unsafe {
                 libc::chdir(buf) == (0 as c_int)
             }
@@ -874,8 +872,8 @@ fn do_copy_file(from: &Path, to: &Path) -> bool {
     #[cfg(unix)]
     fn do_copy_file(from: &Path, to: &Path) -> bool {
         unsafe {
-            let istream = do from.to_str().as_c_str |fromp| {
-                do "rb".as_c_str |modebuf| {
+            let istream = do from.to_c_str().with_ref |fromp| {
+                do "rb".to_c_str().with_ref |modebuf| {
                     libc::fopen(fromp, modebuf)
                 }
             };
@@ -886,8 +884,8 @@ fn do_copy_file(from: &Path, to: &Path) -> bool {
             let from_mode = from.get_mode().expect("copy_file: couldn't get permissions \
                                                     for source file");
 
-            let ostream = do to.to_str().as_c_str |top| {
-                do "w+b".as_c_str |modebuf| {
+            let ostream = do to.to_c_str().with_ref |top| {
+                do "w+b".to_c_str().with_ref |modebuf| {
                     libc::fopen(top, modebuf)
                 }
             };
@@ -919,7 +917,7 @@ fn do_copy_file(from: &Path, to: &Path) -> bool {
             fclose(ostream);
 
             // Give the new file the old file's permissions
-            if do to.to_str().as_c_str |to_buf| {
+            if do to.to_c_str().with_ref |to_buf| {
                 libc::chmod(to_buf, from_mode as libc::mode_t)
             } != 0 {
                 return false; // should be a condition...
@@ -946,7 +944,7 @@ fn unlink(p: &Path) -> bool {
     #[cfg(unix)]
     fn unlink(p: &Path) -> bool {
         unsafe {
-            do p.to_str().as_c_str |buf| {
+            do p.to_c_str().with_ref |buf| {
                 libc::unlink(buf) == (0 as c_int)
             }
         }
@@ -1038,14 +1036,15 @@ fn __xpg_strerror_r(errnum: c_int,
         }
 
         let mut buf = [0 as c_char, ..TMPBUF_SZ];
-        unsafe {
-            let err = strerror_r(errno() as c_int, &mut buf[0],
-                                 TMPBUF_SZ as size_t);
-            if err < 0 {
-                fail!("strerror_r failure");
-            }
 
-            str::raw::from_c_str(&buf[0])
+        do buf.as_mut_buf |buf, len| {
+            unsafe {
+                if strerror_r(errno() as c_int, buf, len as size_t) < 0 {
+                    fail!("strerror_r failure");
+                }
+
+                str::raw::from_c_str(buf as *c_char)
+            }
         }
     }
 
@@ -1071,23 +1070,31 @@ fn FormatMessageA(flags: DWORD,
         static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
         static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
 
-        let mut buf = [0 as c_char, ..TMPBUF_SZ];
-
         // This value is calculated from the macro
         // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
         let langId = 0x0800 as DWORD;
         let err = errno() as DWORD;
+
+        let mut buf = [0 as c_char, ..TMPBUF_SZ];
+
         unsafe {
-            let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
-                                     FORMAT_MESSAGE_IGNORE_INSERTS,
-                                     ptr::mut_null(), err, langId,
-                                     &mut buf[0], TMPBUF_SZ as DWORD,
-                                     ptr::null());
-            if res == 0 {
-                fail!("[%?] FormatMessage failure", errno());
+            do buf.as_mut_buf |buf, len| {
+                let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+                                         FORMAT_MESSAGE_IGNORE_INSERTS,
+                                         ptr::mut_null(),
+                                         err,
+                                         langId,
+                                         buf,
+                                         len as DWORD,
+                                         ptr::null());
+                if res == 0 {
+                    fail!("[%?] FormatMessage failure", errno());
+                }
             }
 
-            str::raw::from_c_str(&buf[0])
+            do buf.as_imm_buf |buf, _len| {
+                str::raw::from_c_str(buf)
+            }
         }
     }
 
@@ -1104,15 +1111,7 @@ fn FormatMessageA(flags: DWORD,
  */
 pub fn set_exit_status(code: int) {
     use rt;
-    use rt::OldTaskContext;
-
-    if rt::context() == OldTaskContext {
-        unsafe {
-            rustrt::rust_set_exit_status(code as libc::intptr_t);
-        }
-    } else {
-        rt::util::set_exit_status(code);
-    }
+    rt::util::set_exit_status(code);
 }
 
 unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] {
@@ -1142,19 +1141,10 @@ pub fn real_args() -> ~[~str] {
 #[cfg(target_os = "freebsd")]
 pub fn real_args() -> ~[~str] {
     use rt;
-    use rt::TaskContext;
 
-    if rt::context() == TaskContext {
-        match rt::args::clone() {
-            Some(args) => args,
-            None => fail!("process arguments not initialized")
-        }
-    } else {
-        unsafe {
-            let argc = rustrt::rust_get_argc();
-            let argv = rustrt::rust_get_argv();
-            load_argc_and_argv(argc, argv)
-        }
+    match rt::args::clone() {
+        Some(args) => args,
+        None => fail!("process arguments not initialized")
     }
 }
 
@@ -1180,7 +1170,7 @@ pub fn real_args() -> ~[~str] {
     }
 
     unsafe {
-        LocalFree(cast::transmute(szArgList));
+        LocalFree(szArgList as *c_void);
     }
 
     return args;
@@ -1292,7 +1282,7 @@ fn default_glob_t () -> libc::glob_t {
     }
 
     let mut g = default_glob_t();
-    do pattern.as_c_str |c_pattern| {
+    do pattern.to_c_str().with_ref |c_pattern| {
         unsafe { libc::glob(c_pattern, 0, ptr::null(), &mut g) }
     };
     do(|| {
@@ -1697,6 +1687,7 @@ pub mod mips {
 
 #[cfg(test)]
 mod tests {
+    use c_str::ToCStr;
     use libc::{c_int, c_void, size_t};
     use libc;
     use option::Some;
@@ -1709,7 +1700,6 @@ mod tests {
     use rand;
     use run;
     use str::StrSlice;
-    use vec::CopyableVector;
     use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
 
 
@@ -1932,39 +1922,39 @@ fn copy_file_does_not_exist() {
     #[test]
     fn copy_file_ok() {
         unsafe {
-          let tempdir = getcwd(); // would like to use $TMPDIR,
-                                  // doesn't seem to work on Linux
-          assert!((tempdir.to_str().len() > 0u));
-          let input = tempdir.push("in.txt");
-          let out = tempdir.push("out.txt");
-
-          /* Write the temp input file */
-            let ostream = do input.to_str().as_c_str |fromp| {
-                do "w+b".as_c_str |modebuf| {
+            let tempdir = getcwd(); // would like to use $TMPDIR,
+                                    // doesn't seem to work on Linux
+            assert!((tempdir.to_str().len() > 0u));
+            let input = tempdir.push("in.txt");
+            let out = tempdir.push("out.txt");
+
+            /* Write the temp input file */
+            let ostream = do input.to_c_str().with_ref |fromp| {
+                do "w+b".to_c_str().with_ref |modebuf| {
                     libc::fopen(fromp, modebuf)
                 }
-          };
-          assert!((ostream as uint != 0u));
-          let s = ~"hello";
-          let mut buf = s.as_bytes_with_null().to_owned();
-          let len = buf.len();
-          do buf.as_mut_buf |b, _len| {
-              assert_eq!(libc::fwrite(b as *c_void, 1u as size_t,
-                                      (s.len() + 1u) as size_t, ostream),
-                         len as size_t)
-          }
-          assert_eq!(libc::fclose(ostream), (0u as c_int));
-          let in_mode = input.get_mode();
-          let rs = os::copy_file(&input, &out);
-          if (!os::path_exists(&input)) {
-            fail!("%s doesn't exist", input.to_str());
-          }
-          assert!((rs));
-          let rslt = run::process_status("diff", [input.to_str(), out.to_str()]);
-          assert_eq!(rslt, 0);
-          assert_eq!(out.get_mode(), in_mode);
-          assert!((remove_file(&input)));
-          assert!((remove_file(&out)));
+            };
+            assert!((ostream as uint != 0u));
+            let s = ~"hello";
+            do "hello".to_c_str().with_ref |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 in_mode = input.get_mode();
+            let rs = os::copy_file(&input, &out);
+            if (!os::path_exists(&input)) {
+                fail!("%s doesn't exist", input.to_str());
+            }
+            assert!((rs));
+            let rslt = run::process_status("diff", [input.to_str(), out.to_str()]);
+            assert_eq!(rslt, 0);
+            assert_eq!(out.get_mode(), in_mode);
+            assert!((remove_file(&input)));
+            assert!((remove_file(&out)));
         }
     }
 
@@ -2023,11 +2013,11 @@ fn lseek_(fd: c_int, size: uint) {
         remove_file(&path);
 
         let fd = unsafe {
-            let fd = do path.to_str().as_c_str |path| {
+            let fd = do path.to_c_str().with_ref |path| {
                 open(path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR)
             };
             lseek_(fd, size);
-            do "x".as_c_str |x| {
+            do "x".to_c_str().with_ref |x| {
                 assert!(write(fd, x as *c_void, 1) == 1);
             }
             fd
index 76001ae41887a8b19a53218b01a9d7de351d8808..177f0efb6dad380677fef7b9d442ddbb5bf11411 100644 (file)
 
 #[allow(missing_doc)];
 
+use c_str::ToCStr;
+use c_str;
 use clone::Clone;
-use container::Container;
 use cmp::Eq;
-use iterator::{Iterator, IteratorUtil};
+use container::Container;
+use iterator::{Iterator, range};
 use libc;
+use num;
 use option::{None, Option, Some};
 use str::{OwnedStr, Str, StrSlice, StrVector};
 use to_str::ToStr;
 use ascii::{AsciiCast, AsciiStr};
-use vec::{OwnedVector, ImmutableVector};
+use vec::{OwnedVector, ImmutableVector, OwnedCopyableVector};
 
 #[cfg(windows)]
 pub use Path = self::WindowsPath;
@@ -124,6 +127,43 @@ pub trait GenericPath {
 
     /// True if `self` is an ancestor of `other`. See `test_is_ancestor_of` for examples
     fn is_ancestor_of(&self, (&Self)) -> bool;
+
+    /// Find the relative path from one file to another
+    fn get_relative_to(&self, abs2: (&Self)) -> Self {
+        assert!(self.is_absolute());
+        assert!(abs2.is_absolute());
+        let abs1 = self.normalize();
+        let abs2 = abs2.normalize();
+
+        let split1: &[~str] = abs1.components();
+        let split2: &[~str] = abs2.components();
+        let len1 = split1.len();
+        let len2 = split2.len();
+        assert!(len1 > 0);
+        assert!(len2 > 0);
+
+        let max_common_path = num::min(len1, len2) - 1;
+        let mut start_idx = 0;
+        while start_idx < max_common_path
+            && split1[start_idx] == split2[start_idx] {
+            start_idx += 1;
+        }
+
+        let mut path: ~[~str] = ~[];
+        for _ in range(start_idx, len1 - 1) { path.push(~".."); };
+
+        path.push_all(split2.slice(start_idx, len2 - 1));
+
+        let mut result: Self = GenericPath::from_str(".");
+        if !path.is_empty() {
+            // Without this type hint, the typechecker doesn't seem to like it
+            let p: Self = GenericPath::from_str("");
+            result = p.push_many(path);
+        };
+        result
+    }
+
+    fn components(self) -> ~[~str];
 }
 
 #[cfg(target_os = "linux")]
@@ -341,7 +381,7 @@ pub fn default_stat() -> libc::stat {
 #[cfg(target_os = "win32")]
 impl WindowsPath {
     pub fn stat(&self) -> Option<libc::stat> {
-        do self.to_str().as_c_str |buf| {
+        do self.to_c_str().with_ref |buf| {
             let mut st = stat::arch::default_stat();
             match unsafe { libc::stat(buf, &mut st) } {
                 0 => Some(st),
@@ -375,7 +415,7 @@ pub fn get_mode(&self) -> Option<uint> {
 #[cfg(not(target_os = "win32"))]
 impl PosixPath {
     pub fn stat(&self) -> Option<libc::stat> {
-        do self.to_str().as_c_str |buf| {
+        do self.to_c_str().with_ref |buf| {
             let mut st = stat::arch::default_stat();
             match unsafe { libc::stat(buf as *libc::c_char, &mut st) } {
                 0 => Some(st),
@@ -453,7 +493,7 @@ pub fn get_ctime(&self) -> Option<(i64, int)> {
 #[cfg(unix)]
 impl PosixPath {
     pub fn lstat(&self) -> Option<libc::stat> {
-        do self.to_str().as_c_str |buf| {
+        do self.to_c_str().with_ref |buf| {
             let mut st = stat::arch::default_stat();
             match unsafe { libc::lstat(buf, &mut st) } {
                 0 => Some(st),
@@ -525,6 +565,12 @@ fn to_str(&self) -> ~str {
     }
 }
 
+impl ToCStr for PosixPath {
+    fn to_c_str(&self) -> c_str::CString {
+        self.to_str().to_c_str()
+    }
+}
+
 // FIXME (#3227): when default methods in traits are working, de-duplicate
 // PosixPath and WindowsPath, most of their methods are common.
 impl GenericPath for PosixPath {
@@ -703,6 +749,7 @@ fn is_ancestor_of(&self, other: &PosixPath) -> bool {
              self.is_ancestor_of(&other.pop()))
     }
 
+   fn components(self) -> ~[~str] { self.components }
 }
 
 
@@ -730,6 +777,11 @@ fn to_str(&self) -> ~str {
     }
 }
 
+impl c_str::ToCStr for WindowsPath {
+    fn to_c_str(&self) -> c_str::CString {
+        self.to_str().to_c_str()
+    }
+}
 
 impl GenericPath for WindowsPath {
     fn from_str(s: &str) -> WindowsPath {
@@ -909,7 +961,7 @@ fn is_restricted(&self) -> bool {
         match self.filestem() {
             Some(stem) => {
                 // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
-                // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+                // to_ascii_move and to_str_move to not do a unnecessary copy.
                 match stem.to_ascii().to_lower().to_str_ascii() {
                     ~"con" | ~"aux" | ~"com1" | ~"com2" | ~"com3" | ~"com4" |
                     ~"lpt1" | ~"lpt2" | ~"lpt3" | ~"prn" | ~"nul" => true,
@@ -968,7 +1020,7 @@ fn normalize(&self) -> WindowsPath {
                 None => None,
 
                 // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
-                // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+                // to_ascii_move and to_str_move to not do a unnecessary copy.
                 Some(ref device) => Some(device.to_ascii().to_upper().to_str_ascii())
             },
             is_absolute: self.is_absolute,
@@ -985,6 +1037,8 @@ fn is_ancestor_of(&self, other: &WindowsPath) -> bool {
             (!other.components.is_empty() && !(self.components.is_empty() && !self.is_absolute) &&
              self.is_ancestor_of(&other.pop()))
     }
+
+   fn components(self) -> ~[~str] { self.components }
 }
 
 pub fn normalize(components: &[~str]) -> ~[~str] {
@@ -1341,4 +1395,124 @@ fn test_is_ancestor_of() {
 
     }
 
+    #[test]
+    fn test_relative_to1() {
+        let p1 = PosixPath("/usr/bin/rustc");
+        let p2 = PosixPath("/usr/lib/mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, PosixPath("../lib"));
+
+        let p1 = WindowsPath("C:\\usr\\bin\\rustc");
+        let p2 = WindowsPath("C:\\usr\\lib\\mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, WindowsPath("..\\lib"));
+
+    }
+
+    #[test]
+    fn test_relative_to2() {
+        let p1 = PosixPath("/usr/bin/rustc");
+        let p2 = PosixPath("/usr/bin/../lib/mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, PosixPath("../lib"));
+
+        let p1 = WindowsPath("C:\\usr\\bin\\rustc");
+        let p2 = WindowsPath("C:\\usr\\bin\\..\\lib\\mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, WindowsPath("..\\lib"));
+    }
+
+    #[test]
+    fn test_relative_to3() {
+        let p1 = PosixPath("/usr/bin/whatever/rustc");
+        let p2 = PosixPath("/usr/lib/whatever/mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, PosixPath("../../lib/whatever"));
+
+        let p1 = WindowsPath("C:\\usr\\bin\\whatever\\rustc");
+        let p2 = WindowsPath("C:\\usr\\lib\\whatever\\mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, WindowsPath("..\\..\\lib\\whatever"));
+
+    }
+
+    #[test]
+    fn test_relative_to4() {
+        let p1 = PosixPath("/usr/bin/whatever/../rustc");
+        let p2 = PosixPath("/usr/lib/whatever/mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, PosixPath("../lib/whatever"));
+
+        let p1 = WindowsPath("C:\\usr\\bin\\whatever\\..\\rustc");
+        let p2 = WindowsPath("C:\\usr\\lib\\whatever\\mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, WindowsPath("..\\lib\\whatever"));
+
+    }
+
+    #[test]
+    fn test_relative_to5() {
+        let p1 = PosixPath("/usr/bin/whatever/../rustc");
+        let p2 = PosixPath("/usr/lib/whatever/../mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, PosixPath("../lib"));
+
+        let p1 = WindowsPath("C:\\usr\\bin/whatever\\..\\rustc");
+        let p2 = WindowsPath("C:\\usr\\lib\\whatever\\..\\mylib");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, WindowsPath("..\\lib"));
+    }
+
+    #[test]
+    fn test_relative_to6() {
+        let p1 = PosixPath("/1");
+        let p2 = PosixPath("/2/3");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, PosixPath("2"));
+
+        let p1 = WindowsPath("C:\\1");
+        let p2 = WindowsPath("C:\\2\\3");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, WindowsPath("2"));
+
+    }
+
+    #[test]
+    fn test_relative_to7() {
+        let p1 = PosixPath("/1/2");
+        let p2 = PosixPath("/3");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, PosixPath(".."));
+
+        let p1 = WindowsPath("C:\\1\\2");
+        let p2 = WindowsPath("C:\\3");
+        let res = p1.get_relative_to(&p2);
+        assert_eq!(res, WindowsPath(".."));
+
+    }
+
+    #[test]
+    fn test_relative_to8() {
+        let p1 = PosixPath("/home/brian/Dev/rust/build/").push_rel(
+            &PosixPath("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
+        let p2 = PosixPath("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
+            &PosixPath("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
+        let res = p1.get_relative_to(&p2);
+        debug!("test_relative_to8: %s vs. %s",
+               res.to_str(),
+               PosixPath(".").to_str());
+        assert_eq!(res, PosixPath("."));
+
+        let p1 = WindowsPath("C:\\home\\brian\\Dev\\rust\\build\\").push_rel(
+            &WindowsPath("stage2\\lib\\rustc\\i686-unknown-linux-gnu\\lib\\librustc.so"));
+        let p2 = WindowsPath("\\home\\brian\\Dev\\rust\\build\\stage2\\bin\\..").push_rel(
+            &WindowsPath("lib\\rustc\\i686-unknown-linux-gnu\\lib\\libstd.so"));
+        let res = p1.get_relative_to(&p2);
+        debug!("test_relative_to8: %s vs. %s",
+               res.to_str(),
+               WindowsPath(".").to_str());
+        assert_eq!(res, WindowsPath("."));
+
+    }
+
 }
diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs
deleted file mode 100644 (file)
index 78f937e..0000000
+++ /dev/null
@@ -1,870 +0,0 @@
-// 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 support for message passing with protocol enforcement.
-
-
-Pipes consist of two endpoints. One endpoint can send messages and
-the other can receive messages. The set of legal messages and which
-directions they can flow at any given point are determined by a
-protocol. Below is an example protocol.
-
-~~~ {.rust}
-proto! pingpong (
-    ping: send {
-        ping -> pong
-    }
-    pong: recv {
-        pong -> ping
-    }
-)
-~~~
-
-The `proto!` syntax extension will convert this into a module called
-`pingpong`, which includes a set of types and functions that can be
-used to write programs that follow the pingpong protocol.
-
-*/
-
-/* IMPLEMENTATION NOTES
-
-The initial design for this feature is available at:
-
-https://github.com/eholk/rust/wiki/Proposal-for-channel-contracts
-
-Much of the design in that document is still accurate. There are
-several components for the pipe implementation. First of all is the
-syntax extension. To see how that works, it is best see comments in
-libsyntax/ext/pipes.rs.
-
-This module includes two related pieces of the runtime
-implementation: support for unbounded and bounded
-protocols. The main difference between the two is the type of the
-buffer that is carried along in the endpoint data structures.
-
-
-The heart of the implementation is the packet type. It contains a
-header and a payload field. Much of the code in this module deals with
-the header field. This is where the synchronization information is
-stored. In the case of a bounded protocol, the header also includes a
-pointer to the buffer the packet is contained in.
-
-Packets represent a single message in a protocol. The payload field
-gets instatiated at the type of the message, which is usually an enum
-generated by the pipe compiler. Packets are conceptually single use,
-although in bounded protocols they are reused each time around the
-loop.
-
-
-Packets are usually handled through a send_packet_buffered or
-recv_packet_buffered object. Each packet is referenced by one
-send_packet and one recv_packet, and these wrappers enforce that only
-one end can send and only one end can receive. The structs also
-include a destructor that marks packets are terminated if the sender
-or receiver destroys the object before sending or receiving a value.
-
-The *_packet_buffered structs take two type parameters. The first is
-the message type for the current packet (or state). The second
-represents the type of the whole buffer. For bounded protocols, the
-protocol compiler generates a struct with a field for each protocol
-state. This generated struct is used as the buffer type parameter. For
-unbounded protocols, the buffer is simply one packet, so there is a
-shorthand struct called send_packet and recv_packet, where the buffer
-type is just `packet<T>`. Using the same underlying structure for both
-bounded and unbounded protocols allows for less code duplication.
-
-*/
-
-#[allow(missing_doc)];
-
-use container::Container;
-use cast::{forget, transmute, transmute_copy, transmute_mut};
-use either::{Either, Left, Right};
-use iterator::{Iterator, IteratorUtil};
-use kinds::Send;
-use libc;
-use ops::Drop;
-use option::{None, Option, Some};
-use unstable::finally::Finally;
-use unstable::intrinsics;
-use ptr;
-use ptr::RawPtr;
-use task;
-use vec::{OwnedVector, MutableVector};
-use util::replace;
-
-static SPIN_COUNT: uint = 0;
-
-#[deriving(Eq)]
-enum State {
-    Empty,
-    Full,
-    Blocked,
-    Terminated
-}
-
-pub struct BufferHeader {
-    // Tracks whether this buffer needs to be freed. We can probably
-    // get away with restricting it to 0 or 1, if we're careful.
-    ref_count: int,
-
-    // We may want a drop, and to be careful about stringing this
-    // thing along.
-}
-
-pub fn BufferHeader() -> BufferHeader {
-    BufferHeader {
-        ref_count: 0
-    }
-}
-
-// This is for protocols to associate extra data to thread around.
-pub struct Buffer<T> {
-    header: BufferHeader,
-    data: T,
-}
-
-pub struct PacketHeader {
-    state: State,
-    blocked_task: *rust_task,
-
-    // This is a transmute_copy of a ~buffer, that can also be cast
-    // to a buffer_header if need be.
-    buffer: *libc::c_void,
-}
-
-pub fn PacketHeader() -> PacketHeader {
-    PacketHeader {
-        state: Empty,
-        blocked_task: ptr::null(),
-        buffer: ptr::null()
-    }
-}
-
-impl PacketHeader {
-    // Returns the old state.
-    pub unsafe fn mark_blocked(&mut self, this: *rust_task) -> State {
-        rustrt::rust_task_ref(this);
-        let old_task = swap_task(&mut self.blocked_task, this);
-        assert!(old_task.is_null());
-        swap_state_acq(&mut self.state, Blocked)
-    }
-
-    pub unsafe fn unblock(&mut self) {
-        let old_task = swap_task(&mut self.blocked_task, ptr::null());
-        if !old_task.is_null() {
-            rustrt::rust_task_deref(old_task)
-        }
-        match swap_state_acq(&mut self.state, Empty) {
-          Empty | Blocked => (),
-          Terminated => self.state = Terminated,
-          Full => self.state = Full
-        }
-    }
-
-    // unsafe because this can do weird things to the space/time
-    // continuum. It ends making multiple unique pointers to the same
-    // thing. You'll probably want to forget them when you're done.
-    pub unsafe fn buf_header(&mut self) -> ~BufferHeader {
-        assert!(self.buffer.is_not_null());
-        transmute_copy(&self.buffer)
-    }
-
-    pub fn set_buffer<T:Send>(&mut self, b: ~Buffer<T>) {
-        unsafe {
-            self.buffer = transmute_copy(&b);
-        }
-    }
-}
-
-pub struct Packet<T> {
-    header: PacketHeader,
-    payload: Option<T>,
-}
-
-pub trait HasBuffer {
-    fn set_buffer(&mut self, b: *libc::c_void);
-}
-
-impl<T:Send> HasBuffer for Packet<T> {
-    fn set_buffer(&mut self, b: *libc::c_void) {
-        self.header.buffer = b;
-    }
-}
-
-pub fn mk_packet<T:Send>() -> Packet<T> {
-    Packet {
-        header: PacketHeader(),
-        payload: None,
-    }
-}
-fn unibuffer<T>() -> ~Buffer<Packet<T>> {
-    let mut b = ~Buffer {
-        header: BufferHeader(),
-        data: Packet {
-            header: PacketHeader(),
-            payload: None,
-        }
-    };
-
-    unsafe {
-        b.data.header.buffer = transmute_copy(&b);
-    }
-    b
-}
-
-pub fn packet<T>() -> *mut Packet<T> {
-    let mut b = unibuffer();
-    let p = ptr::to_mut_unsafe_ptr(&mut b.data);
-    // We'll take over memory management from here.
-    unsafe {
-        forget(b);
-    }
-    p
-}
-
-pub fn entangle_buffer<T:Send,Tstart:Send>(
-    mut buffer: ~Buffer<T>,
-    init: &fn(*libc::c_void, x: &mut T) -> *mut Packet<Tstart>)
-    -> (RecvPacketBuffered<Tstart, T>, SendPacketBuffered<Tstart, T>) {
-    unsafe {
-        let p = init(transmute_copy(&buffer), &mut buffer.data);
-        forget(buffer);
-        (RecvPacketBuffered(p), SendPacketBuffered(p))
-    }
-}
-
-pub fn swap_task(dst: &mut *rust_task, src: *rust_task) -> *rust_task {
-    // It might be worth making both acquire and release versions of
-    // this.
-    unsafe {
-        transmute(intrinsics::atomic_xchg(transmute(dst), src as int))
-    }
-}
-
-#[allow(non_camel_case_types)]
-pub type rust_task = libc::c_void;
-
-pub mod rustrt {
-    use libc;
-    use super::rust_task;
-
-    extern {
-        #[rust_stack]
-        pub fn rust_get_task() -> *rust_task;
-        #[rust_stack]
-        pub fn rust_task_ref(task: *rust_task);
-        pub fn rust_task_deref(task: *rust_task);
-
-        #[rust_stack]
-        pub fn task_clear_event_reject(task: *rust_task);
-
-        pub fn task_wait_event(this: *rust_task, killed: &mut *libc::c_void)
-                               -> bool;
-        pub fn task_signal_event(target: *rust_task, event: *libc::c_void);
-    }
-}
-
-fn wait_event(this: *rust_task) -> *libc::c_void {
-    unsafe {
-        let mut event = ptr::null();
-
-        let killed = rustrt::task_wait_event(this, &mut event);
-        if killed && !task::failing() {
-            fail!("killed")
-        }
-        event
-    }
-}
-
-fn swap_state_acq(dst: &mut State, src: State) -> State {
-    unsafe {
-        transmute(intrinsics::atomic_xchg_acq(transmute(dst), src as int))
-    }
-}
-
-fn swap_state_rel(dst: &mut State, src: State) -> State {
-    unsafe {
-        transmute(intrinsics::atomic_xchg_rel(transmute(dst), src as int))
-    }
-}
-
-pub unsafe fn get_buffer<T>(p: *mut PacketHeader) -> ~Buffer<T> {
-    transmute((*p).buf_header())
-}
-
-// This could probably be done with SharedMutableState to avoid move_it!().
-struct BufferResource<T> {
-    buffer: ~Buffer<T>,
-
-}
-
-#[unsafe_destructor]
-impl<T> Drop for BufferResource<T> {
-    fn drop(&self) {
-        unsafe {
-            // FIXME(#4330) Need self by value to get mutability.
-            let this: &mut BufferResource<T> = transmute_mut(self);
-
-            let null_buffer: ~Buffer<T> = transmute(ptr::null::<Buffer<T>>());
-            let mut b = replace(&mut this.buffer, null_buffer);
-
-            //let p = ptr::to_unsafe_ptr(*b);
-            //error!("drop %?", p);
-            let old_count = intrinsics::atomic_xsub_rel(
-                &mut b.header.ref_count,
-                1);
-            //let old_count = atomic_xchng_rel(b.header.ref_count, 0);
-            if old_count == 1 {
-                // The new count is 0.
-
-                // go go gadget drop glue
-            }
-            else {
-                forget(b)
-            }
-        }
-    }
-}
-
-fn BufferResource<T>(mut b: ~Buffer<T>) -> BufferResource<T> {
-    //let p = ptr::to_unsafe_ptr(*b);
-    //error!("take %?", p);
-    unsafe {
-        intrinsics::atomic_xadd_acq(&mut b.header.ref_count, 1);
-    }
-
-    BufferResource {
-        // tjc: ????
-        buffer: b
-    }
-}
-
-pub fn send<T,Tbuffer>(mut p: SendPacketBuffered<T,Tbuffer>,
-                       payload: T)
-                       -> bool {
-    let header = p.header();
-    let p_ = p.unwrap();
-    let p = unsafe { &mut *p_ };
-    assert_eq!(ptr::to_unsafe_ptr(&(p.header)), header);
-    assert!(p.payload.is_none());
-    p.payload = Some(payload);
-    let old_state = swap_state_rel(&mut p.header.state, Full);
-    match old_state {
-        Empty => {
-            // Yay, fastpath.
-
-            // The receiver will eventually clean this up.
-            //unsafe { forget(p); }
-            return true;
-        }
-        Full => fail!("duplicate send"),
-        Blocked => {
-            debug!("waking up task for %?", p_);
-            let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
-            if !old_task.is_null() {
-                unsafe {
-                    rustrt::task_signal_event(
-                        old_task,
-                        ptr::to_unsafe_ptr(&(p.header)) as *libc::c_void);
-                    rustrt::rust_task_deref(old_task);
-                }
-            }
-
-            // The receiver will eventually clean this up.
-            //unsafe { forget(p); }
-            return true;
-        }
-        Terminated => {
-            // The receiver will never receive this. Rely on drop_glue
-            // to clean everything up.
-            return false;
-        }
-    }
-}
-
-/** Receives a message from a pipe.
-
-Fails if the sender closes the connection.
-
-*/
-pub fn recv<T:Send,Tbuffer:Send>(
-    p: RecvPacketBuffered<T, Tbuffer>) -> T {
-    try_recv(p).expect("connection closed")
-}
-
-/** Attempts to receive a message from a pipe.
-
-Returns `None` if the sender has closed the connection without sending
-a message, or `Some(T)` if a message was received.
-
-*/
-pub fn try_recv<T:Send,Tbuffer:Send>(mut p: RecvPacketBuffered<T, Tbuffer>)
-                                       -> Option<T> {
-    let p_ = p.unwrap();
-    let p = unsafe { &mut *p_ };
-
-    do (|| {
-        try_recv_(p)
-    }).finally {
-        unsafe {
-            if task::failing() {
-                p.header.state = Terminated;
-                let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
-                if !old_task.is_null() {
-                    rustrt::rust_task_deref(old_task);
-                }
-            }
-        }
-    }
-}
-
-fn try_recv_<T:Send>(p: &mut Packet<T>) -> Option<T> {
-    // optimistic path
-    match p.header.state {
-      Full => {
-        let payload = p.payload.take();
-        p.header.state = Empty;
-        return Some(payload.unwrap())
-      },
-      Terminated => return None,
-      _ => {}
-    }
-
-    // regular path
-    let this = unsafe { rustrt::rust_get_task() };
-    unsafe {
-        rustrt::task_clear_event_reject(this);
-        rustrt::rust_task_ref(this);
-    };
-    debug!("blocked = %x this = %x", p.header.blocked_task as uint,
-           this as uint);
-    let old_task = swap_task(&mut p.header.blocked_task, this);
-    debug!("blocked = %x this = %x old_task = %x",
-           p.header.blocked_task as uint,
-           this as uint, old_task as uint);
-    assert!(old_task.is_null());
-    let mut first = true;
-    let mut count = SPIN_COUNT;
-    loop {
-        unsafe {
-            rustrt::task_clear_event_reject(this);
-        }
-
-        let old_state = swap_state_acq(&mut p.header.state,
-                                       Blocked);
-        match old_state {
-          Empty => {
-            debug!("no data available on %?, going to sleep.", p);
-            if count == 0 {
-                wait_event(this);
-            }
-            else {
-                count -= 1;
-                // FIXME (#524): Putting the yield here destroys a lot
-                // of the benefit of spinning, since we still go into
-                // the scheduler at every iteration. However, without
-                // this everything spins too much because we end up
-                // sometimes blocking the thing we are waiting on.
-                task::yield();
-            }
-            debug!("woke up, p.state = %?", p.header.state);
-          }
-          Blocked => if first {
-            fail!("blocking on already blocked packet")
-          },
-          Full => {
-            let payload = p.payload.take();
-            let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
-            if !old_task.is_null() {
-                unsafe {
-                    rustrt::rust_task_deref(old_task);
-                }
-            }
-            p.header.state = Empty;
-            return Some(payload.unwrap())
-          }
-          Terminated => {
-            // This assert detects when we've accidentally unsafely
-            // casted too big of a number to a state.
-            assert_eq!(old_state, Terminated);
-
-            let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
-            if !old_task.is_null() {
-                unsafe {
-                    rustrt::rust_task_deref(old_task);
-                }
-            }
-            return None;
-          }
-        }
-        first = false;
-    }
-}
-
-/// Returns true if messages are available.
-pub fn peek<T:Send,Tb:Send>(p: &mut RecvPacketBuffered<T, Tb>) -> bool {
-    unsafe {
-        match (*p.header()).state {
-            Empty | Terminated => false,
-            Blocked => fail!("peeking on blocked packet"),
-            Full => true
-        }
-    }
-}
-
-fn sender_terminate<T:Send>(p: *mut Packet<T>) {
-    let p = unsafe {
-        &mut *p
-    };
-    match swap_state_rel(&mut p.header.state, Terminated) {
-      Empty => {
-        // The receiver will eventually clean up.
-      }
-      Blocked => {
-        // wake up the target
-        let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
-        if !old_task.is_null() {
-            unsafe {
-                rustrt::task_signal_event(
-                    old_task,
-                    ptr::to_unsafe_ptr(&(p.header)) as *libc::c_void);
-                rustrt::rust_task_deref(old_task);
-            }
-        }
-        // The receiver will eventually clean up.
-      }
-      Full => {
-        // This is impossible
-        fail!("you dun goofed")
-      }
-      Terminated => {
-        assert!(p.header.blocked_task.is_null());
-        // I have to clean up, use drop_glue
-      }
-    }
-}
-
-fn receiver_terminate<T:Send>(p: *mut Packet<T>) {
-    let p = unsafe {
-        &mut *p
-    };
-    match swap_state_rel(&mut p.header.state, Terminated) {
-      Empty => {
-        assert!(p.header.blocked_task.is_null());
-        // the sender will clean up
-      }
-      Blocked => {
-        let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
-        if !old_task.is_null() {
-            unsafe {
-                rustrt::rust_task_deref(old_task);
-                assert_eq!(old_task, rustrt::rust_get_task());
-            }
-        }
-      }
-      Terminated | Full => {
-        assert!(p.header.blocked_task.is_null());
-        // I have to clean up, use drop_glue
-      }
-    }
-}
-
-/** Returns when one of the packet headers reports data is available.
-
-This function is primarily intended for building higher level waiting
-functions, such as `select`, `select2`, etc.
-
-It takes a vector slice of packet_headers and returns an index into
-that vector. The index points to an endpoint that has either been
-closed by the sender or has a message waiting to be received.
-
-*/
-pub fn wait_many<T: Selectable>(pkts: &mut [T]) -> uint {
-    let this = unsafe {
-        rustrt::rust_get_task()
-    };
-
-    unsafe {
-        rustrt::task_clear_event_reject(this);
-    }
-
-    let mut data_avail = false;
-    let mut ready_packet = pkts.len();
-    for (i, p) in pkts.mut_iter().enumerate() {
-        unsafe {
-            let p = &mut *p.header();
-            let old = p.mark_blocked(this);
-            match old {
-                Full | Terminated => {
-                    data_avail = true;
-                    ready_packet = i;
-                    (*p).state = old;
-                    break;
-                }
-                Blocked => fail!("blocking on blocked packet"),
-                Empty => ()
-            }
-        }
-    }
-
-    while !data_avail {
-        debug!("sleeping on %? packets", pkts.len());
-        let event = wait_event(this) as *PacketHeader;
-
-        let mut pos = None;
-        for (i, p) in pkts.mut_iter().enumerate() {
-            if p.header() == event {
-                pos = Some(i);
-                break;
-            }
-        };
-
-        match pos {
-          Some(i) => {
-            ready_packet = i;
-            data_avail = true;
-          }
-          None => debug!("ignoring spurious event, %?", event)
-        }
-    }
-
-    debug!("%?", &mut pkts[ready_packet]);
-
-    for p in pkts.mut_iter() {
-        unsafe {
-            (*p.header()).unblock()
-        }
-    }
-
-    debug!("%?, %?", ready_packet, &mut pkts[ready_packet]);
-
-    unsafe {
-        assert!((*pkts[ready_packet].header()).state == Full
-                     || (*pkts[ready_packet].header()).state == Terminated);
-    }
-
-    ready_packet
-}
-
-/** The sending end of a pipe. It can be used to send exactly one
-message.
-
-*/
-pub type SendPacket<T> = SendPacketBuffered<T, Packet<T>>;
-
-pub fn SendPacket<T>(p: *mut Packet<T>) -> SendPacket<T> {
-    SendPacketBuffered(p)
-}
-
-pub struct SendPacketBuffered<T, Tbuffer> {
-    p: Option<*mut Packet<T>>,
-    buffer: Option<BufferResource<Tbuffer>>,
-}
-
-#[unsafe_destructor]
-impl<T:Send,Tbuffer:Send> Drop for SendPacketBuffered<T,Tbuffer> {
-    fn drop(&self) {
-        unsafe {
-            let this: &mut SendPacketBuffered<T,Tbuffer> = transmute(self);
-            if this.p != None {
-                sender_terminate(this.p.take_unwrap());
-            }
-        }
-    }
-}
-
-pub fn SendPacketBuffered<T,Tbuffer>(p: *mut Packet<T>)
-                                     -> SendPacketBuffered<T,Tbuffer> {
-    SendPacketBuffered {
-        p: Some(p),
-        buffer: unsafe {
-            Some(BufferResource(get_buffer(&mut (*p).header)))
-        }
-    }
-}
-
-impl<T,Tbuffer> SendPacketBuffered<T,Tbuffer> {
-    pub fn unwrap(&mut self) -> *mut Packet<T> {
-        self.p.take_unwrap()
-    }
-
-    pub fn header(&mut self) -> *mut PacketHeader {
-        match self.p {
-            Some(packet) => unsafe {
-                let packet = &mut *packet;
-                let header = ptr::to_mut_unsafe_ptr(&mut packet.header);
-                header
-            },
-            None => fail!("packet already consumed")
-        }
-    }
-
-    pub fn reuse_buffer(&mut self) -> BufferResource<Tbuffer> {
-        //error!("send reuse_buffer");
-        self.buffer.take_unwrap()
-    }
-}
-
-/// Represents the receive end of a pipe. It can receive exactly one
-/// message.
-pub type RecvPacket<T> = RecvPacketBuffered<T, Packet<T>>;
-
-pub fn RecvPacket<T>(p: *mut Packet<T>) -> RecvPacket<T> {
-    RecvPacketBuffered(p)
-}
-
-pub struct RecvPacketBuffered<T, Tbuffer> {
-    p: Option<*mut Packet<T>>,
-    buffer: Option<BufferResource<Tbuffer>>,
-}
-
-#[unsafe_destructor]
-impl<T:Send,Tbuffer:Send> Drop for RecvPacketBuffered<T,Tbuffer> {
-    fn drop(&self) {
-        unsafe {
-            let this: &mut RecvPacketBuffered<T,Tbuffer> = transmute(self);
-            if this.p != None {
-                receiver_terminate(this.p.take_unwrap())
-            }
-        }
-    }
-}
-
-impl<T:Send,Tbuffer:Send> RecvPacketBuffered<T, Tbuffer> {
-    pub fn unwrap(&mut self) -> *mut Packet<T> {
-        self.p.take_unwrap()
-    }
-
-    pub fn reuse_buffer(&mut self) -> BufferResource<Tbuffer> {
-        self.buffer.take_unwrap()
-    }
-}
-
-impl<T:Send,Tbuffer:Send> Selectable for RecvPacketBuffered<T, Tbuffer> {
-    fn header(&mut self) -> *mut PacketHeader {
-        match self.p {
-            Some(packet) => unsafe {
-                let packet = &mut *packet;
-                let header = ptr::to_mut_unsafe_ptr(&mut packet.header);
-                header
-            },
-            None => fail!("packet already consumed")
-        }
-    }
-}
-
-pub fn RecvPacketBuffered<T,Tbuffer>(p: *mut Packet<T>)
-                                     -> RecvPacketBuffered<T,Tbuffer> {
-    RecvPacketBuffered {
-        p: Some(p),
-        buffer: unsafe {
-            Some(BufferResource(get_buffer(&mut (*p).header)))
-        }
-    }
-}
-
-pub fn entangle<T>() -> (RecvPacket<T>, SendPacket<T>) {
-    let p = packet();
-    (RecvPacket(p), SendPacket(p))
-}
-
-/** Receives a message from one of two endpoints.
-
-The return value is `left` if the first endpoint received something,
-or `right` if the second endpoint receives something. In each case,
-the result includes the other endpoint as well so it can be used
-again. Below is an example of using `select2`.
-
-~~~ {.rust}
-match select2(a, b) {
-    left((none, b)) {
-        // endpoint a was closed.
-    }
-    right((a, none)) {
-        // endpoint b was closed.
-    }
-    left((Some(_), b)) {
-        // endpoint a received a message
-    }
-    right(a, Some(_)) {
-        // endpoint b received a message.
-    }
-}
-~~~
-
-Sometimes messages will be available on both endpoints at once. In
-this case, `select2` may return either `left` or `right`.
-
-*/
-pub fn select2<A:Send,Ab:Send,B:Send,Bb:Send>(
-    mut a: RecvPacketBuffered<A, Ab>,
-    mut b: RecvPacketBuffered<B, Bb>)
-    -> Either<(Option<A>, RecvPacketBuffered<B, Bb>),
-              (RecvPacketBuffered<A, Ab>, Option<B>)> {
-    let mut endpoints = [ a.header(), b.header() ];
-    let i = wait_many(endpoints);
-    match i {
-        0 => Left((try_recv(a), b)),
-        1 => Right((a, try_recv(b))),
-        _ => fail!("select2 return an invalid packet")
-    }
-}
-
-pub trait Selectable {
-    fn header(&mut self) -> *mut PacketHeader;
-}
-
-impl Selectable for *mut PacketHeader {
-    fn header(&mut self) -> *mut PacketHeader { *self }
-}
-
-/// Returns the index of an endpoint that is ready to receive.
-pub fn selecti<T:Selectable>(endpoints: &mut [T]) -> uint {
-    wait_many(endpoints)
-}
-
-/// Returns 0 or 1 depending on which endpoint is ready to receive
-pub fn select2i<A:Selectable,B:Selectable>(a: &mut A, b: &mut B)
-                                           -> Either<(), ()> {
-    let mut endpoints = [ a.header(), b.header() ];
-    match wait_many(endpoints) {
-        0 => Left(()),
-        1 => Right(()),
-        _ => fail!("wait returned unexpected index")
-    }
-}
-
-/// Waits on a set of endpoints. Returns a message, its index, and a
-/// list of the remaining endpoints.
-pub fn select<T:Send,Tb:Send>(mut endpoints: ~[RecvPacketBuffered<T, Tb>])
-                                -> (uint,
-                                    Option<T>,
-                                    ~[RecvPacketBuffered<T, Tb>]) {
-    let mut endpoint_headers = ~[];
-    for endpoint in endpoints.mut_iter() {
-        endpoint_headers.push(endpoint.header());
-    }
-
-    let ready = wait_many(endpoint_headers);
-    let mut remaining = endpoints;
-    let port = remaining.swap_remove(ready);
-    let result = try_recv(port);
-    (ready, result, remaining)
-}
-
-pub mod rt {
-    use option::{None, Option, Some};
-
-    // These are used to hide the option constructors from the
-    // compiler because their names are changing
-    pub fn make_some<T>(val: T) -> Option<T> { Some(val) }
-    pub fn make_none<T>() -> Option<T> { None }
-}
index 65db55297b3b70e673146e74b19f2c58d3121d52..9a8737f4dee3f5adc01dc60f481a5d2b1b91d103 100644 (file)
@@ -43,6 +43,7 @@
 pub use iterator::range;
 
 // Reexported types and traits
+pub use c_str::ToCStr;
 pub use clone::{Clone, DeepClone};
 pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
 pub use char::Char;
@@ -50,7 +51,7 @@
 pub use hash::Hash;
 pub use iter::Times;
 pub use iterator::Extendable;
-pub use iterator::{Iterator, IteratorUtil, DoubleEndedIterator, DoubleEndedIteratorUtil};
+pub use iterator::{Iterator, DoubleEndedIterator};
 pub use iterator::{ClonableIterator, OrdIterator};
 pub use num::{Num, NumCast};
 pub use num::{Orderable, Signed, Unsigned, Round};
@@ -64,7 +65,7 @@
 pub use path::WindowsPath;
 pub use ptr::RawPtr;
 pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, ToBytesConsume};
-pub use str::{Str, StrVector, StrSlice, OwnedStr, NullTerminatedStr};
+pub use str::{Str, StrVector, StrSlice, OwnedStr};
 pub use from_str::FromStr;
 pub use to_bytes::IterBytes;
 pub use to_str::{ToStr, ToStrConsume};
index 5a2bd0c4de9cea8e88cd256c87100c1eb42650d0..26653a51d66182dedf95b01b2d4345fec6652d82 100644 (file)
@@ -456,6 +456,7 @@ pub mod ptr_tests {
     use super::*;
     use prelude::*;
 
+    use c_str::ToCStr;
     use cast;
     use libc;
     use str;
@@ -502,22 +503,20 @@ struct Pair {
     fn test_position() {
         use libc::c_char;
 
-        let s = ~"hello";
-        unsafe {
-            assert!(2u == s.as_c_str(|p| position(p, |c| *c == 'l' as c_char)));
-            assert!(4u == s.as_c_str(|p| position(p, |c| *c == 'o' as c_char)));
-            assert!(5u == s.as_c_str(|p| position(p, |c| *c == 0 as c_char)));
+        do "hello".to_c_str().with_ref |p| {
+            unsafe {
+                assert!(2u == position(p, |c| *c == 'l' as c_char));
+                assert!(4u == position(p, |c| *c == 'o' as c_char));
+                assert!(5u == position(p, |c| *c == 0 as c_char));
+            }
         }
     }
 
     #[test]
     fn test_buf_len() {
-        let s0 = ~"hello";
-        let s1 = ~"there";
-        let s2 = ~"thing";
-        do s0.as_c_str |p0| {
-            do s1.as_c_str |p1| {
-                do s2.as_c_str |p2| {
+        do "hello".to_c_str().with_ref |p0| {
+            do "there".to_c_str().with_ref |p1| {
+                do "thing".to_c_str().with_ref |p2| {
                     let v = ~[p0, p1, p2, null()];
                     do v.as_imm_buf |vp, len| {
                         assert_eq!(unsafe { buf_len(vp) }, 3u);
@@ -621,66 +620,75 @@ fn test_ptr_subtraction() {
     #[test]
     fn test_ptr_array_each_with_len() {
         unsafe {
-            let one = ~"oneOne";
-            let two = ~"twoTwo";
-            let three = ~"threeThree";
-            let arr: ~[*i8] = ~[
-                ::cast::transmute(&one[0]),
-                ::cast::transmute(&two[0]),
-                ::cast::transmute(&three[0]),
+            let one = "oneOne".to_c_str();
+            let two = "twoTwo".to_c_str();
+            let three = "threeThree".to_c_str();
+            let arr = ~[
+                one.with_ref(|buf| buf),
+                two.with_ref(|buf| buf),
+                three.with_ref(|buf| buf),
             ];
             let expected_arr = [
                 one, two, three
             ];
-            let arr_ptr = &arr[0];
-            let mut ctr = 0;
-            let mut iteration_count = 0;
-            array_each_with_len(arr_ptr, arr.len(),
-                                |e| {
-                                         let actual = str::raw::from_c_str(e);
-                                         let expected = expected_arr[ctr].clone();
-                                         debug!(
-                                             "test_ptr_array_each e: %s, a: %s",
-                                             expected, actual);
-                                         assert_eq!(actual, expected);
-                                         ctr += 1;
-                                         iteration_count += 1;
-                                     });
-            assert_eq!(iteration_count, 3u);
+
+            do arr.as_imm_buf |arr_ptr, arr_len| {
+                let mut ctr = 0;
+                let mut iteration_count = 0;
+                do array_each_with_len(arr_ptr, arr_len) |e| {
+                     let actual = str::raw::from_c_str(e);
+                     let expected = do expected_arr[ctr].with_ref |buf| {
+                         str::raw::from_c_str(buf)
+                     };
+                     debug!(
+                         "test_ptr_array_each_with_len e: %s, a: %s",
+                         expected, actual);
+                     assert_eq!(actual, expected);
+                     ctr += 1;
+                     iteration_count += 1;
+                 }
+                assert_eq!(iteration_count, 3u);
+            }
         }
     }
+
     #[test]
     fn test_ptr_array_each() {
         unsafe {
-            let one = ~"oneOne";
-            let two = ~"twoTwo";
-            let three = ~"threeThree";
-            let arr: ~[*i8] = ~[
-                ::cast::transmute(&one[0]),
-                ::cast::transmute(&two[0]),
-                ::cast::transmute(&three[0]),
+            let one = "oneOne".to_c_str();
+            let two = "twoTwo".to_c_str();
+            let three = "threeThree".to_c_str();
+            let arr = ~[
+                one.with_ref(|buf| buf),
+                two.with_ref(|buf| buf),
+                three.with_ref(|buf| buf),
                 // fake a null terminator
-                0 as *i8
+                null(),
             ];
             let expected_arr = [
                 one, two, three
             ];
-            let arr_ptr = &arr[0];
-            let mut ctr = 0;
-            let mut iteration_count = 0;
-            array_each(arr_ptr, |e| {
-                let actual = str::raw::from_c_str(e);
-                let expected = expected_arr[ctr].clone();
-                debug!(
-                    "test_ptr_array_each e: %s, a: %s",
-                    expected, actual);
-                assert_eq!(actual, expected);
-                ctr += 1;
-                iteration_count += 1;
-            });
-            assert_eq!(iteration_count, 3);
+
+            do arr.as_imm_buf |arr_ptr, arr_len| {
+                let mut ctr = 0;
+                let mut iteration_count = 0;
+                do array_each(arr_ptr) |e| {
+                     let actual = str::raw::from_c_str(e);
+                     let expected = do expected_arr[ctr].with_ref |buf| {
+                         str::raw::from_c_str(buf)
+                     };
+                     debug!(
+                         "test_ptr_array_each e: %s, a: %s",
+                         expected, actual);
+                     assert_eq!(actual, expected);
+                     ctr += 1;
+                     iteration_count += 1;
+                 }
+                assert_eq!(iteration_count, 3);
+            }
         }
     }
+
     #[test]
     #[should_fail]
     #[ignore(cfg(windows))]
index 3e429c6116d4c60d2c7aa191170405433b158593..9de5e69148ae998cc39065e34844e0a4e3a0cdca 100644 (file)
@@ -94,7 +94,7 @@ pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
         match *self {
             Ok(ref t) => Some(t),
             Err(*) => None,
-        }.consume()
+        }.move_iter()
     }
 
     /// Call a method based on a previous result
@@ -108,7 +108,7 @@ pub fn iter_err<'r>(&'r self) -> OptionIterator<&'r E> {
         match *self {
             Ok(*) => None,
             Err(ref t) => Some(t),
-        }.consume()
+        }.move_iter()
     }
 
     /// Unwraps a result, yielding the content of an `Ok`.
index dcfcc3a9fc67a401341ea845979201f8182cf22c..f620a7347a4cd31bf403146bfa4c62c2ceff9a5e 100644 (file)
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use c_str::ToCStr;
 use cast::transmute;
-use libc::{c_char, c_void, size_t, STDERR_FILENO};
+use libc::{c_char, size_t, STDERR_FILENO};
 use io;
 use io::{Writer, WriterUtil};
 use option::{Option, None, Some};
@@ -20,9 +21,6 @@
 use unstable::raw;
 use vec::ImmutableVector;
 
-#[allow(non_camel_case_types)]
-type rust_task = c_void;
-
 pub static FROZEN_BIT: uint = 1 << (uint::bits - 1);
 pub static MUT_BIT: uint = 1 << (uint::bits - 2);
 static ALL_BITS: uint = FROZEN_BIT | MUT_BIT;
@@ -35,34 +33,12 @@ struct BorrowRecord {
 }
 
 fn try_take_task_borrow_list() -> Option<~[BorrowRecord]> {
-    unsafe {
-        let cur_task: *rust_task = rust_try_get_task();
-        if cur_task.is_not_null() {
-            let ptr = rust_take_task_borrow_list(cur_task);
-            if ptr.is_null() {
-                None
-            } else {
-                let v: ~[BorrowRecord] = transmute(ptr);
-                Some(v)
-            }
-        } else {
-            None
-        }
-    }
+    // XXX
+    None
 }
 
-fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) {
-    unsafe {
-        let cur_task: *rust_task = rust_try_get_task();
-        if cur_task.is_not_null() {
-            let mut borrow_list: ~[BorrowRecord] = {
-                let ptr = rust_take_task_borrow_list(cur_task);
-                if ptr.is_null() { ~[] } else { transmute(ptr) }
-            };
-            borrow_list = f(borrow_list);
-            rust_set_task_borrow_list(cur_task, transmute(borrow_list));
-        }
-    }
+fn swap_task_borrow_list(_f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) {
+    // XXX
 }
 
 pub unsafe fn clear_task_borrow_list() {
@@ -76,8 +52,8 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) {
     match try_take_task_borrow_list() {
         None => { // not recording borrows
             let msg = "borrowed";
-            do msg.as_c_str |msg_p| {
-                sys::begin_unwind_(msg_p as *c_char, file, line);
+            do msg.to_c_str().with_ref |msg_p| {
+                sys::begin_unwind_(msg_p, file, line);
             }
         }
         Some(borrow_list) => { // recording borrows
@@ -92,8 +68,8 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) {
                     sep = " and at ";
                 }
             }
-            do msg.as_c_str |msg_p| {
-                sys::begin_unwind_(msg_p as *c_char, file, line)
+            do msg.to_c_str().with_ref |msg_p| {
+                sys::begin_unwind_(msg_p, file, line)
             }
         }
     }
@@ -113,7 +89,8 @@ unsafe fn debug_borrow<T>(tag: &'static str,
     //! A useful debugging function that prints a pointer + tag + newline
     //! without allocating memory.
 
-    if ENABLE_DEBUG && ::rt::env::get().debug_borrow {
+    // XXX
+    if false {
         debug_borrow_slow(tag, p, old_bits, new_bits, filename, line);
     }
 
@@ -231,8 +208,8 @@ pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint,
             let br = borrow_list.pop();
             if br.box != a || br.file != file || br.line != line {
                 let err = fmt!("wrong borrow found, br=%?", br);
-                do err.as_c_str |msg_p| {
-                    sys::begin_unwind_(msg_p as *c_char, file, line)
+                do err.to_c_str().with_ref |msg_p| {
+                    sys::begin_unwind_(msg_p, file, line)
                 }
             }
             borrow_list
@@ -269,15 +246,3 @@ pub unsafe fn check_not_borrowed(a: *u8,
         fail_borrowed(a, file, line);
     }
 }
-
-
-extern {
-    #[rust_stack]
-    pub fn rust_take_task_borrow_list(task: *rust_task) -> *c_void;
-
-    #[rust_stack]
-    pub fn rust_set_task_borrow_list(task: *rust_task, map: *c_void);
-
-    #[rust_stack]
-    pub fn rust_try_get_task() -> *rust_task;
-}
index 6dc44dd1193b9e57532df2ca6a55029ec4e307c4..793e244bec7b937276096033741de9751dc5cf53 100644 (file)
@@ -15,6 +15,7 @@
 use ops::Drop;
 use rt::kill::BlockedTask;
 use kinds::Send;
+use rt;
 use rt::sched::Scheduler;
 use rt::local::Local;
 use rt::select::{Select, SelectPort};
@@ -24,7 +25,6 @@
 use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable};
 use cell::Cell;
 use clone::Clone;
-use rt::{context, SchedulerContext};
 use tuple::ImmutableTuple;
 
 /// A combined refcount / BlockedTask-as-uint pointer.
@@ -113,7 +113,7 @@ pub fn try_send_deferred(self, val: T) -> bool {
     // 'do_resched' configures whether the scheduler immediately switches to
     // the receiving task, or leaves the sending task still running.
     fn try_send_inner(self, val: T, do_resched: bool) -> bool {
-        rtassert!(context() != SchedulerContext);
+        rtassert!(!rt::in_sched_context());
 
         let mut this = self;
         let mut recvr_active = true;
@@ -225,9 +225,10 @@ fn optimistic_check(&mut self) -> bool {
     fn optimistic_check(&mut self) -> bool {
         // The optimistic check is never necessary for correctness. For testing
         // purposes, making it randomly return false simulates a racing sender.
-        use rand::{Rand, rng};
-        let mut rng = rng();
-        let actually_check = Rand::rand(&mut rng);
+        use rand::{Rand};
+        let actually_check = do Local::borrow::<Scheduler, bool> |sched| {
+            Rand::rand(&mut sched.rng)
+        };
         if actually_check {
             unsafe { (*self.packet()).state.load(Acquire) == STATE_ONE }
         } else {
index 6e671742fb6fdfa7fd8c8c71b8ed58fcbd34faca..3ca39acbfcdf4c8f05bc25a213186c619bbd2040 100644 (file)
 //! Runtime environment settings
 
 use from_str::FromStr;
-use libc::{size_t, c_char, c_int};
 use option::{Some, None};
 use os;
 
-// OLD RT stuff
-
-pub struct Environment {
-    /// The number of threads to use by default
-    num_sched_threads: size_t,
-    /// The minimum size of a stack segment
-    min_stack_size: size_t,
-    /// The maximum amount of total stack per task before aborting
-    max_stack_size: size_t,
-    /// The default logging configuration
-    logspec: *c_char,
-    /// Record and report detailed information about memory leaks
-    detailed_leaks: bool,
-    /// Seed the random number generator
-    rust_seed: *c_char,
-    /// Poison allocations on free
-    poison_on_free: bool,
-    /// The argc value passed to main
-    argc: c_int,
-    /// The argv value passed to main
-    argv: **c_char,
-    /// Print GC debugging info (true if env var RUST_DEBUG_MEM is set)
-    debug_mem: bool,
-    /// Print GC debugging info (true if env var RUST_DEBUG_BORROW is set)
-    debug_borrow: bool,
-}
-
-/// Get the global environment settings
-/// # Safety Note
-/// This will abort the process if run outside of task context
-pub fn get() -> &Environment {
-    unsafe { rust_get_rt_env() }
-}
-
-extern {
-    fn rust_get_rt_env() -> &Environment;
-}
-
-// NEW RT stuff
-
 // Note that these are all accessed without any synchronization.
 // They are expected to be initialized once then left alone.
 
index 7e891f1718e2111016751c745a67275906d0b212..6a3e44b2a4d7009a3c914c08a4de7530501c3cae 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use prelude::*;
+use option::Option;
+use comm::{GenericPort, GenericChan};
 use super::{Reader, Writer};
 
 struct PortReader<P>;
index 815ec9b5c61ec56284ba436caa1a35af611af5b8..77176088801de7fc4f5c08e42451ad9af570239f 100644 (file)
@@ -9,7 +9,11 @@
 // except according to those terms.
 
 use num::FromStrRadix;
+use vec::MutableCloneableVector;
 use to_str::ToStr;
+use from_str::FromStr;
+use option::{Option, None, Some};
+
 
 type Port = u16;
 
@@ -39,7 +43,7 @@ fn to_str(&self) -> ~str {
             }
 
             // Ipv4-Mapped address
-            Ipv6Addr(0, 0, 0, 0, 0, 1, g, h) => {
+            Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, g, h) => {
                 let a = fmt!("%04x", g as uint);
                 let b = FromStrRadix::from_str_radix(a.slice(2, 4), 16).unwrap();
                 let a = FromStrRadix::from_str_radix(a.slice(0, 2), 16).unwrap();
@@ -73,3 +77,371 @@ fn to_str(&self) -> ~str {
         }
     }
 }
+
+struct Parser<'self> {
+    // parsing as ASCII, so can use byte array
+    s: &'self [u8],
+    pos: uint,
+}
+
+impl<'self> Parser<'self> {
+    fn new(s: &'self str) -> Parser<'self> {
+        Parser {
+            s: s.as_bytes(),
+            pos: 0,
+        }
+    }
+
+    fn is_eof(&self) -> bool {
+        self.pos == self.s.len()
+    }
+
+    // Commit only if parser returns Some
+    fn read_atomically<T>(&mut self, cb: &fn(&mut Parser) -> Option<T>) -> Option<T> {
+        let pos = self.pos;
+        let r = cb(self);
+        if r.is_none() {
+            self.pos = pos;
+        }
+        r
+    }
+
+    // Commit only if parser read till EOF
+    fn read_till_eof<T>(&mut self, cb: &fn(&mut Parser) -> Option<T>) -> Option<T> {
+        do self.read_atomically |p| {
+            cb(p).filtered(|_| p.is_eof())
+        }
+    }
+
+    // Return result of first successful parser
+    fn read_or<T>(&mut self, parsers: &[&fn(&mut Parser) -> Option<T>]) -> Option<T> {
+        for pf in parsers.iter() {
+            match self.read_atomically(|p: &mut Parser| (*pf)(p)) {
+                Some(r) => return Some(r),
+                None => {}
+            }
+        }
+        None
+    }
+
+    // Apply 3 parsers sequentially
+    fn read_seq_3<A, B, C>(&mut self,
+            pa: &fn(&mut Parser) -> Option<A>,
+            pb: &fn(&mut Parser) -> Option<B>,
+            pc: &fn(&mut Parser) -> Option<C>
+        ) -> Option<(A, B, C)>
+    {
+        do self.read_atomically |p| {
+            let a = pa(p);
+            let b = if a.is_some() { pb(p) } else { None };
+            let c = if b.is_some() { pc(p) } else { None };
+            match (a, b, c) {
+                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
+                _ => None
+            }
+        }
+    }
+
+    // Read next char
+    fn read_char(&mut self) -> Option<char> {
+        if self.is_eof() {
+            None
+        } else {
+            let r = self.s[self.pos] as char;
+            self.pos += 1;
+            Some(r)
+        }
+    }
+
+    // Return char and advance iff next char is equal to requested
+    fn read_given_char(&mut self, c: char) -> Option<char> {
+        do self.read_atomically |p| {
+            p.read_char().filtered(|&next| next == c)
+        }
+    }
+
+    // Read digit
+    fn read_digit(&mut self, radix: u8) -> Option<u8> {
+        fn parse_digit(c: char, radix: u8) -> Option<u8> {
+            // assuming radix is either 10 or 16
+            if c >= '0' && c <= '9' {
+                Some((c - '0') as u8)
+            } else if radix > 10 && c >= 'a' && c < 'a' + (radix - 10) as char {
+                Some((c - 'a' + (10 as char)) as u8)
+            } else if radix > 10 && c >= 'A' && c < 'A' + (radix - 10) as char {
+                Some((c - 'A' + (10 as char)) as u8)
+            } else {
+                None
+            }
+        }
+
+        do self.read_atomically |p| {
+            p.read_char().chain(|c| parse_digit(c, radix))
+        }
+    }
+
+    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
+        let mut r = 0u32;
+        let mut digit_count = 0;
+        loop {
+            match self.read_digit(radix) {
+                Some(d) => {
+                    r = r * (radix as u32) + (d as u32);
+                    digit_count += 1;
+                    if digit_count > max_digits || r >= upto {
+                        return None
+                    }
+                }
+                None => {
+                    if digit_count == 0 {
+                        return None
+                    } else {
+                        return Some(r)
+                    }
+                }
+            };
+        }
+    }
+
+    // Read number, failing if max_digits of number value exceeded
+    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
+        do self.read_atomically |p| {
+            p.read_number_impl(radix, max_digits, upto)
+        }
+    }
+
+    fn read_ipv4_addr_impl(&mut self) -> Option<IpAddr> {
+        let mut bs = [0u8, ..4];
+        let mut i = 0;
+        while i < 4 {
+            if i != 0 && self.read_given_char('.').is_none() {
+                return None;
+            }
+
+            let octet = self.read_number(10, 3, 0x100).map(|&n| n as u8);
+            match octet {
+                Some(d) => bs[i] = d,
+                None => return None,
+            };
+            i += 1;
+        }
+        Some(Ipv4Addr(bs[0], bs[1], bs[2], bs[3]))
+    }
+
+    // Read IPv4 address
+    fn read_ipv4_addr(&mut self) -> Option<IpAddr> {
+        do self.read_atomically |p| {
+            p.read_ipv4_addr_impl()
+        }
+    }
+
+    fn read_ipv6_addr_impl(&mut self) -> Option<IpAddr> {
+        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr {
+            assert!(head.len() + tail.len() <= 8);
+            let mut gs = [0u16, ..8];
+            gs.copy_from(head);
+            gs.mut_slice(8 - tail.len(), 8).copy_from(tail);
+            Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
+        }
+
+        fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) {
+            let mut i = 0;
+            while i < limit {
+                if i < limit - 1 {
+                    let ipv4 = do p.read_atomically |p| {
+                        if i == 0 || p.read_given_char(':').is_some() {
+                            p.read_ipv4_addr()
+                        } else {
+                            None
+                        }
+                    };
+                    match ipv4 {
+                        Some(Ipv4Addr(a, b, c, d)) => {
+                            groups[i + 0] = (a as u16 << 8) | (b as u16);
+                            groups[i + 1] = (c as u16 << 8) | (d as u16);
+                            return (i + 2, true);
+                        }
+                        _ => {}
+                    }
+                }
+
+                let group = do p.read_atomically |p| {
+                    if i == 0 || p.read_given_char(':').is_some() {
+                        p.read_number(16, 4, 0x10000).map(|&n| n as u16)
+                    } else {
+                        None
+                    }
+                };
+                match group {
+                    Some(g) => groups[i] = g,
+                    None => return (i, false)
+                }
+                i += 1;
+            }
+            (i, false)
+        }
+
+        let mut head = [0u16, ..8];
+        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
+
+        if head_size == 8 {
+            return Some(Ipv6Addr(
+                head[0], head[1], head[2], head[3],
+                head[4], head[5], head[6], head[7]))
+        }
+
+        // IPv4 part is not allowed before `::`
+        if head_ipv4 {
+            return None
+        }
+
+        // read `::` if previous code parsed less than 8 groups
+        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
+            return None;
+        }
+
+        let mut tail = [0u16, ..8];
+        let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
+        Some(ipv6_addr_from_head_tail(head.slice(0, head_size), tail.slice(0, tail_size)))
+    }
+
+    fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
+        do self.read_atomically |p| {
+            p.read_ipv6_addr_impl()
+        }
+    }
+
+    fn read_ip_addr(&mut self) -> Option<IpAddr> {
+        let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr();
+        let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr();
+        self.read_or([ipv4_addr, ipv6_addr])
+    }
+
+    fn read_socket_addr(&mut self) -> Option<SocketAddr> {
+        let ip_addr = |p: &mut Parser| {
+            let ipv4_p = |p: &mut Parser| p.read_ip_addr();
+            let ipv6_p = |p: &mut Parser| {
+                let open_br = |p: &mut Parser| p.read_given_char('[');
+                let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
+                let clos_br = |p: &mut Parser| p.read_given_char(']');
+                p.read_seq_3::<char, IpAddr, char>(open_br, ip_addr, clos_br)
+                        .map(|&t| match t { (_, ip, _) => ip })
+            };
+            p.read_or([ipv4_p, ipv6_p])
+        };
+        let colon = |p: &mut Parser| p.read_given_char(':');
+        let port  = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|&n| n as u16);
+
+        // host, colon, port
+        self.read_seq_3::<IpAddr, char, u16>(ip_addr, colon, port)
+                .map(|&t| match t { (ip, _, port) => SocketAddr { ip: ip, port: port } })
+    }
+}
+
+impl FromStr for IpAddr {
+    fn from_str(s: &str) -> Option<IpAddr> {
+        do Parser::new(s).read_till_eof |p| {
+            p.read_ip_addr()
+        }
+    }
+}
+
+impl FromStr for SocketAddr {
+    fn from_str(s: &str) -> Option<SocketAddr> {
+        do Parser::new(s).read_till_eof |p| {
+            p.read_socket_addr()
+        }
+    }
+}
+
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use from_str::FromStr;
+    use option::{Some, None};
+
+    #[test]
+    fn test_from_str_ipv4() {
+        assert_eq!(Some(Ipv4Addr(127, 0, 0, 1)), FromStr::from_str("127.0.0.1"));
+        assert_eq!(Some(Ipv4Addr(255, 255, 255, 255)), FromStr::from_str("255.255.255.255"));
+        assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0"));
+
+        // out of range
+        assert_eq!(None, FromStr::from_str::<IpAddr>("256.0.0.1"));
+        // too short
+        assert_eq!(None, FromStr::from_str::<IpAddr>("255.0.0"));
+        // too long
+        assert_eq!(None, FromStr::from_str::<IpAddr>("255.0.0.1.2"));
+        // no number between dots
+        assert_eq!(None, FromStr::from_str::<IpAddr>("255.0..1"));
+    }
+
+    #[test]
+    fn test_from_str_ipv6() {
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("0:0:0:0:0:0:0:0"));
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("0:0:0:0:0:0:0:1"));
+
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("::1"));
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("::"));
+
+        assert_eq!(Some(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
+                FromStr::from_str("2a02:6b8::11:11"));
+
+        // too long group
+        assert_eq!(None, FromStr::from_str::<IpAddr>("::00000"));
+        // too short
+        assert_eq!(None, FromStr::from_str::<IpAddr>("1:2:3:4:5:6:7"));
+        // too long
+        assert_eq!(None, FromStr::from_str::<IpAddr>("1:2:3:4:5:6:7:8:9"));
+        // triple colon
+        assert_eq!(None, FromStr::from_str::<IpAddr>("1:2:::6:7:8"));
+        // two double colons
+        assert_eq!(None, FromStr::from_str::<IpAddr>("1:2::6::8"));
+    }
+
+    #[test]
+    fn test_from_str_ipv4_in_ipv6() {
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)),
+                FromStr::from_str("::192.0.2.33"));
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
+                FromStr::from_str("::FFFF:192.0.2.33"));
+        assert_eq!(Some(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
+                FromStr::from_str("64:ff9b::192.0.2.33"));
+        assert_eq!(Some(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
+                FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33"));
+
+        // colon after v4
+        assert_eq!(None, FromStr::from_str::<IpAddr>("::127.0.0.1:"));
+        // not enought groups
+        assert_eq!(None, FromStr::from_str::<IpAddr>("1.2.3.4.5:127.0.0.1"));
+        // too many groups
+        assert_eq!(None, FromStr::from_str::<IpAddr>("1.2.3.4.5:6:7:127.0.0.1"));
+    }
+
+    #[test]
+    fn test_from_str_socket_addr() {
+        assert_eq!(Some(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }),
+                FromStr::from_str("77.88.21.11:80"));
+        assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }),
+                FromStr::from_str("[2a02:6b8:0:1::1]:53"));
+        assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }),
+                FromStr::from_str("[::127.0.0.1]:22"));
+
+        // without port
+        assert_eq!(None, FromStr::from_str::<SocketAddr>("127.0.0.1"));
+        // without port
+        assert_eq!(None, FromStr::from_str::<SocketAddr>("127.0.0.1:"));
+        // wrong brackets around v4
+        assert_eq!(None, FromStr::from_str::<SocketAddr>("[127.0.0.1]:22"));
+        // port out of range
+        assert_eq!(None, FromStr::from_str::<SocketAddr>("127.0.0.1:123456"));
+    }
+
+    #[test]
+    fn ipv6_addr_to_str() {
+        let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
+        assert!(a1.to_str() == ~"::ffff:192.0.2.128" || a1.to_str() == ~"::FFFF:192.0.2.128");
+    }
+
+}
index e07cb1425bf75819efa2dfc1a58568e5518fe0f3..07b4ea10b6a3712200fe949b5e020bb0902c4574 100644 (file)
@@ -239,7 +239,7 @@ pub fn make_selectable(self, num_handles: uint) -> ~[BlockedTask] {
         };
         // Even if the task was unkillable before, we use 'Killable' because
         // multiple pipes will have handles. It does not really mean killable.
-        handles.consume_iter().transform(|x| Killable(x)).collect()
+        handles.move_iter().map(|x| Killable(x)).collect()
     }
 
     // This assertion has two flavours because the wake involves an atomic op.
index e1e7ceacc383405cbac8336f1e64effe1b25e9ab..11afd03033a90fdf05ad93a4b93722ba672e589c 100644 (file)
@@ -13,8 +13,6 @@
 use libc;
 use libc::{c_void, uintptr_t, size_t};
 use ops::Drop;
-use rt;
-use rt::OldTaskContext;
 use rt::local::Local;
 use rt::task::Task;
 use unstable::raw;
@@ -86,54 +84,41 @@ fn drop(&self) {
 
 // A little compatibility function
 pub unsafe fn local_free(ptr: *libc::c_char) {
-    match rt::context() {
-        OldTaskContext => {
-            rust_upcall_free_noswitch(ptr);
-
-            extern {
-                #[fast_ffi]
-                fn rust_upcall_free_noswitch(ptr: *libc::c_char);
-            }
-        }
-        _ => {
-            do Local::borrow::<Task,()> |task| {
-                task.heap.free(ptr as *libc::c_void);
-            }
-        }
+    do Local::borrow::<Task,()> |task| {
+        task.heap.free(ptr as *libc::c_void);
     }
 }
 
 pub fn live_allocs() -> *raw::Box<()> {
-    let region = match rt::context() {
-        OldTaskContext => {
-            unsafe { rust_current_boxed_region() }
-        }
-        _ => {
-            do Local::borrow::<Task, *BoxedRegion> |task| {
-                task.heap.boxed_region
-            }
-        }
+    let region = do Local::borrow::<Task, *BoxedRegion> |task| {
+        task.heap.boxed_region
     };
 
     return unsafe { (*region).live_allocs };
 }
 
 extern {
+    #[fast_ffi]
     fn rust_new_memory_region(synchronized: uintptr_t,
                                detailed_leaks: uintptr_t,
                                poison_on_free: uintptr_t) -> *MemoryRegion;
+    #[fast_ffi]
     fn rust_delete_memory_region(region: *MemoryRegion);
+    #[fast_ffi]
     fn rust_new_boxed_region(region: *MemoryRegion,
                              poison_on_free: uintptr_t) -> *BoxedRegion;
+    #[fast_ffi]
     fn rust_delete_boxed_region(region: *BoxedRegion);
+    #[fast_ffi]
     fn rust_boxed_region_malloc(region: *BoxedRegion,
                                 td: *TypeDesc,
                                 size: size_t) -> *OpaqueBox;
+    #[fast_ffi]
     fn rust_boxed_region_realloc(region: *BoxedRegion,
                                  ptr: *OpaqueBox,
                                  size: size_t) -> *OpaqueBox;
+    #[fast_ffi]
     fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox);
-    fn rust_current_boxed_region() -> *BoxedRegion;
 }
 
 #[cfg(test)]
index 9056f0d52e09a1492231a472b122ae773bcbdc6a..117795f6c90e0ab49860e92cd73c6277fceea12a 100644 (file)
@@ -58,15 +58,15 @@ fn print(s: &str) {
 /// Configure logging by traversing the crate map and setting the
 /// per-module global logging flags based on the logging spec
 pub fn init(crate_map: *u8) {
+    use c_str::ToCStr;
     use os;
-    use str::StrSlice;
     use ptr;
     use option::{Some, None};
 
     let log_spec = os::getenv("RUST_LOG");
     match log_spec {
         Some(spec) => {
-            do spec.as_c_str |buf| {
+            do spec.to_c_str().with_ref |buf| {
                 unsafe { rust_update_log_settings(crate_map, buf) }
             }
         }
index 147c75e5c41ef1bc47fdc7a358799c9588acb3bf..1b9f28b95fb3fc27b5042e067f933922b41d78ee 100644 (file)
@@ -63,8 +63,7 @@
 use cell::Cell;
 use clone::Clone;
 use container::Container;
-use iter::Times;
-use iterator::{Iterator, IteratorUtil};
+use iterator::{Iterator, range};
 use option::{Some, None};
 use ptr::RawPtr;
 use rt::local::Local;
 /// Bindings to system threading libraries.
 mod thread;
 
-/// The runtime configuration, read from environment variables
+/// The runtime configuration, read from environment variables.
 pub mod env;
 
 /// The local, managed heap
@@ -247,11 +246,16 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
 
     let main = Cell::new(main);
 
-    // The shared list of sleeping schedulers. Schedulers wake each other
-    // occassionally to do new work.
+    // The shared list of sleeping schedulers.
     let sleepers = SleeperList::new();
-    // The shared work queue. Temporary until work stealing is implemented.
-    let work_queue = WorkQueue::new();
+
+    // 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);
+    }
 
     // The schedulers.
     let mut scheds = ~[];
@@ -259,12 +263,15 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
     // sent the Shutdown message to terminate the schedulers.
     let mut handles = ~[];
 
-    do nscheds.times {
+    for i in range(0u, nscheds) {
         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_queue.clone(), sleepers.clone());
+        let mut sched = ~Scheduler::new(loop_,
+                                        work_queues[i].clone(),
+                                        work_queues.clone(),
+                                        sleepers.clone());
         let handle = sched.make_handle();
 
         scheds.push(sched);
@@ -280,9 +287,14 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
         let friend_handle = friend_sched.make_handle();
         scheds.push(friend_sched);
 
+        // This scheduler needs a queue that isn't part of the stealee
+        // set.
+        let work_queue = WorkQueue::new();
+
         let main_loop = ~UvEventLoop::new();
         let mut main_sched = ~Scheduler::new_special(main_loop,
-                                                     work_queue.clone(),
+                                                     work_queue,
+                                                     work_queues.clone(),
                                                      sleepers.clone(),
                                                      false,
                                                      Some(friend_handle));
@@ -371,7 +383,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
         let mut main_task = ~Task::new_root_homed(&mut main_sched.stack_pool, None,
                                                   home, main.take());
         main_task.death.on_exit = Some(on_exit.take());
-        rtdebug!("boostrapping main_task");
+        rtdebug!("bootstrapping main_task");
 
         main_sched.bootstrap(main_task);
     }
@@ -379,7 +391,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
     rtdebug!("waiting for threads");
 
     // Wait for schedulers
-    for thread in threads.consume_iter() {
+    for thread in threads.move_iter() {
         thread.join();
     }
 
@@ -389,46 +401,30 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
     }
 }
 
-/// Possible contexts in which Rust code may be executing.
-/// Different runtime services are available depending on context.
-/// Mostly used for determining if we're using the new scheduler
-/// or the old scheduler.
-#[deriving(Eq)]
-pub enum RuntimeContext {
-    // Only the exchange heap is available
-    GlobalContext,
-    // The scheduler may be accessed
-    SchedulerContext,
-    // Full task services, e.g. local heap, unwinding
-    TaskContext,
-    // Running in an old-style task
-    OldTaskContext
-}
-
-/// Determine the current RuntimeContext
-pub fn context() -> RuntimeContext {
-
-    use task::rt::rust_task;
-
-    if unsafe { rust_try_get_task().is_not_null() } {
-        return OldTaskContext;
-    } else if Local::exists::<Task>() {
-        // In this case we know it is a new runtime context, but we
-        // need to check which one. Going to try borrowing task to
-        // check. Task should always be in TLS, so hopefully this
-        // doesn't conflict with other ops that borrow.
-        return do Local::borrow::<Task,RuntimeContext> |task| {
-            match task.task_type {
-                SchedTask => SchedulerContext,
-                GreenTask(_) => TaskContext
+pub fn in_sched_context() -> bool {
+    unsafe {
+        match Local::try_unsafe_borrow::<Task>() {
+            Some(task) => {
+                match (*task).task_type {
+                    SchedTask => true,
+                    _ => false
+                }
             }
-        };
-    } else {
-        return GlobalContext;
+            None => false
+        }
     }
+}
 
-    extern {
-        #[rust_stack]
-        pub fn rust_try_get_task() -> *rust_task;
+pub fn in_green_task_context() -> bool {
+    unsafe {
+        match Local::try_unsafe_borrow::<Task>() {
+            Some(task) => {
+                match (*task).task_type {
+                    GreenTask(_) => true,
+                    _ => false
+                }
+            }
+            None => false
+        }
     }
 }
index 990e1a4a3de9915cb65355119d555b7a9e55fe3f..ce4e64c47d2ef5cb3faefd7cd5ead4bf9400d9e3 100644 (file)
@@ -13,7 +13,6 @@
 use cast::{transmute, transmute_mut_region, transmute_mut_unsafe};
 use clone::Clone;
 use unstable::raw;
-
 use super::sleeper_list::SleeperList;
 use super::work_queue::WorkQueue;
 use super::stack::{StackPool};
@@ -28,6 +27,9 @@
 use rt::metrics::SchedMetrics;
 use borrow::{to_uint};
 use cell::Cell;
+use rand::{XorShiftRng, RngUtil};
+use iterator::{range};
+use vec::{OwnedVector};
 
 /// The Scheduler is responsible for coordinating execution of Coroutines
 /// on a single thread. When the scheduler is running it is owned by
 /// XXX: This creates too many callbacks to run_sched_once, resulting
 /// in too much allocation and too many events.
 pub struct Scheduler {
-    /// A queue of available work. Under a work-stealing policy there
-    /// is one per Scheduler.
-    work_queue: WorkQueue<~Task>,
+    /// There are N work queues, one per scheduler.
+    priv work_queue: WorkQueue<~Task>,
+    /// Work queues for the other schedulers. These are created by
+    /// cloning the core work queues.
+    work_queues: ~[WorkQueue<~Task>],
     /// The queue of incoming messages from other schedulers.
     /// These are enqueued by SchedHandles after which a remote callback
     /// is triggered to handle the message.
@@ -70,7 +74,10 @@ pub struct Scheduler {
     run_anything: bool,
     /// If the scheduler shouldn't run some tasks, a friend to send
     /// them to.
-    friend_handle: Option<SchedHandle>
+    friend_handle: Option<SchedHandle>,
+    /// A fast XorShift rng for scheduler use
+    rng: XorShiftRng
+
 }
 
 pub struct SchedHandle {
@@ -97,10 +104,13 @@ pub fn sched_id(&self) -> uint { to_uint(self) }
 
     pub fn new(event_loop: ~EventLoopObject,
                work_queue: WorkQueue<~Task>,
+               work_queues: ~[WorkQueue<~Task>],
                sleeper_list: SleeperList)
         -> Scheduler {
 
-        Scheduler::new_special(event_loop, work_queue, sleeper_list, true, None)
+        Scheduler::new_special(event_loop, work_queue,
+                               work_queues,
+                               sleeper_list, true, None)
 
     }
 
@@ -108,6 +118,7 @@ pub fn new(event_loop: ~EventLoopObject,
     // task field is None.
     pub fn new_special(event_loop: ~EventLoopObject,
                        work_queue: WorkQueue<~Task>,
+                       work_queues: ~[WorkQueue<~Task>],
                        sleeper_list: SleeperList,
                        run_anything: bool,
                        friend: Option<SchedHandle>)
@@ -120,12 +131,14 @@ pub fn new_special(event_loop: ~EventLoopObject,
             no_sleep: false,
             event_loop: event_loop,
             work_queue: work_queue,
+            work_queues: work_queues,
             stack_pool: StackPool::new(),
             sched_task: None,
             cleanup_job: None,
             metrics: SchedMetrics::new(),
             run_anything: run_anything,
-            friend_handle: friend
+            friend_handle: friend,
+            rng: XorShiftRng::new()
         }
     }
 
@@ -248,7 +261,7 @@ fn run_sched_once() {
 
         // Second activity is to try resuming a task from the queue.
 
-        let result = sched.resume_task_from_queue();
+        let result = sched.do_work();
         let mut sched = match result {
             Some(sched) => {
                 // Failed to dequeue a task, so we return.
@@ -415,47 +428,98 @@ fn send_to_friend(&mut self, task: ~Task) {
         }
     }
 
-    // Resume a task from the queue - but also take into account that
-    // it might not belong here.
+    // Workstealing: In this iteration of the runtime each scheduler
+    // thread has a distinct work queue. When no work is available
+    // locally, make a few attempts to steal work from the queues of
+    // other scheduler threads. If a few steals fail we end up in the
+    // old "no work" path which is fine.
+
+    // First step in the process is to find a task. This function does
+    // that by first checking the local queue, and if there is no work
+    // there, trying to steal from the remote work queues.
+    fn find_work(&mut self) -> Option<~Task> {
+        rtdebug!("scheduler looking for work");
+        match self.work_queue.pop() {
+            Some(task) => {
+                rtdebug!("found a task locally");
+                return Some(task)
+            }
+            None => {
+                // Our naive stealing, try kinda hard.
+                rtdebug!("scheduler trying to steal");
+                let _len = self.work_queues.len();
+                return self.try_steals(2);
+            }
+        }
+    }
+
+    // With no backoff try stealing n times from the queues the
+    // scheduler knows about. This naive implementation can steal from
+    // our own queue or from other special schedulers.
+    fn try_steals(&mut self, n: uint) -> Option<~Task> {
+        for _ in range(0, n) {
+            let index = self.rng.gen_uint_range(0, self.work_queues.len());
+            let work_queues = &mut self.work_queues;
+            match work_queues[index].steal() {
+                Some(task) => {
+                    rtdebug!("found task by stealing"); return Some(task)
+                }
+                None => ()
+            }
+        };
+        rtdebug!("giving up on stealing");
+        return None;
+    }
 
-    // If we perform a scheduler action we give away the scheduler ~
-    // pointer, if it is still available we return it.
+    // Given a task, execute it correctly.
+    fn process_task(~self, task: ~Task) -> Option<~Scheduler> {
+        let mut this = self;
+        let mut task = task;
 
-    fn resume_task_from_queue(~self) -> Option<~Scheduler> {
+        rtdebug!("processing a task");
 
+        let home = task.take_unwrap_home();
+        match home {
+            Sched(home_handle) => {
+                if home_handle.sched_id != this.sched_id() {
+                    rtdebug!("sending task home");
+                    task.give_home(Sched(home_handle));
+                    Scheduler::send_task_home(task);
+                    return Some(this);
+                } else {
+                    rtdebug!("running task here");
+                    task.give_home(Sched(home_handle));
+                    this.resume_task_immediately(task);
+                    return None;
+                }
+            }
+            AnySched if this.run_anything => {
+                rtdebug!("running anysched task here");
+                task.give_home(AnySched);
+                this.resume_task_immediately(task);
+                return None;
+            }
+            AnySched => {
+                rtdebug!("sending task to friend");
+                task.give_home(AnySched);
+                this.send_to_friend(task);
+                return Some(this);
+            }
+        }
+    }
+
+    // Bundle the helpers together.
+    fn do_work(~self) -> Option<~Scheduler> {
         let mut this = self;
 
-        match this.work_queue.pop() {
+        rtdebug!("scheduler calling do work");
+        match this.find_work() {
             Some(task) => {
-                let mut task = task;
-                let home = task.take_unwrap_home();
-                match home {
-                    Sched(home_handle) => {
-                        if home_handle.sched_id != this.sched_id() {
-                            task.give_home(Sched(home_handle));
-                            Scheduler::send_task_home(task);
-                            return Some(this);
-                        } else {
-                            this.event_loop.callback(Scheduler::run_sched_once);
-                            task.give_home(Sched(home_handle));
-                            this.resume_task_immediately(task);
-                            return None;
-                        }
-                    }
-                    AnySched if this.run_anything => {
-                        this.event_loop.callback(Scheduler::run_sched_once);
-                        task.give_home(AnySched);
-                        this.resume_task_immediately(task);
-                        return None;
-                    }
-                    AnySched => {
-                        task.give_home(AnySched);
-                        this.send_to_friend(task);
-                        return Some(this);
-                    }
-                }
+                rtdebug!("found some work! processing the task");
+                return this.process_task(task);
             }
             None => {
+                rtdebug!("no work was found, returning the scheduler struct");
                 return Some(this);
             }
         }
@@ -711,7 +775,6 @@ pub fn run_cleanup_job(&mut self) {
             GiveTask(task, f) => f.to_fn()(self, task)
         }
     }
-
 }
 
 // The cases for the below function.
@@ -745,6 +808,8 @@ fn to_fn(self) -> &fn(&mut Scheduler, ~Task) { unsafe { transmute(self) } }
 
 #[cfg(test)]
 mod test {
+    extern mod extra;
+
     use prelude::*;
     use rt::test::*;
     use unstable::run_in_bare_thread;
@@ -862,12 +927,15 @@ fn test_schedule_home_states() {
         do run_in_bare_thread {
 
             let sleepers = SleeperList::new();
-            let work_queue = WorkQueue::new();
+            let normal_queue = WorkQueue::new();
+            let special_queue = WorkQueue::new();
+            let queues = ~[normal_queue.clone(), special_queue.clone()];
 
             // Our normal scheduler
             let mut normal_sched = ~Scheduler::new(
                 ~UvEventLoop::new(),
-                work_queue.clone(),
+                normal_queue,
+                queues.clone(),
                 sleepers.clone());
 
             let normal_handle = Cell::new(normal_sched.make_handle());
@@ -877,7 +945,8 @@ fn test_schedule_home_states() {
             // Our special scheduler
             let mut special_sched = ~Scheduler::new_special(
                 ~UvEventLoop::new(),
-                work_queue.clone(),
+                special_queue.clone(),
+                queues.clone(),
                 sleepers.clone(),
                 false,
                 Some(friend_handle));
index 84ce36c3e6b5a36007f99ed280cf2b39a3b232a1..bde703af31580eb382cf60a315a96cfbe989b9ce 100644 (file)
@@ -54,7 +54,7 @@ pub fn select<A: Select>(ports: &mut [A]) -> uint {
         let task_handles = task.make_selectable(ports.len());
 
         for (index, (port, task_handle)) in
-                ports.mut_iter().zip(task_handles.consume_iter()).enumerate() {
+                ports.mut_iter().zip(task_handles.move_iter()).enumerate() {
             // If one of the ports has data by now, it will wake the handle.
             if port.block_on(sched, task_handle) {
                 ready_index = index;
@@ -128,7 +128,7 @@ fn select_helper(num_ports: uint, send_on_chans: &[uint]) {
         let (ports, chans) = unzip(from_fn(num_ports, |_| oneshot::<()>()));
         let mut dead_chans = ~[];
         let mut ports = ports;
-        for (i, chan) in chans.consume_iter().enumerate() {
+        for (i, chan) in chans.move_iter().enumerate() {
             if send_on_chans.contains(&i) {
                 chan.send(());
             } else {
@@ -145,7 +145,7 @@ fn select_helper(num_ports: uint, send_on_chans: &[uint]) {
         let (ports, chans) = unzip(from_fn(num_ports, |_| stream::<()>()));
         let mut dead_chans = ~[];
         let mut ports = ports;
-        for (i, chan) in chans.consume_iter().enumerate() {
+        for (i, chan) in chans.move_iter().enumerate() {
             if send_on_chans.contains(&i) {
                 chan.send(());
             } else {
@@ -182,6 +182,7 @@ fn select_a_lot() {
     fn select_stream() {
         use util;
         use comm::GenericChan;
+        use iter::Times;
 
         // Sends 10 buffered packets, and uses select to retrieve them all.
         // Puts the port in a different spot in the vector each time.
@@ -263,6 +264,7 @@ fn select_racing_senders() {
 
         fn select_racing_senders_helper(killable: bool, send_on_chans: ~[uint]) {
             use rt::test::spawntask_random;
+            use iter::Times;
 
             do run_in_newsched_task {
                 // A bit of stress, since ordinarily this is just smoke and mirrors.
index 364439a452601e490e5f2580d629f21c6caeb40f..b50e794cce0f34b6de9850c58acc8695746b9339 100644 (file)
@@ -515,8 +515,8 @@ fn comm_oneshot() {
 
         do run_in_newsched_task {
             let (port, chan) = oneshot();
-            send_one(chan, 10);
-            assert!(recv_one(port) == 10);
+            chan.send(10);
+            assert!(port.recv() == 10);
         }
     }
 
index 792ea5eb33f5acfa138be4692e53222858c34c2a..ca94468e1adaedbb670c421840a46fd9c2d6d108 100644 (file)
@@ -15,8 +15,8 @@
 use clone::Clone;
 use container::Container;
 use iterator::{Iterator, range};
-use vec::{OwnedVector, MutableVector};
 use super::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
+use vec::{OwnedVector, MutableVector, ImmutableVector};
 use rt::sched::Scheduler;
 use unstable::run_in_bare_thread;
 use rt::thread::Thread;
 
 pub fn new_test_uv_sched() -> Scheduler {
 
+    let queue = WorkQueue::new();
+    let queues = ~[queue.clone()];
+
     let mut sched = Scheduler::new(~UvEventLoop::new(),
-                                   WorkQueue::new(),
+                                   queue,
+                                   queues,
                                    SleeperList::new());
 
     // Don't wait for the Shutdown message
@@ -164,15 +168,21 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
         };
 
         let sleepers = SleeperList::new();
-        let work_queue = WorkQueue::new();
 
         let mut handles = ~[];
         let mut scheds = ~[];
+        let mut work_queues = ~[];
 
         for _ in range(0u, nthreads) {
+            let work_queue = WorkQueue::new();
+            work_queues.push(work_queue);
+        }
+
+        for i in range(0u, nthreads) {
             let loop_ = ~UvEventLoop::new();
             let mut sched = ~Scheduler::new(loop_,
-                                            work_queue.clone(),
+                                            work_queues[i].clone(),
+                                            work_queues.clone(),
                                             sleepers.clone());
             let handle = sched.make_handle();
 
@@ -222,7 +232,7 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
         }
 
         // Wait for schedulers
-        for thread in threads.consume_iter() {
+        for thread in threads.move_iter() {
             thread.join();
         }
     }
index 40e5c8d4bf1a088d7d470e768f35a61c1afd4645..6280b64ecf51c71742a22751ef64ba176d0a0860 100644 (file)
@@ -10,7 +10,6 @@
 
 use container::Container;
 use from_str::FromStr;
-use iterator::IteratorUtil;
 use libc;
 use option::{Some, None};
 use os;
index fd3042899f6bca5e28dadc366b1ed0e0208ea8d3..c8b3d41a78d79b65e8b5316e77dcc98aa38cd529 100644 (file)
@@ -20,7 +20,6 @@
 use vec;
 use str;
 use from_str::{FromStr};
-use num;
 
 pub enum UvSocketAddr {
     UvIpv4SocketAddr(*sockaddr_in),
@@ -85,77 +84,10 @@ fn uv_socket_addr_as_socket_addr<T>(addr: UvSocketAddr, f: &fn(SocketAddr) -> T)
         port as u16
     };
     let ip_str = str::from_bytes_slice(ip_name).trim_right_chars(&'\x00');
-    let ip = match addr {
-        UvIpv4SocketAddr(*) => {
-            let ip: ~[u8] =
-                ip_str.split_iter('.')
-                      .transform(|s: &str| -> u8 { FromStr::from_str(s).unwrap() })
-                      .collect();
-            assert_eq!(ip.len(), 4);
-            SocketAddr {
-                ip: Ipv4Addr(ip[0], ip[1], ip[2], ip[3]),
-                port: ip_port
-            }
-        },
-        UvIpv6SocketAddr(*) => {
-            let ip: ~[u16] = {
-                let expand_shorthand_and_convert = |s: &str| -> ~[~[u16]] {
-                    let convert_each_segment = |s: &str| -> ~[u16] {
-                        let read_hex_segment = |s: &str| -> u16 {
-                            num::FromStrRadix::from_str_radix(s, 16u).unwrap()
-                        };
-                        match s {
-                            "" => ~[],
-                            // IPv4-Mapped/Compatible IPv6 Address?
-                            s if s.find('.').is_some() => {
-                                let i = s.rfind(':').unwrap_or_default(-1);
-
-                                let b = s.slice(i + 1, s.len()); // the ipv4 part
-
-                                let h = b.split_iter('.')
-                                   .transform(|s: &str| -> u8 { FromStr::from_str(s).unwrap() })
-                                   .transform(|s: u8| -> ~str { fmt!("%02x", s as uint) })
-                                   .collect::<~[~str]>();
-
-                                if i == -1 {
-                                    // Ipv4 Compatible Address (::x.x.x.x)
-                                    // first 96 bits are zero leaving 32 bits
-                                    // for the ipv4 part
-                                    // (i.e ::127.0.0.1 == ::7F00:1)
-                                    ~[num::FromStrRadix::from_str_radix(h[0] + h[1], 16).unwrap(),
-                                      num::FromStrRadix::from_str_radix(h[2] + h[3], 16).unwrap()]
-                                } else {
-                                    // Ipv4-Mapped Address (::FFFF:x.x.x.x)
-                                    // first 80 bits are zero, followed by all ones
-                                    // for the next 16 bits, leaving 32 bits for
-                                    // the ipv4 part
-                                    // (i.e ::FFFF:127.0.0.1 == ::FFFF:7F00:1)
-                                    ~[1,
-                                      num::FromStrRadix::from_str_radix(h[0] + h[1], 16).unwrap(),
-                                      num::FromStrRadix::from_str_radix(h[2] + h[3], 16).unwrap()]
-                                }
-                            },
-                            s => s.split_iter(':').transform(read_hex_segment).collect()
-                        }
-                    };
-                    s.split_str_iter("::").transform(convert_each_segment).collect()
-                };
-                match expand_shorthand_and_convert(ip_str) {
-                    [x] => x, // no shorthand found
-                    [l, r] => l + vec::from_elem(8 - l.len() - r.len(), 0u16) + r, // fill the gap
-                    _ => fail!(), // impossible. only one shorthand allowed.
-                }
-            };
-            assert_eq!(ip.len(), 8);
-            SocketAddr {
-                ip: Ipv6Addr(ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]),
-                port: ip_port
-            }
-        },
-    };
+    let ip_addr = FromStr::from_str(ip_str).unwrap();
 
     // finally run the closure
-    f(ip)
+    f(SocketAddr { ip: ip_addr, port: ip_port })
 }
 
 pub fn uv_socket_addr_to_socket_addr(addr: UvSocketAddr) -> SocketAddr {
index 70a397199ab7ce5b159e82f93f04618ae0a6d47b..038ebad3540aecd29657474dffaacaaf8a2ab365 100644 (file)
@@ -8,26 +8,26 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use option::*;
-use result::*;
-use ops::Drop;
-use cell::Cell;
-use cast;
+use c_str::ToCStr;
 use cast::transmute;
+use cast;
+use cell::Cell;
 use clone::Clone;
 use libc::{c_int, c_uint, c_void};
+use ops::Drop;
+use option::*;
 use ptr;
+use result::*;
 use rt::io::IoError;
 use rt::io::net::ip::{SocketAddr, IpAddr};
-use rt::uv::*;
-use rt::uv::idle::IdleWatcher;
-use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
+use rt::io::{standard_error, OtherIoError};
+use rt::local::Local;
 use rt::rtio::*;
 use rt::sched::Scheduler;
-use rt::io::{standard_error, OtherIoError};
 use rt::tube::Tube;
-use rt::local::Local;
-use str::StrSlice;
+use rt::uv::*;
+use rt::uv::idle::IdleWatcher;
+use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
 use unstable::sync::Exclusive;
 
 #[cfg(test)] use container::Container;
@@ -654,7 +654,7 @@ fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> Result<(), IoError> {
 
     fn join_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> {
         let r = unsafe {
-            do multi.to_str().as_c_str |m_addr| {
+            do multi.to_str().to_c_str().with_ref |m_addr| {
                 uvll::udp_set_membership(self.native_handle(), m_addr,
                                          ptr::null(), uvll::UV_JOIN_GROUP)
             }
@@ -668,7 +668,7 @@ fn join_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> {
 
     fn leave_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> {
         let r = unsafe {
-            do multi.to_str().as_c_str |m_addr| {
+            do multi.to_str().to_c_str().with_ref |m_addr| {
                 uvll::udp_set_membership(self.native_handle(), m_addr,
                                          ptr::null(), uvll::UV_LEAVE_GROUP)
             }
index 07264839c3555dda0107bdc085540cf2168d98b8..e240395a495d36f02f60cc0daadd06c58353c773 100644 (file)
@@ -29,6 +29,7 @@
 
 #[allow(non_camel_case_types)]; // C types
 
+use c_str::ToCStr;
 use libc::{size_t, c_int, c_uint, c_void, c_char, uintptr_t};
 use libc::{malloc, free};
 use libc;
@@ -372,12 +373,12 @@ pub unsafe fn is_ip6_addr(addr: *sockaddr) -> bool {
 }
 
 pub unsafe fn malloc_ip4_addr(ip: &str, port: int) -> *sockaddr_in {
-    do ip.as_c_str |ip_buf| {
+    do ip.to_c_str().with_ref |ip_buf| {
         rust_uv_ip4_addrp(ip_buf as *u8, port as libc::c_int)
     }
 }
 pub unsafe fn malloc_ip6_addr(ip: &str, port: int) -> *sockaddr_in6 {
-    do ip.as_c_str |ip_buf| {
+    do ip.to_c_str().with_ref |ip_buf| {
         rust_uv_ip6_addrp(ip_buf as *u8, port as libc::c_int)
     }
 }
@@ -448,13 +449,6 @@ pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 {
 pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> size_t {
     return rust_uv_get_len_from_buf(buf);
 }
-pub unsafe fn malloc_buf_base_of(suggested_size: size_t) -> *u8 {
-    return rust_uv_malloc_buf_base_of(suggested_size);
-}
-pub unsafe fn free_base_of_buf(buf: uv_buf_t) {
-    rust_uv_free_base_of_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);
@@ -558,8 +552,6 @@ fn rust_uv_timer_start(timer_handle: *uv_timer_t, cb: *u8, timeout: libc::uint64
                            repeat: libc::uint64_t) -> c_int;
     fn rust_uv_timer_stop(handle: *uv_timer_t) -> c_int;
 
-    fn rust_uv_malloc_buf_base_of(sug_size: size_t) -> *u8;
-    fn rust_uv_free_base_of_buf(buf: uv_buf_t);
     fn rust_uv_get_stream_handle_from_connect_req(connect_req: *uv_connect_t) -> *uv_stream_t;
     fn rust_uv_get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t;
     fn rust_uv_get_loop_for_uv_handle(handle: *c_void) -> *c_void;
index 99cf96eaae2fff4be0fcdd9d72a4714c5ff2f06b..31e317604c77e073ba75edde11acddec9d970e13 100644 (file)
@@ -12,6 +12,7 @@
 
 #[allow(missing_doc)];
 
+use c_str::ToCStr;
 use cast;
 use clone::Clone;
 use comm::{stream, SharedChan, GenericChan, GenericPort};
@@ -505,7 +506,7 @@ fn spawn_process_os(prog: &str, args: &[~str],
 
         do with_envp(env) |envp| {
             do with_dirp(dir) |dirp| {
-                do cmd.as_c_str |cmdp| {
+                do cmd.to_c_str().with_ref |cmdp| {
                     let created = CreateProcessA(ptr::null(), cast::transmute(cmdp),
                                                  ptr::mut_null(), ptr::mut_null(), TRUE,
                                                  0, envp, dirp, &mut si, &mut pi);
@@ -688,46 +689,62 @@ mod rustrt {
 }
 
 #[cfg(unix)]
-fn with_argv<T>(prog: &str, args: &[~str],
-                cb: &fn(**libc::c_char) -> T) -> T {
-    let mut argptrs = ~[prog.as_c_str(|b| b)];
-    let mut tmps = ~[];
+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() {
-        let t = @(*arg).clone();
-        tmps.push(t);
-        argptrs.push(t.as_c_str(|b| b));
+        tmps.push(arg.to_c_str());
     }
-    argptrs.push(ptr::null());
-    argptrs.as_imm_buf(|buf, _len| cb(buf))
+
+    // 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 {
-    // On posixy systems we can pass a char** for envp, which is
-    // a null-terminated array of "k=v\n" strings.
+    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(es) => {
-        let mut tmps = ~[];
-        let mut ptrs = ~[];
-
-        for pair in es.iter() {
-            // Use of match here is just to workaround limitations
-            // in the stage0 irrefutable pattern impl.
-            match pair {
-                &(ref k, ref v) => {
-                    let kv = @fmt!("%s=%s", *k, *v);
-                    tmps.push(kv);
-                    ptrs.push(kv.as_c_str(|b| b));
-                }
+        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());
             }
-        }
 
-        ptrs.push(ptr::null());
-        ptrs.as_imm_buf(|p, _len|
-            unsafe { cb(::cast::transmute(p)) }
-        )
-      }
-      _ => cb(ptr::null())
+            // 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())
     }
 }
 
@@ -737,25 +754,28 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T {
     // rather a concatenation of null-terminated k=v\0 sequences, with a final
     // \0 to terminate.
     match env {
-      Some(es) => {
-        let mut blk = ~[];
-        for pair in es.iter() {
-            let kv = fmt!("%s=%s", pair.first(), pair.second());
-            blk.push_all(kv.to_bytes_with_null());
+        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)) }
+            }
         }
-        blk.push(0);
-        blk.as_imm_buf(|p, _len|
-            unsafe { cb(::cast::transmute(p)) }
-        )
-      }
-      _ => cb(ptr::mut_null())
+        _ => cb(ptr::mut_null())
     }
 }
 
-fn with_dirp<T>(d: Option<&Path>,
-                cb: &fn(*libc::c_char) -> T) -> T {
+fn with_dirp<T>(d: Option<&Path>, cb: &fn(*libc::c_char) -> T) -> T {
     match d {
-      Some(dir) => dir.to_str().as_c_str(cb),
+      Some(dir) => dir.to_c_str().with_ref(|buf| cb(buf)),
       None => cb(ptr::null())
     }
 }
@@ -1309,11 +1329,11 @@ fn test_inherit_env() {
         let output = str::from_bytes(prog.finish_with_output().output);
 
         let r = os::env();
-        for &(k, v) in r.iter() {
+        for &(ref k, ref v) in r.iter() {
             // don't check android RANDOM variables
-            if k != ~"RANDOM" {
-                assert!(output.contains(fmt!("%s=%s", k, v)) ||
-                        output.contains(fmt!("%s=\'%s\'", k, v)));
+            if *k != ~"RANDOM" {
+                assert!(output.contains(fmt!("%s=%s", *k, *v)) ||
+                        output.contains(fmt!("%s=\'%s\'", *k, *v)));
             }
         }
     }
index 7000b56069df624333ba6bed60dde795a395a648..aa0bb905e9a68fb99d5933171434a21d73d4c6ef 100644 (file)
@@ -164,13 +164,13 @@ pub mod linkhack {
 
 pub mod task;
 pub mod comm;
-pub mod pipes;
 pub mod local_data;
 
 
 /* Runtime and platform support */
 
 pub mod libc;
+pub mod c_str;
 pub mod os;
 pub mod path;
 pub mod rand;
@@ -213,7 +213,6 @@ mod std {
     pub use kinds;
     pub use local_data;
     pub use sys;
-    pub use pipes;
     pub use unstable;
     pub use str;
     pub use os;
index fa75916fb8640e10785c53b3e70c6c69aab93a89..26a00cca4c82b1291c565cf1e6637ab8643b4445 100644 (file)
@@ -23,9 +23,9 @@
 use clone::Clone;
 use container::{Container, Mutable};
 use iter::Times;
-use iterator::{Iterator, FromIterator, Extendable, IteratorUtil};
+use iterator::{Iterator, FromIterator, Extendable};
 use iterator::{Filter, AdditiveIterator, Map};
-use iterator::{Invert, DoubleEndedIterator, DoubleEndedIteratorUtil};
+use iterator::{Invert, DoubleEndedIterator};
 use libc;
 use num::Zero;
 use option::{None, Option, Some};
@@ -33,6 +33,7 @@
 use ptr::RawPtr;
 use to_str::ToStr;
 use uint;
+#[cfg(stage0)]
 use unstable::raw::Repr;
 use vec;
 use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector, MutableVector};
@@ -58,7 +59,7 @@ pub fn from_bytes(vv: &[u8]) -> ~str {
     use str::not_utf8::cond;
 
     if !is_utf8(vv) {
-        let first_bad_byte = *vv.iter().find_(|&b| !is_utf8([*b])).unwrap();
+        let first_bad_byte = *vv.iter().find(|&b| !is_utf8([*b])).unwrap();
         cond.raise(fmt!("from_bytes: input is not UTF-8; first bad byte is %u",
                         first_bad_byte as uint))
     } else {
@@ -75,7 +76,7 @@ pub fn from_bytes_owned(vv: ~[u8]) -> ~str {
     use str::not_utf8::cond;
 
     if !is_utf8(vv) {
-        let first_bad_byte = *vv.iter().find_(|&b| !is_utf8([*b])).unwrap();
+        let first_bad_byte = *vv.iter().find(|&b| !is_utf8([*b])).unwrap();
         cond.raise(fmt!("from_bytes: input is not UTF-8; first bad byte is %u",
                         first_bad_byte as uint))
     } else {
@@ -83,21 +84,6 @@ pub fn from_bytes_owned(vv: ~[u8]) -> ~str {
     }
 }
 
-/// Convert a vector of bytes to a UTF-8 string.
-/// The vector needs to be one byte longer than the string, and end with a 0 byte.
-///
-/// Compared to `from_bytes()`, this fn doesn't need to allocate a new owned str.
-///
-/// # Failure
-///
-/// Fails if invalid UTF-8
-/// Fails if not null terminated
-pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str {
-    assert_eq!(vv[vv.len() - 1], 0);
-    assert!(is_utf8(vv));
-    return unsafe { raw::from_bytes_with_null(vv) };
-}
-
 /// Converts a vector to a string slice without performing any allocations.
 ///
 /// Once the slice has been validated as utf-8, it is transmuted in-place and
@@ -106,6 +92,7 @@ pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str {
 /// # Failure
 ///
 /// Fails if invalid UTF-8
+#[cfg(stage0)]
 pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
     unsafe {
         assert!(is_utf8(vector));
@@ -115,6 +102,20 @@ pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
     }
 }
 
+/// Converts a vector to a string slice without performing any allocations.
+///
+/// Once the slice has been validated as utf-8, it is transmuted in-place and
+/// returned as a '&str' instead of a '&[u8]'
+///
+/// # Failure
+///
+/// Fails if invalid UTF-8
+#[cfg(not(stage0))]
+pub fn from_bytes_slice<'a>(v: &'a [u8]) -> &'a str {
+    assert!(is_utf8(v));
+    unsafe { cast::transmute(v) }
+}
+
 impl ToStr for ~str {
     #[inline]
     fn to_str(&self) -> ~str { self.to_owned() }
@@ -133,11 +134,23 @@ fn to_str(&self) -> ~str { self.to_owned() }
 /// # Failure
 ///
 /// Fails if invalid UTF-8
+#[cfg(stage0)]
 pub fn from_byte(b: u8) -> ~str {
     assert!(b < 128u8);
     unsafe { cast::transmute(~[b, 0u8]) }
 }
 
+/// Convert a byte to a UTF-8 string
+///
+/// # Failure
+///
+/// Fails if invalid UTF-8
+#[cfg(not(stage0))]
+pub fn from_byte(b: u8) -> ~str {
+    assert!(b < 128u8);
+    unsafe { ::cast::transmute(~[b]) }
+}
+
 /// Convert a char to a string
 pub fn from_char(ch: char) -> ~str {
     let mut buf = ~"";
@@ -168,10 +181,11 @@ pub trait StrVector {
 
 impl<'self, S: Str> StrVector for &'self [S] {
     /// Concatenate a vector of strings.
+    #[cfg(stage0)]
     pub fn concat(&self) -> ~str {
         if self.is_empty() { return ~""; }
 
-        let len = self.iter().transform(|s| s.as_slice().len()).sum();
+        let len = self.iter().map(|s| s.as_slice().len()).sum();
 
         let mut s = with_capacity(len);
 
@@ -191,7 +205,32 @@ pub fn concat(&self) -> ~str {
         s
     }
 
+    /// Concatenate a vector of strings.
+    #[cfg(not(stage0))]
+    pub fn concat(&self) -> ~str {
+        if self.is_empty() { return ~""; }
+
+        let len = self.iter().map(|s| s.as_slice().len()).sum();
+
+        let mut s = with_capacity(len);
+
+        unsafe {
+            do s.as_mut_buf |buf, _| {
+                let mut buf = buf;
+                for ss in self.iter() {
+                    do ss.as_slice().as_imm_buf |ssbuf, sslen| {
+                        ptr::copy_memory(buf, ssbuf, sslen);
+                        buf = buf.offset(sslen as int);
+                    }
+                }
+            }
+            raw::set_len(&mut s, len);
+        }
+        s
+    }
+
     /// Concatenate a vector of strings, placing a given separator between each.
+    #[cfg(stage0)]
     pub fn connect(&self, sep: &str) -> ~str {
         if self.is_empty() { return ~""; }
 
@@ -200,7 +239,7 @@ pub fn connect(&self, sep: &str) -> ~str {
 
         // this is wrong without the guarantee that `self` is non-empty
         let len = sep.len() * (self.len() - 1)
-            + self.iter().transform(|s| s.as_slice().len()).sum();
+            + self.iter().map(|s| s.as_slice().len()).sum();
         let mut s = ~"";
         let mut first = true;
 
@@ -230,6 +269,45 @@ pub fn connect(&self, sep: &str) -> ~str {
         }
         s
     }
+
+    /// Concatenate a vector of strings, placing a given separator between each.
+    #[cfg(not(stage0))]
+    pub fn connect(&self, sep: &str) -> ~str {
+        if self.is_empty() { return ~""; }
+
+        // concat is faster
+        if sep.is_empty() { return self.concat(); }
+
+        // this is wrong without the guarantee that `self` is non-empty
+        let len = sep.len() * (self.len() - 1)
+            + self.iter().map(|s| s.as_slice().len()).sum();
+        let mut s = ~"";
+        let mut first = true;
+
+        s.reserve(len);
+
+        unsafe {
+            do s.as_mut_buf |buf, _| {
+                do sep.as_imm_buf |sepbuf, seplen| {
+                    let mut buf = buf;
+                    for ss in self.iter() {
+                        do ss.as_slice().as_imm_buf |ssbuf, sslen| {
+                            if first {
+                                first = false;
+                            } else {
+                                ptr::copy_memory(buf, sepbuf, seplen);
+                                buf = buf.offset(seplen as int);
+                            }
+                            ptr::copy_memory(buf, ssbuf, sslen);
+                            buf = buf.offset(sslen as int);
+                        }
+                    }
+                }
+            }
+            raw::set_len(&mut s, len);
+        }
+        s
+    }
 }
 
 /// Something that can be used to compare against a character
@@ -500,7 +578,7 @@ pub fn replace(s: &str, from: &str, to: &str) -> ~str {
 */
 
 /// Bytewise slice equality
-#[cfg(not(test))]
+#[cfg(not(test), stage0)]
 #[lang="str_eq"]
 #[inline]
 pub fn eq_slice(a: &str, b: &str) -> bool {
@@ -518,7 +596,28 @@ pub fn eq_slice(a: &str, b: &str) -> bool {
     }
 }
 
-#[cfg(test)]
+/// Bytewise slice equality
+#[cfg(not(test), not(stage0))]
+#[lang="str_eq"]
+#[inline]
+pub fn eq_slice(a: &str, b: &str) -> bool {
+    do a.as_imm_buf |ap, alen| {
+        do b.as_imm_buf |bp, blen| {
+            if (alen != blen) { false }
+            else {
+                unsafe {
+                    libc::memcmp(ap as *libc::c_void,
+                                 bp as *libc::c_void,
+                                 alen as libc::size_t) == 0
+                }
+            }
+        }
+    }
+}
+
+/// Bytewise slice equality
+#[cfg(test, stage0)]
+#[lang="str_eq"]
 #[inline]
 pub fn eq_slice(a: &str, b: &str) -> bool {
     do a.as_imm_buf |ap, alen| {
@@ -535,6 +634,24 @@ pub fn eq_slice(a: &str, b: &str) -> bool {
     }
 }
 
+/// Bytewise slice equality
+#[cfg(test, not(stage0))]
+#[inline]
+pub fn eq_slice(a: &str, b: &str) -> bool {
+    do a.as_imm_buf |ap, alen| {
+        do b.as_imm_buf |bp, blen| {
+            if (alen != blen) { false }
+            else {
+                unsafe {
+                    libc::memcmp(ap as *libc::c_void,
+                                 bp as *libc::c_void,
+                                 alen as libc::size_t) == 0
+                }
+            }
+        }
+    }
+}
+
 /// Bytewise string equality
 #[cfg(not(test))]
 #[lang="uniq_str_eq"]
@@ -800,20 +917,12 @@ pub mod raw {
     use str::is_utf8;
     use vec;
     use vec::MutableVector;
-    use unstable::raw::{Slice, String};
-
-    /// Create a Rust string from a null-terminated *u8 buffer
-    pub unsafe fn from_buf(buf: *u8) -> ~str {
-        let mut curr = buf;
-        let mut i = 0u;
-        while *curr != 0u8 {
-            i += 1u;
-            curr = ptr::offset(buf, i as int);
-        }
-        return from_buf_len(buf, i);
-    }
+    use unstable::raw::Slice;
+    #[cfg(stage0)]
+    use unstable::raw::String;
 
     /// Create a Rust string from a *u8 buffer of the given length
+    #[cfg(stage0)]
     pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
         let mut v: ~[u8] = vec::with_capacity(len + 1);
         v.as_mut_buf(|vbuf, _len| {
@@ -823,17 +932,31 @@ pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
         v.push(0u8);
 
         assert!(is_utf8(v));
-        return cast::transmute(v);
+        cast::transmute(v)
     }
 
-    /// Create a Rust string from a null-terminated C string
-    pub unsafe fn from_c_str(c_str: *libc::c_char) -> ~str {
-        from_buf(c_str as *u8)
+    /// Create a Rust string from a *u8 buffer of the given length
+    #[cfg(not(stage0))]
+    pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
+        let mut v: ~[u8] = vec::with_capacity(len);
+        do v.as_mut_buf |vbuf, _len| {
+            ptr::copy_memory(vbuf, buf as *u8, len)
+        };
+        vec::raw::set_len(&mut v, len);
+
+        assert!(is_utf8(v));
+        ::cast::transmute(v)
     }
 
-    /// Create a Rust string from a `*c_char` buffer of the given length
-    pub unsafe fn from_c_str_len(c_str: *libc::c_char, len: uint) -> ~str {
-        from_buf_len(c_str as *u8, len)
+    /// Create a Rust string from a null-terminated C string
+    pub unsafe fn from_c_str(buf: *libc::c_char) -> ~str {
+        let mut curr = buf;
+        let mut i = 0;
+        while *curr != 0 {
+            i += 1;
+            curr = ptr::offset(buf, i);
+        }
+        from_buf_len(buf as *u8, i as uint)
     }
 
     /// Converts a vector of bytes to a new owned string.
@@ -845,15 +968,17 @@ pub unsafe fn from_bytes(v: &[u8]) -> ~str {
 
     /// Converts an owned vector of bytes to a new owned string. This assumes
     /// that the utf-8-ness of the vector has already been validated
+    #[cfg(stage0)]
     pub unsafe fn from_bytes_owned(mut v: ~[u8]) -> ~str {
         v.push(0u8);
         cast::transmute(v)
     }
 
-    /// Converts a vector of bytes to a string.
-    /// The byte slice needs to contain valid utf8 and needs to be one byte longer than
-    /// the string, if possible ending in a 0 byte.
-    pub unsafe fn from_bytes_with_null<'a>(v: &'a [u8]) -> &'a str {
+    /// Converts an owned vector of bytes to a new owned string. This assumes
+    /// that the utf-8-ness of the vector has already been validated
+    #[cfg(not(stage0))]
+    #[inline]
+    pub unsafe fn from_bytes_owned(v: ~[u8]) -> ~str {
         cast::transmute(v)
     }
 
@@ -863,6 +988,7 @@ pub unsafe fn from_byte(u: u8) -> ~str { from_bytes([u]) }
     /// Form a slice from a C string. Unsafe because the caller must ensure the
     /// C string has the static lifetime, or else the return value may be
     /// invalidated later.
+    #[cfg(stage0)]
     pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
         let s = s as *u8;
         let mut curr = s;
@@ -876,6 +1002,23 @@ pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
         cast::transmute(v)
     }
 
+    /// Form a slice from a C string. Unsafe because the caller must ensure the
+    /// C string has the static lifetime, or else the return value may be
+    /// invalidated later.
+    #[cfg(not(stage0))]
+    pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
+        let s = s as *u8;
+        let mut curr = s;
+        let mut len = 0u;
+        while *curr != 0u8 {
+            len += 1u;
+            curr = ptr::offset(s, len as int);
+        }
+        let v = Slice { data: s, len: len };
+        assert!(is_utf8(::cast::transmute(v)));
+        ::cast::transmute(v)
+    }
+
     /// Takes a bytewise (not UTF-8) slice from a string.
     ///
     /// Returns the substring from [`begin`..`end`).
@@ -884,6 +1027,7 @@ pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
     ///
     /// If begin is greater than end.
     /// If end is greater than the length of the string.
+    #[cfg(stage0)]
     #[inline]
     pub unsafe fn slice_bytes<'a>(s: &'a str, begin: uint, end: uint) -> &'a str {
         do s.as_imm_buf |sbuf, n| {
@@ -897,16 +1041,47 @@ pub unsafe fn slice_bytes<'a>(s: &'a str, begin: uint, end: uint) -> &'a str {
         }
     }
 
+    /// Takes a bytewise (not UTF-8) slice from a string.
+    ///
+    /// Returns the substring from [`begin`..`end`).
+    ///
+    /// # Failure
+    ///
+    /// If begin is greater than end.
+    /// If end is greater than the length of the string.
+    #[cfg(not(stage0))]
+    #[inline]
+    pub unsafe fn slice_bytes<'a>(s: &'a str, begin: uint, end: uint) -> &'a str {
+        do s.as_imm_buf |sbuf, n| {
+             assert!((begin <= end));
+             assert!((end <= n));
+
+             cast::transmute(Slice {
+                 data: ptr::offset(sbuf, begin as int),
+                 len: end - begin,
+             })
+        }
+    }
+
     /// Appends a byte to a string. (Not UTF-8 safe).
+    #[cfg(stage0)]
     pub unsafe fn push_byte(s: &mut ~str, b: u8) {
         let new_len = s.len() + 1;
         s.reserve_at_least(new_len);
         do s.as_mut_buf |buf, len| {
-            *ptr::mut_offset(buf, (len-1) as int) = b;
+            *ptr::mut_offset(buf, len as int) = b;
         }
         set_len(&mut *s, new_len);
     }
 
+    /// Appends a byte to a string. (Not UTF-8 safe).
+    #[cfg(not(stage0))]
+    #[inline]
+    pub unsafe fn push_byte(s: &mut ~str, b: u8) {
+        let v: &mut ~[u8] = cast::transmute(s);
+        v.push(b);
+    }
+
     /// Appends a vector of bytes to a string. (Not UTF-8 safe).
     unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) {
         let new_len = s.len() + bytes.len();
@@ -933,6 +1108,7 @@ pub unsafe fn shift_byte(s: &mut ~str) -> u8 {
     }
 
     /// Sets the length of the string and adds the null terminator
+    #[cfg(stage0)]
     #[inline]
     pub unsafe fn set_len(v: &mut ~str, new_len: uint) {
         let v: **mut String = cast::transmute(v);
@@ -942,6 +1118,23 @@ pub unsafe fn set_len(v: &mut ~str, new_len: uint) {
         *null = 0u8;
     }
 
+    /// Sets the length of a string
+    ///
+    /// This will explicitly set the size of the string, without actually
+    /// modifing its buffers, so it is up to the caller to ensure that
+    /// the string is actually the specified size.
+    #[cfg(not(stage0))]
+    #[inline]
+    pub unsafe fn set_len(s: &mut ~str, new_len: uint) {
+        let v: &mut ~[u8] = cast::transmute(s);
+        vec::raw::set_len(v, new_len)
+    }
+
+    /// Sets the length of a string
+    ///
+    /// This will explicitly set the size of the string, without actually
+    /// modifing its buffers, so it is up to the caller to ensure that
+    /// the string is actually the specified size.
     #[test]
     fn test_from_buf_len() {
         unsafe {
@@ -1050,34 +1243,16 @@ fn equals(&self, other: &@str) -> bool {
     impl<'self> Ord for &'self str {
         #[inline]
         fn lt(&self, other: & &'self str) -> bool { self.cmp(other) == Less }
-        #[inline]
-        fn le(&self, other: & &'self str) -> bool { self.cmp(other) != Greater }
-        #[inline]
-        fn ge(&self, other: & &'self str) -> bool { self.cmp(other) != Less }
-        #[inline]
-        fn gt(&self, other: & &'self str) -> bool { self.cmp(other) == Greater }
     }
 
     impl Ord for ~str {
         #[inline]
         fn lt(&self, other: &~str) -> bool { self.cmp(other) == Less }
-        #[inline]
-        fn le(&self, other: &~str) -> bool { self.cmp(other) != Greater }
-        #[inline]
-        fn ge(&self, other: &~str) -> bool { self.cmp(other) != Less }
-        #[inline]
-        fn gt(&self, other: &~str) -> bool { self.cmp(other) == Greater }
     }
 
     impl Ord for @str {
         #[inline]
         fn lt(&self, other: &@str) -> bool { self.cmp(other) == Less }
-        #[inline]
-        fn le(&self, other: &@str) -> bool { self.cmp(other) != Greater }
-        #[inline]
-        fn ge(&self, other: &@str) -> bool { self.cmp(other) != Less }
-        #[inline]
-        fn gt(&self, other: &@str) -> bool { self.cmp(other) == Greater }
     }
 
     impl<'self, S: Str> Equiv<S> for &'self str {
@@ -1137,10 +1312,17 @@ fn into_owned(self) -> ~str { self.to_owned() }
 }
 
 impl<'self> Container for &'self str {
+    #[cfg(stage0)]
     #[inline]
     fn len(&self) -> uint {
         do self.as_imm_buf |_p, n| { n - 1u }
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn len(&self) -> uint {
+        do self.as_imm_buf |_p, n| { n }
+    }
 }
 
 impl Container for ~str {
@@ -1228,7 +1410,6 @@ fn split_options_iter<Sep: CharEq>(&self, sep: Sep, count: uint, allow_trailing_
     fn subslice_offset(&self, inner: &str) -> uint;
 
     fn as_imm_buf<T>(&self, f: &fn(*u8, uint) -> T) -> T;
-    fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T;
 }
 
 /// Extension methods for strings
@@ -1264,7 +1445,7 @@ fn contains_char(&self, needle: char) -> bool {
     /// ~~~
     #[inline]
     fn iter(&self) -> CharIterator<'self> {
-        self.char_offset_iter().transform(|(_, c)| c)
+        self.char_offset_iter().map(|(_, c)| c)
     }
 
     /// An iterator over the characters of `self`, in reverse order.
@@ -1276,7 +1457,7 @@ fn rev_iter(&self) -> CharRevIterator<'self> {
     /// An iterator over the bytes of `self`
     #[inline]
     fn byte_iter(&self) -> ByteIterator<'self> {
-        self.as_bytes().iter().transform(|&b| b)
+        self.as_bytes().iter().map(|&b| b)
     }
 
     /// An iterator over the bytes of `self`, in reverse order
@@ -1384,7 +1565,7 @@ fn line_iter(&self) -> CharSplitIterator<'self, char> {
     /// An iterator over the lines of a string, separated by either
     /// `\n` or (`\r\n`).
     fn any_line_iter(&self) -> AnyLineIterator<'self> {
-        do self.line_iter().transform |line| {
+        do self.line_iter().map |line| {
             let l = line.len();
             if l > 0 && line[l - 1] == '\r' as u8 { line.slice(0, l - 1) }
             else { line }
@@ -1412,7 +1593,7 @@ fn is_alphanumeric(&self) -> bool { self.iter().all(char::is_alphanumeric) }
 
     /// Returns the number of characters that a string holds
     #[inline]
-    fn char_len(&self) -> uint { self.iter().len_() }
+    fn char_len(&self) -> uint { self.iter().len() }
 
     /// Returns a slice of the given string from the byte range
     /// [`begin`..`end`)
@@ -1615,6 +1796,7 @@ pub fn replace(&self, from: &str, to: &str) -> ~str {
     }
 
     /// Copy a slice into a new unique str
+    #[cfg(stage0)]
     #[inline]
     fn to_owned(&self) -> ~str {
         do self.as_imm_buf |src, len| {
@@ -1632,6 +1814,24 @@ fn to_owned(&self) -> ~str {
         }
     }
 
+    /// Copy a slice into a new unique str
+    #[cfg(not(stage0))]
+    #[inline]
+    fn to_owned(&self) -> ~str {
+        do self.as_imm_buf |src, len| {
+            unsafe {
+                let mut v = vec::with_capacity(len);
+
+                do v.as_mut_buf |dst, _| {
+                    ptr::copy_memory(dst, src, len);
+                }
+                vec::raw::set_len(&mut v, len);
+                ::cast::transmute(v)
+            }
+        }
+    }
+
+    #[cfg(stage0)]
     #[inline]
     fn to_managed(&self) -> @str {
         let v = at_vec::from_fn(self.len() + 1, |i| {
@@ -1640,6 +1840,15 @@ fn to_managed(&self) -> @str {
         unsafe { cast::transmute(v) }
     }
 
+    #[cfg(not(stage0))]
+    #[inline]
+    fn to_managed(&self) -> @str {
+        unsafe {
+            let v: *&[u8] = cast::transmute(self);
+            cast::transmute(at_vec::to_managed(*v))
+        }
+    }
+
     /// Converts to a vector of `u16` encoded as UTF-16.
     fn to_utf16(&self) -> ~[u16] {
         let mut u = ~[];
@@ -1780,6 +1989,7 @@ fn char_at_reverse(&self, i: uint) -> char {
     /// Work with the byte buffer of a string as a byte slice.
     ///
     /// The byte slice does not include the null terminator.
+    #[cfg(stage0)]
     fn as_bytes(&self) -> &'self [u8] {
         unsafe {
             let mut slice = self.repr();
@@ -1788,6 +1998,14 @@ fn as_bytes(&self) -> &'self [u8] {
         }
     }
 
+    /// Work with the byte buffer of a string as a byte slice.
+    ///
+    /// The byte slice does not include the null terminator.
+    #[cfg(not(stage0))]
+    fn as_bytes(&self) -> &'self [u8] {
+        unsafe { cast::transmute(*self) }
+    }
+
     /// Returns the byte index of the first character of `self` that matches `search`
     ///
     /// # Return value
@@ -1854,6 +2072,7 @@ fn find_str(&self, needle: &str) -> Option<uint> {
     }
 
     /// Given a string, make a new string with repeated copies of it.
+    #[cfg(stage0)]
     fn repeat(&self, nn: uint) -> ~str {
         do self.as_imm_buf |buf, len| {
             // ignore the NULL terminator
@@ -1875,6 +2094,27 @@ fn repeat(&self, nn: uint) -> ~str {
         }
     }
 
+    /// Given a string, make a new string with repeated copies of it.
+    #[cfg(not(stage0))]
+    fn repeat(&self, nn: uint) -> ~str {
+        do self.as_imm_buf |buf, len| {
+            let mut ret = with_capacity(nn * len);
+
+            unsafe {
+                do ret.as_mut_buf |rbuf, _len| {
+                    let mut rbuf = rbuf;
+
+                    do nn.times {
+                        ptr::copy_memory(rbuf, buf, len);
+                        rbuf = rbuf.offset(len as int);
+                    }
+                }
+                raw::set_len(&mut ret, nn * len);
+            }
+            ret
+        }
+    }
+
     /// Retrieves the first character from a string slice and returns
     /// it. This does not allocate a new string; instead, it returns a
     /// slice that point one character beyond the character that was
@@ -1977,61 +2217,6 @@ fn as_imm_buf<T>(&self, f: &fn(*u8, uint) -> T) -> T {
         let v: &[u8] = unsafe { cast::transmute(*self) };
         v.as_imm_buf(f)
     }
-
-    /// Work with the byte buffer of a string as a null-terminated C string.
-    ///
-    /// Allows for unsafe manipulation of strings, which is useful for foreign
-    /// interop. This is similar to `str::as_buf`, but guarantees null-termination.
-    /// If the given slice is not already null-terminated, this function will
-    /// allocate a temporary, copy the slice, null terminate it, and pass
-    /// that instead.
-    ///
-    /// # Example
-    ///
-    /// ~~~ {.rust}
-    /// let s = "PATH".as_c_str(|path| libc::getenv(path));
-    /// ~~~
-    #[inline]
-    fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
-        do self.as_imm_buf |buf, len| {
-            // NB: len includes the trailing null.
-            assert!(len > 0);
-            if unsafe { *(ptr::offset(buf, (len - 1) as int)) != 0 } {
-                self.to_owned().as_c_str(|s| f(s))
-            } else {
-                f(buf as *libc::c_char)
-            }
-        }
-    }
-}
-
-#[allow(missing_doc)]
-pub trait NullTerminatedStr {
-    fn as_bytes_with_null<'a>(&'a self) -> &'a [u8];
-}
-
-impl NullTerminatedStr for ~str {
-    /// Work with the byte buffer of a string as a byte slice.
-    ///
-    /// The byte slice does include the null terminator.
-    #[inline]
-    fn as_bytes_with_null<'a>(&'a self) -> &'a [u8] {
-        let ptr: &'a ~[u8] = unsafe { cast::transmute(self) };
-        let slice: &'a [u8] = *ptr;
-        slice
-    }
-}
-
-impl NullTerminatedStr for @str {
-    /// Work with the byte buffer of a string as a byte slice.
-    ///
-    /// The byte slice does include the null terminator.
-    #[inline]
-    fn as_bytes_with_null<'a>(&'a self) -> &'a [u8] {
-        let ptr: &'a @[u8] = unsafe { cast::transmute(self) };
-        let slice: &'a [u8] = *ptr;
-        slice
-    }
 }
 
 #[allow(missing_doc)]
@@ -2046,6 +2231,7 @@ pub trait OwnedStr {
     fn reserve(&mut self, n: uint);
     fn reserve_at_least(&mut self, n: uint);
     fn capacity(&self) -> uint;
+    #[cfg(stage0)]
     fn to_bytes_with_null(self) -> ~[u8];
 
     /// Work with the mutable byte buffer and length of a slice.
@@ -2192,6 +2378,7 @@ fn append(self, rhs: &str) -> ~str {
     ///
     /// * s - A string
     /// * n - The number of bytes to reserve space for
+    #[cfg(stage0)]
     #[inline]
     pub fn reserve(&mut self, n: uint) {
         unsafe {
@@ -2200,6 +2387,29 @@ pub fn reserve(&mut self, n: uint) {
         }
     }
 
+    /// Reserves capacity for exactly `n` bytes in the given string, not including
+    /// the null terminator.
+    ///
+    /// Assuming single-byte characters, the resulting string will be large
+    /// enough to hold a string of length `n`. To account for the null terminator,
+    /// the underlying buffer will have the size `n` + 1.
+    ///
+    /// If the capacity for `s` is already equal to or greater than the requested
+    /// capacity, then no action is taken.
+    ///
+    /// # Arguments
+    ///
+    /// * s - A string
+    /// * n - The number of bytes to reserve space for
+    #[cfg(not(stage0))]
+    #[inline]
+    pub fn reserve(&mut self, n: uint) {
+        unsafe {
+            let v: &mut ~[u8] = cast::transmute(self);
+            (*v).reserve(n);
+        }
+    }
+
     /// Reserves capacity for at least `n` bytes in the given string, not including
     /// the null terminator.
     ///
@@ -2218,13 +2428,38 @@ pub fn reserve(&mut self, n: uint) {
     ///
     /// * s - A string
     /// * n - The number of bytes to reserve space for
+    #[cfg(stage0)]
     #[inline]
     fn reserve_at_least(&mut self, n: uint) {
         self.reserve(uint::next_power_of_two(n + 1u) - 1u)
     }
 
+    /// Reserves capacity for at least `n` bytes in the given string.
+    ///
+    /// Assuming single-byte characters, the resulting string will be large
+    /// enough to hold a string of length `n`. To account for the null terminator,
+    /// the underlying buffer will have the size `n` + 1.
+    ///
+    /// This function will over-allocate in order to amortize the allocation costs
+    /// in scenarios where the caller may need to repeatedly reserve additional
+    /// space.
+    ///
+    /// If the capacity for `s` is already equal to or greater than the requested
+    /// capacity, then no action is taken.
+    ///
+    /// # Arguments
+    ///
+    /// * s - A string
+    /// * n - The number of bytes to reserve space for
+    #[cfg(not(stage0))]
+    #[inline]
+    fn reserve_at_least(&mut self, n: uint) {
+        self.reserve(uint::next_power_of_two(n))
+    }
+
     /// Returns the number of single-byte characters the string can hold without
     /// reallocating
+    #[cfg(stage0)]
     fn capacity(&self) -> uint {
         let buf: &~[u8] = unsafe { cast::transmute(self) };
         let vcap = buf.capacity();
@@ -2232,8 +2467,19 @@ fn capacity(&self) -> uint {
         vcap - 1u
     }
 
+    /// Returns the number of single-byte characters the string can hold without
+    /// reallocating
+    #[cfg(not(stage0))]
+    fn capacity(&self) -> uint {
+        unsafe {
+            let buf: &~[u8] = cast::transmute(self);
+            buf.capacity()
+        }
+    }
+
     /// Convert to a vector of bytes. This does not allocate a new
     /// string, and includes the null terminator.
+    #[cfg(stage0)]
     #[inline]
     fn to_bytes_with_null(self) -> ~[u8] {
         unsafe { cast::transmute(self) }
@@ -2300,7 +2546,6 @@ fn is_zero(&self) -> bool { self.len() == 0 }
 
 #[cfg(test)]
 mod tests {
-    use iterator::IteratorUtil;
     use container::Container;
     use option::Some;
     use libc::c_char;
@@ -2922,71 +3167,11 @@ fn test_from_bytes_fail() {
     }
 
     #[test]
-    fn test_unsafe_from_bytes_with_null() {
-        let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
-        let b = unsafe { raw::from_bytes_with_null(a) };
-        assert_eq!(b, "AAAAAAA");
-    }
-
-    #[test]
-    fn test_from_bytes_with_null() {
-        let ss = "ศไทย中华Việt Nam";
-        let bb = [0xe0_u8, 0xb8_u8, 0xa8_u8,
-                  0xe0_u8, 0xb9_u8, 0x84_u8,
-                  0xe0_u8, 0xb8_u8, 0x97_u8,
-                  0xe0_u8, 0xb8_u8, 0xa2_u8,
-                  0xe4_u8, 0xb8_u8, 0xad_u8,
-                  0xe5_u8, 0x8d_u8, 0x8e_u8,
-                  0x56_u8, 0x69_u8, 0xe1_u8,
-                  0xbb_u8, 0x87_u8, 0x74_u8,
-                  0x20_u8, 0x4e_u8, 0x61_u8,
-                  0x6d_u8, 0x0_u8];
-
-        assert_eq!(ss, from_bytes_with_null(bb));
-    }
-
-    #[test]
-    #[should_fail]
-    #[ignore(cfg(windows))]
-    fn test_from_bytes_with_null_fail() {
-        let bb = [0xff_u8, 0xb8_u8, 0xa8_u8,
-                  0xe0_u8, 0xb9_u8, 0x84_u8,
-                  0xe0_u8, 0xb8_u8, 0x97_u8,
-                  0xe0_u8, 0xb8_u8, 0xa2_u8,
-                  0xe4_u8, 0xb8_u8, 0xad_u8,
-                  0xe5_u8, 0x8d_u8, 0x8e_u8,
-                  0x56_u8, 0x69_u8, 0xe1_u8,
-                  0xbb_u8, 0x87_u8, 0x74_u8,
-                  0x20_u8, 0x4e_u8, 0x61_u8,
-                  0x6d_u8, 0x0_u8];
-
-         let _x = from_bytes_with_null(bb);
-    }
-
-    #[test]
-    #[should_fail]
-    #[ignore(cfg(windows))]
-    fn test_from_bytes_with_null_fail_2() {
-        let bb = [0xff_u8, 0xb8_u8, 0xa8_u8,
-                  0xe0_u8, 0xb9_u8, 0x84_u8,
-                  0xe0_u8, 0xb8_u8, 0x97_u8,
-                  0xe0_u8, 0xb8_u8, 0xa2_u8,
-                  0xe4_u8, 0xb8_u8, 0xad_u8,
-                  0xe5_u8, 0x8d_u8, 0x8e_u8,
-                  0x56_u8, 0x69_u8, 0xe1_u8,
-                  0xbb_u8, 0x87_u8, 0x74_u8,
-                  0x20_u8, 0x4e_u8, 0x61_u8,
-                  0x6d_u8, 0x60_u8];
-
-         let _x = from_bytes_with_null(bb);
-    }
-
-    #[test]
-    fn test_from_buf() {
+    fn test_raw_from_c_str() {
         unsafe {
-            let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
+            let a = ~[65, 65, 65, 65, 65, 65, 65, 0];
             let b = vec::raw::to_ptr(a);
-            let c = raw::from_buf(b);
+            let c = raw::from_c_str(b);
             assert_eq!(c, ~"AAAAAAA");
         }
     }
@@ -3004,30 +3189,31 @@ fn test_as_bytes() {
         assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
     }
 
+    #[cfg(stage0)]
     #[test]
-    fn test_as_bytes_with_null() {
-        // has null
-        let v = [
-            224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
-            184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
-            109, 0
-        ];
-
-        let s1 = @"";
-        let s2 = @"abc";
-        let s3 = @"ศไทย中华Việt Nam";
-        assert_eq!(s1.as_bytes_with_null(), &[0]);
-        assert_eq!(s2.as_bytes_with_null(), &['a' as u8, 'b' as u8, 'c' as u8, 0]);
-        assert_eq!(s3.as_bytes_with_null(), v);
+    #[ignore(cfg(windows))]
+    #[should_fail]
+    fn test_as_bytes_fail() {
+        // Don't double free. (I'm not sure if this exercises the
+        // original problem code path anymore.)
+        let s = ~"";
+        let _bytes = s.as_bytes();
+        fail!();
+    }
 
-        let s1 = ~"";
-        let s2 = ~"abc";
-        let s3 = ~"ศไทย中华Việt Nam";
-        assert_eq!(s1.as_bytes_with_null(), &[0]);
-        assert_eq!(s2.as_bytes_with_null(), &['a' as u8, 'b' as u8, 'c' as u8, 0]);
-        assert_eq!(s3.as_bytes_with_null(), v);
+    #[cfg(stage0)]
+    #[test]
+    #[ignore(cfg(windows))]
+    #[should_fail]
+    fn test_as_bytes_fail() {
+        // Don't double free. (I'm not sure if this exercises the
+        // original problem code path anymore.)
+        let s = ~"";
+        let _bytes = s.as_bytes_with_null();
+        fail!();
     }
 
+    #[cfg(stage0)]
     #[test]
     fn test_to_bytes_with_null() {
         let s = ~"ศไทย中华Việt Nam";
@@ -3049,50 +3235,24 @@ fn test_as_bytes_fail() {
         // Don't double free. (I'm not sure if this exercises the
         // original problem code path anymore.)
         let s = ~"";
-        let _bytes = s.as_bytes_with_null();
+        let _bytes = s.as_bytes();
         fail!();
     }
 
     #[test]
     fn test_as_imm_buf() {
-        do "".as_imm_buf |buf, len| {
-            assert_eq!(len, 1);
-            unsafe {
-                assert_eq!(*ptr::offset(buf, 0), 0);
-            }
+        do "".as_imm_buf |_, len| {
+            assert_eq!(len, 0);
         }
 
         do "hello".as_imm_buf |buf, len| {
-            assert_eq!(len, 6);
+            assert_eq!(len, 5);
             unsafe {
                 assert_eq!(*ptr::offset(buf, 0), 'h' as u8);
                 assert_eq!(*ptr::offset(buf, 1), 'e' as u8);
                 assert_eq!(*ptr::offset(buf, 2), 'l' as u8);
                 assert_eq!(*ptr::offset(buf, 3), 'l' as u8);
                 assert_eq!(*ptr::offset(buf, 4), 'o' as u8);
-                assert_eq!(*ptr::offset(buf, 5), 0);
-            }
-        }
-    }
-
-    #[test]
-    fn test_as_c_str() {
-        let a = ~"";
-        do a.as_c_str |buf| {
-            unsafe {
-                assert_eq!(*ptr::offset(buf, 0), 0);
-            }
-        }
-
-        let a = ~"hello";
-        do a.as_c_str |buf| {
-            unsafe {
-                assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
-                assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
-                assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
-                assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
-                assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
-                assert_eq!(*ptr::offset(buf, 5), 0);
             }
         }
     }
@@ -3526,7 +3686,7 @@ fn t<S: Zero + Str>() {
     #[test]
     fn test_str_container() {
         fn sum_len<S: Container>(v: &[S]) -> uint {
-            v.iter().transform(|x| x.len()).sum()
+            v.iter().map(|x| x.len()).sum()
         }
 
         let s = ~"01234";
index 6ededb02107d497bb77a2d0b91e1b11d70b84978..c6ae535c19a3c4ec6edb5a3d7db38cf74c958fc1 100644 (file)
 use container::Container;
 use cast;
 use ptr;
-use iterator::{Iterator, IteratorUtil};
-use vec::{CopyableVector, ImmutableVector, OwnedVector};
+use iterator::Iterator;
+use vec::{CopyableVector, ImmutableVector};
+#[cfg(stage0)]
+use vec::OwnedVector;
 use to_bytes::IterBytes;
 use option::{Some, None};
 
@@ -96,19 +98,26 @@ fn is_ascii(&self) -> bool {
     }
 }
 
-impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
+impl<'self> AsciiCast<&'self [Ascii]> for &'self str {
     #[inline]
-    fn to_ascii(&self) -> &'self[Ascii] {
+    fn to_ascii(&self) -> &'self [Ascii] {
         assert!(self.is_ascii());
-        unsafe {self.to_ascii_nocheck()}
+        unsafe { self.to_ascii_nocheck() }
     }
 
+    #[cfg(stage0)]
     #[inline]
-    unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] {
+    unsafe fn to_ascii_nocheck(&self) -> &'self [Ascii] {
         let (p,len): (*u8, uint) = cast::transmute(*self);
         cast::transmute((p, len - 1))
     }
 
+    #[cfg(not(stage0))]
+    #[inline]
+    unsafe fn to_ascii_nocheck(&self) -> &'self [Ascii] {
+        cast::transmute(*self)
+    }
+
     #[inline]
     fn is_ascii(&self) -> bool {
         self.byte_iter().all(|b| b.is_ascii())
@@ -181,12 +190,19 @@ fn into_ascii(self) -> ~[Ascii] {
         unsafe {self.into_ascii_nocheck()}
     }
 
+    #[cfg(stage0)]
     #[inline]
     unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
         let mut r: ~[Ascii] = cast::transmute(self);
         r.pop();
         r
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
+        cast::transmute(self)
+    }
 }
 
 /// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
@@ -205,11 +221,19 @@ pub trait AsciiStr {
 }
 
 impl<'self> AsciiStr for &'self [Ascii] {
+    #[cfg(stage0)]
     #[inline]
     fn to_str_ascii(&self) -> ~str {
         let mut cpy = self.to_owned();
         cpy.push(0u8.to_ascii());
-        unsafe {cast::transmute(cpy)}
+        unsafe { cast::transmute(cpy) }
+    }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn to_str_ascii(&self) -> ~str {
+        let cpy = self.to_owned();
+        unsafe { cast::transmute(cpy) }
     }
 
     #[inline]
@@ -229,11 +253,18 @@ fn eq_ignore_case(self, other: &[Ascii]) -> bool {
 }
 
 impl ToStrConsume for ~[Ascii] {
+    #[cfg(stage0)]
     #[inline]
     fn into_str(self) -> ~str {
         let mut cpy = self;
         cpy.push(0u8.to_ascii());
-        unsafe {cast::transmute(cpy)}
+        unsafe { cast::transmute(cpy) }
+    }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn into_str(self) -> ~str {
+        unsafe { cast::transmute(self) }
     }
 }
 
@@ -252,7 +283,7 @@ pub trait ToBytesConsume {
 
 impl ToBytesConsume for ~[Ascii] {
     fn into_bytes(self) -> ~[u8] {
-        unsafe {cast::transmute(self)}
+        unsafe { cast::transmute(self) }
     }
 }
 
index 9d853087123e831618df134020fe20fba4a118b9..03e6412fcb8c739fb8bcc562123a66bfdb1549de 100644 (file)
 
 #[allow(missing_doc)];
 
+use c_str::ToCStr;
 use cast;
 use io;
 use libc;
 use libc::{c_char, size_t};
 use repr;
-use str::StrSlice;
 use str;
 use unstable::intrinsics;
 
-pub mod rustrt {
-    use libc::{c_char, size_t};
-
-    extern {
-        #[rust_stack]
-        pub fn rust_upcall_fail(expr: *c_char, file: *c_char, line: size_t);
-    }
-}
-
 /// Returns the size of a type
 #[inline]
 pub fn size_of<T>() -> uint {
@@ -114,8 +105,8 @@ pub trait FailWithCause {
 
 impl FailWithCause for ~str {
     fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
-        do cause.as_c_str |msg_buf| {
-            do file.as_c_str |file_buf| {
+        do cause.to_c_str().with_ref |msg_buf| {
+            do file.to_c_str().with_ref |file_buf| {
                 begin_unwind_(msg_buf, file_buf, line as libc::size_t)
             }
         }
@@ -124,8 +115,8 @@ fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
 
 impl FailWithCause for &'static str {
     fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
-        do cause.as_c_str |msg_buf| {
-            do file.as_c_str |file_buf| {
+        do cause.to_c_str().with_ref |msg_buf| {
+            do file.to_c_str().with_ref |file_buf| {
                 begin_unwind_(msg_buf, file_buf, line as libc::size_t)
             }
         }
@@ -136,55 +127,44 @@ fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
 pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
     use either::Left;
     use option::{Some, None};
-    use rt::{context, OldTaskContext, TaskContext};
+    use rt::in_green_task_context;
     use rt::task::Task;
     use rt::local::Local;
     use rt::logging::Logger;
     use str::Str;
 
-    let context = context();
-    match context {
-        OldTaskContext => {
-            unsafe {
-                rustrt::rust_upcall_fail(msg, file, line);
-                cast::transmute(())
+    unsafe {
+        // XXX: Bad re-allocations. fail! needs some refactoring
+        let msg = str::raw::from_c_str(msg);
+        let file = str::raw::from_c_str(file);
+
+        // XXX: Logging doesn't work correctly in non-task context because it
+        // invokes the local heap
+        if in_green_task_context() {
+            // XXX: Logging doesn't work here - the check to call the log
+            // function never passes - so calling the log function directly.
+            do Local::borrow::<Task, ()> |task| {
+                let msg = match task.name {
+                    Some(ref name) =>
+                    fmt!("task '%s' failed at '%s', %s:%i",
+                         name.as_slice(), msg, file, line as int),
+                    None =>
+                    fmt!("task <unnamed> failed at '%s', %s:%i",
+                         msg, file, line as int)
+                };
+
+                task.logger.log(Left(msg));
             }
+        } else {
+            rterrln!("failed in non-task context at '%s', %s:%i",
+                     msg, file, line as int);
         }
-        _ => {
-            unsafe {
-                // XXX: Bad re-allocations. fail! needs some refactoring
-                let msg = str::raw::from_c_str(msg);
-                let file = str::raw::from_c_str(file);
-
-                // XXX: Logging doesn't work correctly in non-task context because it
-                // invokes the local heap
-                if context == TaskContext {
-                    // XXX: Logging doesn't work here - the check to call the log
-                    // function never passes - so calling the log function directly.
-                    do Local::borrow::<Task, ()> |task| {
-                        let msg = match task.name {
-                            Some(ref name) =>
-                                fmt!("task '%s' failed at '%s', %s:%i",
-                                     name.as_slice(), msg, file, line as int),
-                            None =>
-                                fmt!("task <unnamed> failed at '%s', %s:%i",
-                                     msg, file, line as int)
-                        };
-
-                        task.logger.log(Left(msg));
-                    }
-                } else {
-                    rterrln!("failed in non-task context at '%s', %s:%i",
-                             msg, file, line as int);
-                }
-
-                let task = Local::unsafe_borrow::<Task>();
-                if (*task).unwinder.unwinding {
-                    rtabort!("unwinding again");
-                }
-                (*task).unwinder.begin_unwind();
-            }
+
+        let task = Local::unsafe_borrow::<Task>();
+        if (*task).unwinder.unwinding {
+            rtabort!("unwinding again");
         }
+        (*task).unwinder.begin_unwind();
     }
 }
 
index 95d3cbaf89b10185de74ca9fda0c27a8f6244c8d..3a11dee3138168fbb4a2c5303823d85746001601 100644 (file)
 use local_data;
 use prelude::*;
 use ptr;
-use task::rt;
 use unstable::raw;
 use util;
 
-use super::rt::rust_task;
 use rt::task::{Task, LocalStorage};
 
 pub enum Handle {
-    OldHandle(*rust_task),
     NewHandle(*mut LocalStorage)
 }
 
 impl Handle {
     pub fn new() -> Handle {
-        use rt::{context, OldTaskContext};
         use rt::local::Local;
         unsafe {
-            match context() {
-                OldTaskContext => {
-                    OldHandle(rt::rust_get_task())
-                }
-                _ => {
-                    let task = Local::unsafe_borrow::<Task>();
-                    NewHandle(&mut (*task).storage)
-                }
-            }
+            let task = Local::unsafe_borrow::<Task>();
+            NewHandle(&mut (*task).storage)
         }
     }
 }
@@ -109,26 +98,6 @@ fn cleanup_task_local_map(map_ptr: *libc::c_void) {
 // Gets the map from the runtime. Lazily initialises if not done so already.
 unsafe fn get_local_map(handle: Handle) -> &mut TaskLocalMap {
 
-    unsafe fn oldsched_map(task: *rust_task) -> &mut TaskLocalMap {
-        extern fn cleanup_extern_cb(map_ptr: *libc::c_void) {
-            cleanup_task_local_map(map_ptr);
-        }
-
-        // Relies on the runtime initialising the pointer to null.
-        // Note: the map is an owned pointer and is "owned" by TLS. It is moved
-        // into the tls slot for this task, and then mutable loans are taken
-        // from this slot to modify the map.
-        let map_ptr = rt::rust_get_task_local_data(task);
-        if (*map_ptr).is_null() {
-            // First time TLS is used, create a new map and set up the necessary
-            // TLS information for its safe destruction
-            let map: TaskLocalMap = ~[];
-            *map_ptr = cast::transmute(map);
-            rt::rust_task_local_data_atexit(task, cleanup_extern_cb);
-        }
-        return cast::transmute(map_ptr);
-    }
-
     unsafe fn newsched_map(local: *mut LocalStorage) -> &mut TaskLocalMap {
         // This is based on the same idea as the oldsched code above.
         match &mut *local {
@@ -152,7 +121,6 @@ unsafe fn newsched_map(local: *mut LocalStorage) -> &mut TaskLocalMap {
     }
 
     match handle {
-        OldHandle(task) => oldsched_map(task),
         NewHandle(local_storage) => newsched_map(local_storage)
     }
 }
index 2e0c9c1d1ad1e01bf3b75f18e48ebee8c6820d1d..09431c05e22515f138b050fd308142ebadc66ed5 100644 (file)
@@ -42,7 +42,7 @@
 use comm::{stream, Chan, GenericChan, GenericPort, Port};
 use result::Result;
 use result;
-use rt::{context, OldTaskContext, TaskContext};
+use rt::in_green_task_context;
 use rt::local::Local;
 use unstable::finally::Finally;
 use util;
@@ -54,7 +54,6 @@
 #[cfg(test)] use task;
 
 mod local_data_priv;
-pub mod rt;
 pub mod spawn;
 
 /**
@@ -527,42 +526,29 @@ pub fn try<T:Send>(f: ~fn() -> T) -> Result<T,()> {
 pub fn with_task_name<U>(blk: &fn(Option<&str>) -> U) -> U {
     use rt::task::Task;
 
-    match context() {
-        TaskContext => do Local::borrow::<Task, U> |task| {
+    if in_green_task_context() {
+        do Local::borrow::<Task, U> |task| {
             match task.name {
                 Some(ref name) => blk(Some(name.as_slice())),
                 None => blk(None)
             }
-        },
-        _ => fail!("no task name exists in %?", context()),
+        }
+    } else {
+        fail!("no task name exists in non-green task context")
     }
 }
 
 pub fn yield() {
     //! Yield control to the task scheduler
 
-    use rt::{context, OldTaskContext};
     use rt::local::Local;
     use rt::sched::Scheduler;
 
-    unsafe {
-        match context() {
-            OldTaskContext => {
-                let task_ = rt::rust_get_task();
-                let killed = rt::rust_task_yield(task_);
-                if killed && !failing() {
-                    fail!("killed");
-                }
-            }
-            _ => {
-                // XXX: What does yield really mean in newsched?
-                // FIXME(#7544): Optimize this, since we know we won't block.
-                let sched = Local::take::<Scheduler>();
-                do sched.deschedule_running_task_and_then |sched, task| {
-                    sched.enqueue_blocked_task(task);
-                }
-            }
-        }
+    // XXX: What does yield really mean in newsched?
+    // FIXME(#7544): Optimize this, since we know we won't block.
+    let sched = Local::take::<Scheduler>();
+    do sched.deschedule_running_task_and_then |sched, task| {
+        sched.enqueue_blocked_task(task);
     }
 }
 
@@ -571,17 +557,8 @@ pub fn failing() -> bool {
 
     use rt::task::Task;
 
-    match context() {
-        OldTaskContext => {
-            unsafe {
-                rt::rust_task_is_unwinding(rt::rust_get_task())
-            }
-        }
-        _ => {
-            do Local::borrow::<Task, bool> |local| {
-                local.unwinder.unwinding
-            }
-        }
+    do Local::borrow::<Task, bool> |local| {
+        local.unwinder.unwinding
     }
 }
 
@@ -604,29 +581,19 @@ pub fn unkillable<U>(f: &fn() -> U) -> U {
     use rt::task::Task;
 
     unsafe {
-        match context() {
-            OldTaskContext => {
-                let t = rt::rust_get_task();
-                do (|| {
-                    rt::rust_task_inhibit_kill(t);
-                    f()
-                }).finally {
-                    rt::rust_task_allow_kill(t);
-                }
-            }
-            TaskContext => {
-                // The inhibits/allows might fail and need to borrow the task.
-                let t = Local::unsafe_borrow::<Task>();
-                do (|| {
-                    (*t).death.inhibit_kill((*t).unwinder.unwinding);
-                    f()
-                }).finally {
-                    (*t).death.allow_kill((*t).unwinder.unwinding);
-                }
+        if in_green_task_context() {
+            // The inhibits/allows might fail and need to borrow the task.
+            let t = Local::unsafe_borrow::<Task>();
+            do (|| {
+                (*t).death.inhibit_kill((*t).unwinder.unwinding);
+                f()
+            }).finally {
+                (*t).death.allow_kill((*t).unwinder.unwinding);
             }
+        } else {
             // FIXME(#3095): This should be an rtabort as soon as the scheduler
             // no longer uses a workqueue implemented with an Exclusive.
-            _ => f()
+            f()
         }
     }
 }
@@ -635,27 +602,17 @@ pub fn unkillable<U>(f: &fn() -> U) -> U {
 pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
     use rt::task::Task;
 
-    match context() {
-        OldTaskContext => {
-            let t = rt::rust_get_task();
-            do (|| {
-                rt::rust_task_allow_kill(t);
-                f()
-            }).finally {
-                rt::rust_task_inhibit_kill(t);
-            }
-        }
-        TaskContext => {
-            let t = Local::unsafe_borrow::<Task>();
-            do (|| {
-                (*t).death.allow_kill((*t).unwinder.unwinding);
-                f()
-            }).finally {
-                (*t).death.inhibit_kill((*t).unwinder.unwinding);
-            }
+    if in_green_task_context() {
+        let t = Local::unsafe_borrow::<Task>();
+        do (|| {
+            (*t).death.allow_kill((*t).unwinder.unwinding);
+            f()
+        }).finally {
+            (*t).death.inhibit_kill((*t).unwinder.unwinding);
         }
+    } else {
         // FIXME(#3095): As in unkillable().
-        _ => f()
+        f()
     }
 }
 
@@ -1033,14 +990,8 @@ fn test_try_fail() {
 
 #[cfg(test)]
 fn get_sched_id() -> int {
-    if context() == OldTaskContext {
-        unsafe {
-            rt::rust_get_sched_id() as int
-        }
-    } else {
-        do Local::borrow::<::rt::sched::Scheduler, int> |sched| {
-            sched.sched_id() as int
-        }
+    do Local::borrow::<::rt::sched::Scheduler, int> |sched| {
+        sched.sched_id() as int
     }
 }
 
diff --git a/src/libstd/task/rt.rs b/src/libstd/task/rt.rs
deleted file mode 100644 (file)
index 13c5123..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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.
-
-/*!
-
-The task interface to the runtime
-
-*/
-
-#[doc(hidden)];
-
-use libc;
-
-#[allow(non_camel_case_types)] // runtime type
-pub type sched_id = int;
-#[allow(non_camel_case_types)] // runtime type
-pub type task_id = int;
-
-// These are both opaque runtime/compiler types that we don't know the
-// structure of and should only deal with via unsafe pointer
-#[allow(non_camel_case_types)] // runtime type
-pub type rust_task = libc::c_void;
-#[allow(non_camel_case_types)] // runtime type
-pub type rust_closure = libc::c_void;
-
-extern {
-    #[rust_stack]
-    pub fn rust_task_yield(task: *rust_task) -> bool;
-
-    pub fn rust_get_sched_id() -> sched_id;
-    pub fn rust_new_sched(num_threads: libc::uintptr_t) -> sched_id;
-
-    pub fn get_task_id() -> task_id;
-    #[rust_stack]
-    pub fn rust_get_task() -> *rust_task;
-
-    pub fn new_task() -> *rust_task;
-    pub fn rust_new_task_in_sched(id: sched_id) -> *rust_task;
-
-    pub fn start_task(task: *rust_task, closure: *rust_closure);
-
-    pub fn rust_task_is_unwinding(task: *rust_task) -> bool;
-    pub fn rust_osmain_sched_id() -> sched_id;
-    #[rust_stack]
-    pub fn rust_task_inhibit_kill(t: *rust_task);
-    #[rust_stack]
-    pub fn rust_task_allow_kill(t: *rust_task);
-    #[rust_stack]
-    pub fn rust_task_inhibit_yield(t: *rust_task);
-    #[rust_stack]
-    pub fn rust_task_allow_yield(t: *rust_task);
-    pub fn rust_task_kill_other(task: *rust_task);
-    pub fn rust_task_kill_all(task: *rust_task);
-
-    #[rust_stack]
-    pub fn rust_get_task_local_data(task: *rust_task) -> *mut *libc::c_void;
-    #[rust_stack]
-    pub fn rust_task_local_data_atexit(task: *rust_task, cleanup_fn: *u8);
-}
index 2d0a2d98e9fc0780f0c090289b6c47512e4539fd..10bac9325ab43db57ac0c50389b9585900138a61 100644 (file)
 use cell::Cell;
 use container::MutableMap;
 use comm::{Chan, GenericChan, oneshot};
-use hashmap::{HashSet, HashSetConsumeIterator};
+use hashmap::{HashSet, HashSetMoveIterator};
 use local_data;
-use task::local_data_priv::{local_get, local_set, OldHandle};
-use task::rt::rust_task;
-use task::rt;
 use task::{Failure, SingleThreaded};
 use task::{Success, TaskOpts, TaskResult};
 use task::unkillable;
 use uint;
 use util;
 use unstable::sync::Exclusive;
-use rt::{OldTaskContext, TaskContext, SchedulerContext, GlobalContext, context};
+use rt::in_green_task_context;
 use rt::local::Local;
 use rt::task::{Task, Sched};
 use rt::kill::KillHandle;
 use rt::sched::Scheduler;
 use rt::uv::uvio::UvEventLoop;
 use rt::thread::Thread;
+use rt::work_queue::WorkQueue;
 
 #[cfg(test)] use task::default_task_opts;
 #[cfg(test)] use comm;
 // Transitionary.
 #[deriving(Eq)]
 enum TaskHandle {
-    OldTask(*rust_task),
     NewTask(KillHandle),
 }
 
 impl Clone for TaskHandle {
     fn clone(&self) -> TaskHandle {
         match *self {
-            OldTask(x) => OldTask(x),
             NewTask(ref x) => NewTask(x.clone()),
         }
     }
@@ -122,7 +118,6 @@ fn clone(&self) -> TaskHandle {
 impl IterBytes for TaskHandle {
     fn iter_bytes(&self, lsb0: bool, f: &fn(buf: &[u8]) -> bool) -> bool {
         match *self {
-            OldTask(ref x) => x.iter_bytes(lsb0, f),
             NewTask(ref x) => x.iter_bytes(lsb0, f),
         }
     }
@@ -146,8 +141,8 @@ fn remove(&mut self, task: &TaskHandle) {
         assert!(was_present);
     }
     #[inline]
-    fn consume(self) -> HashSetConsumeIterator<TaskHandle> {
-        (*self).consume()
+    fn move_iter(self) -> HashSetMoveIterator<TaskHandle> {
+        (*self).move_iter()
     }
 }
 
@@ -465,13 +460,13 @@ fn kill_taskgroup(state: TaskGroupInner, me: &TaskHandle, is_main: bool) {
         if newstate.is_some() {
             let TaskGroupData { members: members, descendants: descendants } =
                 newstate.unwrap();
-            for sibling in members.consume() {
+            for sibling in members.move_iter() {
                 // Skip self - killing ourself won't do much good.
                 if &sibling != me {
                     RuntimeGlue::kill_task(sibling);
                 }
             }
-            for child in descendants.consume() {
+            for child in descendants.move_iter() {
                 assert!(&child != me);
                 RuntimeGlue::kill_task(child);
             }
@@ -497,7 +492,6 @@ fn taskgroup_key() -> local_data::Key<@@mut Taskgroup> {
 impl RuntimeGlue {
     unsafe fn kill_task(task: TaskHandle) {
         match task {
-            OldTask(ptr) => rt::rust_task_kill_other(ptr),
             NewTask(handle) => {
                 let mut handle = handle;
                 do handle.kill().map_move |killed_task| {
@@ -512,7 +506,6 @@ unsafe fn kill_task(task: TaskHandle) {
 
     unsafe fn kill_all_tasks(task: &TaskHandle) {
         match *task {
-            OldTask(ptr) => rt::rust_task_kill_all(ptr),
             // FIXME(#7544): Remove the kill_all feature entirely once the
             // oldsched goes away.
             NewTask(ref _handle) => rtabort!("can't kill_all in newsched"),
@@ -520,12 +513,8 @@ unsafe fn kill_all_tasks(task: &TaskHandle) {
     }
 
     fn with_task_handle_and_failing(blk: &fn(TaskHandle, bool)) {
-        match context() {
-            OldTaskContext => unsafe {
-                let me = rt::rust_get_task();
-                blk(OldTask(me), rt::rust_task_is_unwinding(me))
-            },
-            TaskContext => unsafe {
+        if in_green_task_context() {
+            unsafe {
                 // Can't use safe borrow, because the taskgroup destructor needs to
                 // access the scheduler again to send kill signals to other tasks.
                 let me = Local::unsafe_borrow::<Task>();
@@ -533,36 +522,15 @@ fn with_task_handle_and_failing(blk: &fn(TaskHandle, bool)) {
                 // Will probably have to wait until the old rt is gone.
                 blk(NewTask((*me).death.kill_handle.get_ref().clone()),
                     (*me).unwinder.unwinding)
-            },
-            SchedulerContext | GlobalContext => rtabort!("task dying in bad context"),
+            }
+        } else {
+            rtabort!("task dying in bad context")
         }
     }
 
     fn with_my_taskgroup<U>(blk: &fn(&Taskgroup) -> U) -> U {
-        match context() {
-            OldTaskContext => unsafe {
-                let me = rt::rust_get_task();
-                do local_get(OldHandle(me), taskgroup_key()) |g| {
-                    match g {
-                        None => {
-                            // Main task, doing first spawn ever. Lazily initialise here.
-                            let mut members = TaskSet::new();
-                            members.insert(OldTask(me));
-                            let tasks = Exclusive::new(Some(TaskGroupData {
-                                members: members,
-                                descendants: TaskSet::new(),
-                            }));
-                            // Main task/group has no ancestors, no notifier, etc.
-                            let group = @@mut Taskgroup(tasks, AncestorList(None),
-                                                        true, None);
-                            local_set(OldHandle(me), taskgroup_key(), group);
-                            blk(&**group)
-                        }
-                        Some(&group) => blk(&**group)
-                    }
-                }
-            },
-            TaskContext => unsafe {
+        if in_green_task_context() {
+            unsafe {
                 // Can't use safe borrow, because creating new hashmaps for the
                 // tasksets requires an rng, which needs to borrow the sched.
                 let me = Local::unsafe_borrow::<Task>();
@@ -586,8 +554,9 @@ fn with_my_taskgroup<U>(blk: &fn(&Taskgroup) -> U) -> U {
                     }
                     Some(ref group) => group,
                 })
-            },
-            SchedulerContext | GlobalContext => rtabort!("spawning in bad context"),
+            }
+        } else {
+            rtabort!("spawning in bad context")
         }
     }
 }
@@ -597,7 +566,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
     -> Option<(TaskGroupArc, AncestorList, bool)> {
     // FIXME(#7544): Not safe to lazily initialize in the old runtime. Remove
     // this context check once 'spawn_raw_oldsched' is gone.
-    if context() == OldTaskContext || linked || supervised {
+    if linked || supervised {
         // with_my_taskgroup will lazily initialize the parent's taskgroup if
         // it doesn't yet exist. We don't want to call it in the unlinked case.
         do RuntimeGlue::with_my_taskgroup |spawner_group| {
@@ -664,11 +633,10 @@ fn enlist_many(child: TaskHandle, child_arc: &TaskGroupArc,
 }
 
 pub fn spawn_raw(opts: TaskOpts, f: ~fn()) {
-    match context() {
-        OldTaskContext   => spawn_raw_oldsched(opts, f),
-        TaskContext      => spawn_raw_newsched(opts, f),
-        SchedulerContext => fail!("can't spawn from scheduler context"),
-        GlobalContext    => fail!("can't spawn from global context"),
+    if in_green_task_context() {
+        spawn_raw_newsched(opts, f)
+    } else {
+        fail!("can't spawn from this context")
     }
 }
 
@@ -722,10 +690,16 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
             let sched = Local::unsafe_borrow::<Scheduler>();
             let sched_handle = (*sched).make_handle();
 
+            // Since this is a 1:1 scheduler we create a queue not in
+            // the stealee set. The run_anything flag is set false
+            // which will disable stealing.
+            let work_queue = WorkQueue::new();
+
             // Create a new scheduler to hold the new task
             let new_loop = ~UvEventLoop::new();
             let mut new_sched = ~Scheduler::new_special(new_loop,
-                                                        (*sched).work_queue.clone(),
+                                                        work_queue,
+                                                        (*sched).work_queues.clone(),
                                                         (*sched).sleeper_list.clone(),
                                                         false,
                                                         Some(sched_handle));
@@ -804,85 +778,6 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
 
 }
 
-fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {
-
-    let (child_tg, ancestors, is_main) =
-        gen_child_taskgroup(opts.linked, opts.supervised).expect("old runtime needs TG");
-
-    unsafe {
-        let child_data = Cell::new((child_tg, ancestors, f));
-        // Being killed with the unsafe task/closure pointers would leak them.
-        do unkillable {
-            let (child_tg, ancestors, f) = child_data.take(); // :(
-            // Create child task.
-            let new_task = match opts.sched.mode {
-                DefaultScheduler => rt::new_task(),
-                _ => new_task_in_sched()
-            };
-            assert!(!new_task.is_null());
-            // Getting killed after here would leak the task.
-            let child_wrapper = make_child_wrapper(new_task, child_tg,
-                  ancestors, is_main, opts.notify_chan.take(), f);
-
-            let closure = cast::transmute(&child_wrapper);
-
-            // Getting killed between these two calls would free the child's
-            // closure. (Reordering them wouldn't help - then getting killed
-            // between them would leak.)
-            rt::start_task(new_task, closure);
-            cast::forget(child_wrapper);
-        }
-    }
-
-    // This function returns a closure-wrapper that we pass to the child task.
-    // (1) It sets up the notification channel.
-    // (2) It attempts to enlist in the child's group and all ancestor groups.
-    // (3a) If any of those fails, it leaves all groups, and does nothing.
-    // (3b) Otherwise it builds a task control structure and puts it in TLS,
-    // (4) ...and runs the provided body function.
-    fn make_child_wrapper(child: *rust_task, child_arc: TaskGroupArc,
-                          ancestors: AncestorList, is_main: bool,
-                          notify_chan: Option<Chan<TaskResult>>,
-                          f: ~fn())
-                       -> ~fn() {
-        let child_data = Cell::new((notify_chan, child_arc, ancestors));
-        let result: ~fn() = || {
-            let (notify_chan, child_arc, ancestors) = child_data.take(); // :(
-            let mut ancestors = ancestors;
-            // Child task runs this code.
-
-            // Even if the below code fails to kick the child off, we must
-            // send Something on the notify channel.
-
-            let notifier = notify_chan.map_move(|c| AutoNotify(c));
-
-            if enlist_many(OldTask(child), &child_arc, &mut ancestors) {
-                let group = @@mut Taskgroup(child_arc, ancestors, is_main, notifier);
-                unsafe {
-                    local_set(OldHandle(child), taskgroup_key(), group);
-                }
-
-                // Run the child's body.
-                f();
-
-                // TLS cleanup code will exit the taskgroup.
-            }
-
-            // Run the box annihilator.
-            // FIXME #4428: Crashy.
-            // unsafe { cleanup::annihilate(); }
-        };
-        return result;
-    }
-
-    fn new_task_in_sched() -> *rust_task {
-        unsafe {
-            let sched_id = rt::rust_new_sched(1);
-            rt::rust_new_task_in_sched(sched_id)
-        }
-    }
-}
-
 #[test]
 fn test_spawn_raw_simple() {
     let (po, ch) = stream();
index 5ad7969c8d21facf3de7600b100d390dc1deb470..f871f4ef6d6acad9db87970e8f40e271c15419ca 100644 (file)
@@ -17,7 +17,7 @@
 use cast;
 use io;
 use io::Writer;
-use iterator::IteratorUtil;
+use iterator::Iterator;
 use option::{None, Option, Some};
 use str::StrSlice;
 use vec::ImmutableVector;
index 5ef5526e5162d4833c3aeff09056c9d94fdc80d4..da1fb9abaeeb6aa0b9d158c3073d5bc9e8e758dc 100644 (file)
@@ -11,7 +11,7 @@
 //! An ordered map and set for integer keys implemented as a radix trie
 
 use prelude::*;
-use iterator::{IteratorUtil, FromIterator, Extendable};
+use iterator::{FromIterator, Extendable};
 use uint;
 use util::{swap, replace};
 use vec;
@@ -156,6 +156,53 @@ pub fn iter<'a>(&'a self) -> TrieMapIterator<'a, T> {
             remaining_max: self.length
         }
     }
+
+    // If `upper` is true then returns upper_bound else returns lower_bound.
+    #[inline]
+    fn bound_iter<'a>(&'a self, key: uint, upper: bool) -> TrieMapIterator<'a, T> {
+        let mut node: &'a TrieNode<T> = &self.root;
+        let mut idx = 0;
+        let mut it = TrieMapIterator {
+            stack: ~[],
+            remaining_min: 0,
+            remaining_max: self.length
+        };
+        loop {
+            let children = &node.children;
+            let child_id = chunk(key, idx);
+            match children[child_id] {
+                Internal(ref n) => {
+                    node = &**n;
+                    it.stack.push(children.slice_from(child_id + 1).iter());
+                }
+                External(stored, _) => {
+                    if stored < key || (upper && stored == key) {
+                        it.stack.push(children.slice_from(child_id + 1).iter());
+                    } else {
+                        it.stack.push(children.slice_from(child_id).iter());
+                    }
+                    return it;
+                }
+                Nothing => {
+                    it.stack.push(children.slice_from(child_id + 1).iter());
+                    return it
+                }
+            }
+            idx += 1;
+        }
+    }
+
+    /// Get an iterator pointing to the first key-value pair whose key is not less than `key`.
+    /// If all keys in the map are less than `key` an empty iterator is returned.
+    pub fn lower_bound_iter<'a>(&'a self, key: uint) -> TrieMapIterator<'a, T> {
+        self.bound_iter(key, false)
+    }
+
+    /// Get an iterator pointing to the first key-value pair whose key is greater than `key`.
+    /// If all keys in the map are not greater than `key` an empty iterator is returned.
+    pub fn upper_bound_iter<'a>(&'a self, key: uint) -> TrieMapIterator<'a, T> {
+        self.bound_iter(key, true)
+    }
 }
 
 impl<T, Iter: Iterator<(uint, T)>> FromIterator<(uint, T), Iter> for TrieMap<T> {
@@ -233,6 +280,18 @@ pub fn each_reverse(&self, f: &fn(&uint) -> bool) -> bool {
     pub fn iter<'a>(&'a self) -> TrieSetIterator<'a> {
         TrieSetIterator{iter: self.map.iter()}
     }
+
+    /// Get an iterator pointing to the first value that is not less than `val`.
+    /// If all values in the set are less than `val` an empty iterator is returned.
+    pub fn lower_bound_iter<'a>(&'a self, val: uint) -> TrieSetIterator<'a> {
+        TrieSetIterator{iter: self.map.lower_bound_iter(val)}
+    }
+
+    /// Get an iterator pointing to the first value that key is greater than `val`.
+    /// If all values in the set are not greater than `val` an empty iterator is returned.
+    pub fn upper_bound_iter<'a>(&'a self, val: uint) -> TrieSetIterator<'a> {
+        TrieSetIterator{iter: self.map.upper_bound_iter(val)}
+    }
 }
 
 impl<Iter: Iterator<uint>> FromIterator<uint, Iter> for TrieSet {
@@ -617,7 +676,7 @@ fn test_pop() {
     fn test_from_iter() {
         let xs = ~[(1u, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
 
-        let map: TrieMap<int> = xs.iter().transform(|&x| x).collect();
+        let map: TrieMap<int> = xs.iter().map(|&x| x).collect();
 
         for &(k, v) in xs.iter() {
             assert_eq!(map.find(&k), Some(&v));
@@ -645,6 +704,49 @@ fn test_iteration() {
         }
         assert_eq!(i, last - first);
     }
+
+    #[test]
+    fn test_bound_iter() {
+        let empty_map : TrieMap<uint> = TrieMap::new();
+        assert_eq!(empty_map.lower_bound_iter(0).next(), None);
+        assert_eq!(empty_map.upper_bound_iter(0).next(), None);
+
+        let last = 999u;
+        let step = 3u;
+        let value = 42u;
+
+        let mut map : TrieMap<uint> = TrieMap::new();
+        do uint::range_step(0u, last, step as int) |x| {
+            assert!(x % step == 0);
+            map.insert(x, value);
+            true
+        };
+
+        for i in range(0u, last - step) {
+            let mut lb = map.lower_bound_iter(i);
+            let mut ub = map.upper_bound_iter(i);
+            let next_key = i - i % step + step;
+            let next_pair = (next_key, &value);
+            if (i % step == 0) {
+                assert_eq!(lb.next(), Some((i, &value)));
+            } else {
+                assert_eq!(lb.next(), Some(next_pair));
+            }
+            assert_eq!(ub.next(), Some(next_pair));
+        }
+
+        let mut lb = map.lower_bound_iter(last - step);
+        assert_eq!(lb.next(), Some((last - step, &value)));
+        let mut ub = map.upper_bound_iter(last - step);
+        assert_eq!(ub.next(), None);
+
+        for i in range(last - step + 1, last) {
+            let mut lb = map.lower_bound_iter(i);
+            assert_eq!(lb.next(), None);
+            let mut ub = map.upper_bound_iter(i);
+            assert_eq!(ub.next(), None);
+        }
+    }
 }
 
 #[cfg(test)]
@@ -680,7 +782,7 @@ fn test_sane_chunk() {
     fn test_from_iter() {
         let xs = ~[9u, 8, 7, 6, 5, 4, 3, 2, 1];
 
-        let set: TrieSet = xs.iter().transform(|&x| x).collect();
+        let set: TrieSet = xs.iter().map(|&x| x).collect();
 
         for x in xs.iter() {
             assert!(set.contains(x));
index 41af29022a66c7449f6012390b236a14d8b608b3..80d1626c084fd0e2763fbce9d85069f16a78ae29 100644 (file)
@@ -15,7 +15,7 @@
 use clone::Clone;
 use vec;
 use vec::ImmutableVector;
-use iterator::IteratorUtil;
+use iterator::Iterator;
 
 pub use self::inner::*;
 
@@ -102,7 +102,7 @@ fn zip(&self) -> ~[(A, B)] {
     fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
         match *self {
             (ref a, ref b) => {
-                a.iter().zip(b.iter()).transform(|(aa, bb)| f(aa, bb)).collect()
+                a.iter().zip(b.iter()).map(|(aa, bb)| f(aa, bb)).collect()
             }
         }
     }
@@ -122,7 +122,7 @@ fn zip(&self) -> ~[(A, B)] {
     fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
         match *self {
             (ref a, ref b) => {
-                a.iter().zip(b.iter()).transform(|(aa, bb)| f(aa, bb)).collect()
+                a.iter().zip(b.iter()).map(|(aa, bb)| f(aa, bb)).collect()
             }
         }
     }
index 8d5654255f14a7264f50a9b3294dec4b49ffcc3c..49e3e0777df84e58356fe734fe07d3e37c36f34f 100644 (file)
@@ -15,6 +15,7 @@
 A simple wrapper over the platforms dynamic library facilities
 
 */
+use c_str::ToCStr;
 use cast;
 use path;
 use libc;
@@ -65,7 +66,7 @@ pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, ~str> {
         // T but that feature is still unimplemented
 
         let maybe_symbol_value = do dl::check_for_errors_in {
-            do symbol.as_c_str |raw_string| {
+            do symbol.to_c_str().with_ref |raw_string| {
                 dl::symbol(self.handle, raw_string)
             }
         };
@@ -135,6 +136,7 @@ fn test_errors_do_not_crash() {
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "freebsd")]
 mod dl {
+    use c_str::ToCStr;
     use libc;
     use path;
     use ptr;
@@ -143,7 +145,7 @@ mod dl {
     use result::*;
 
     pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
-        do filename.to_str().as_c_str |raw_name| {
+        do filename.to_c_str().with_ref |raw_name| {
             dlopen(raw_name, Lazy as libc::c_int)
         }
     }
index 7b05515f74acb29bcf1f1a3d14ec66b33ce157d6..7b1f0e8ced8f2cbe8b7522664336f94d14cc6a17 100644 (file)
@@ -526,7 +526,7 @@ pub fn conv_uint(cv: Conv, u: uint, buf: &mut ~str) {
               TyHexLower => uint_to_str_prec(u, 16, prec),
 
               // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
-              // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+              // to_ascii_move and to_str_move to not do a unnecessary copy.
               TyHexUpper => {
                 let s = uint_to_str_prec(u, 16, prec);
                 s.to_ascii().to_upper().to_str_ascii()
@@ -549,12 +549,14 @@ pub fn conv_str(cv: Conv, s: &str, buf: &mut ~str) {
         // For strings, precision is the maximum characters
         // displayed
         let unpadded = match cv.precision {
-          CountImplied => s,
-          CountIs(max) => if (max as uint) < s.char_len() {
-            s.slice(0, max as uint)
-          } else {
-            s
-          }
+            CountImplied => s,
+            CountIs(max) => {
+                if (max as uint) < s.char_len() {
+                    s.slice(0, max as uint)
+                } else {
+                    s
+                }
+            }
         };
         pad(cv, unpadded, None, PadNozero, buf);
     }
index 98c0fe254b697643325efbe9dff7fb6a9f514991..9e7ac1fd7db1337f230b4f9c075abbf32327c4cb 100644 (file)
 
 //! Runtime calls emitted by the compiler.
 
+use c_str::ToCStr;
 use cast::transmute;
-use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
+use libc::{c_char, c_uchar, c_void, size_t, uintptr_t};
 use str;
 use sys;
-use rt::{context, OldTaskContext};
 use rt::task::Task;
 use rt::local::Local;
 use rt::borrowck;
 
-#[allow(non_camel_case_types)]
-pub type rust_task = c_void;
-
-pub mod rustrt {
-    use unstable::lang::rust_task;
-    use libc::{c_char, uintptr_t};
-
-    extern {
-        #[rust_stack]
-        pub fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;
-        #[rust_stack]
-        pub fn rust_upcall_free(ptr: *c_char);
-        #[fast_ffi]
-        pub fn rust_upcall_malloc_noswitch(td: *c_char, size: uintptr_t)
-                                           -> *c_char;
-        #[rust_stack]
-        pub fn rust_try_get_task() -> *rust_task;
-    }
-}
-
 #[lang="fail_"]
 pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
     sys::begin_unwind_(expr, file, line);
@@ -49,25 +29,21 @@ pub fn fail_bounds_check(file: *c_char, line: size_t,
                          index: size_t, len: size_t) {
     let msg = fmt!("index out of bounds: the len is %d but the index is %d",
                     len as int, index as int);
-    do msg.as_c_str |buf| {
+    do msg.to_c_str().with_ref |buf| {
         fail_(buf, file, line);
     }
 }
 
 #[lang="malloc"]
 pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
-    match context() {
-        OldTaskContext => {
-            return rustrt::rust_upcall_malloc_noswitch(td, size);
-        }
-        _ => {
-            let mut alloc = ::ptr::null();
-            do Local::borrow::<Task,()> |task| {
-                alloc = task.heap.alloc(td as *c_void, size as uint) as *c_char;
-            }
-            return alloc;
-        }
+    let mut alloc = ::ptr::null();
+    do Local::borrow::<Task,()> |task| {
+        rtdebug!("task pointer: %x, heap pointer: %x",
+                 ::borrow::to_uint(task),
+                 ::borrow::to_uint(&task.heap));
+        alloc = task.heap.alloc(td as *c_void, size as uint) as *c_char;
     }
+    return alloc;
 }
 
 // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
@@ -132,23 +108,11 @@ pub unsafe fn annihilate() {
 pub fn start(main: *u8, argc: int, argv: **c_char,
              crate_map: *u8) -> int {
     use rt;
-    use os;
 
     unsafe {
-        let use_old_rt = os::getenv("RUST_OLDRT").is_some();
-        if use_old_rt {
-            return rust_start(main as *c_void, argc as c_int, argv,
-                              crate_map as *c_void) as int;
-        } else {
-            return do rt::start(argc, argv as **u8, crate_map) {
-                let main: extern "Rust" fn() = transmute(main);
-                main();
-            };
-        }
-    }
-
-    extern {
-        fn rust_start(main: *c_void, argc: c_int, argv: **c_char,
-                      crate_map: *c_void) -> c_int;
+        return do rt::start(argc, argv as **u8, crate_map) {
+            let main: extern "Rust" fn() = transmute(main);
+            main();
+        };
     }
 }
index 225ac5c92adcf8bfa32fc12aeebe5326ab998056..a9dded41683a9718676ee863d2986197aecc8192 100644 (file)
@@ -280,33 +280,19 @@ fn drop(&self) {
 // FIXME(#8140) should not be pub
 pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
     use rt::task::Task;
-    use task::rt;
     use rt::local::Local;
-    use rt::{context, OldTaskContext, TaskContext};
-
-    match context() {
-        OldTaskContext => {
-            let t = rt::rust_get_task();
-            do (|| {
-                rt::rust_task_inhibit_kill(t);
-                rt::rust_task_inhibit_yield(t);
-                f()
-            }).finally {
-                rt::rust_task_allow_yield(t);
-                rt::rust_task_allow_kill(t);
-            }
-        }
-        TaskContext => {
-            let t = Local::unsafe_borrow::<Task>();
-            do (|| {
-                (*t).death.inhibit_yield();
-                f()
-            }).finally {
-                (*t).death.allow_yield();
-            }
+    use rt::in_green_task_context;
+
+    if in_green_task_context() {
+        let t = Local::unsafe_borrow::<Task>();
+        do (|| {
+            (*t).death.inhibit_yield();
+            f()
+        }).finally {
+            (*t).death.allow_yield();
         }
-        // FIXME(#3095): As in unkillable().
-        _ => f()
+    } else {
+        f()
     }
 }
 
index 0f6d94bb77107786bfff531ad73645ea73d8f380..c831dd709182824e42f1c13b63f5c82851173606 100644 (file)
@@ -382,7 +382,7 @@ pub fn unzip_slice<T:Clone,U:Clone>(v: &[(T, U)]) -> (~[T], ~[U]) {
 pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) {
     let mut ts = ~[];
     let mut us = ~[];
-    for p in v.consume_iter() {
+    for p in v.move_iter() {
         let (t, u) = p;
         ts.push(t);
         us.push(u);
@@ -1068,10 +1068,10 @@ fn bsearch(&self, f: &fn(&T) -> Ordering) -> Option<uint> {
     }
 
     /// Deprecated, use iterators where possible
-    /// (`self.iter().transform(f)`). Apply a function to each element
+    /// (`self.iter().map(f)`). Apply a function to each element
     /// of a vector and return the results.
     fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U] {
-        self.iter().transform(f).collect()
+        self.iter().map(f).collect()
     }
 
     /**
@@ -1174,8 +1174,8 @@ unsafe fn unsafe_get(&self, index: uint) -> T {
 
 #[allow(missing_doc)]
 pub trait OwnedVector<T> {
-    fn consume_iter(self) -> ConsumeIterator<T>;
-    fn consume_rev_iter(self) -> ConsumeRevIterator<T>;
+    fn move_iter(self) -> MoveIterator<T>;
+    fn move_rev_iter(self) -> MoveRevIterator<T>;
 
     fn reserve(&mut self, n: uint);
     fn reserve_at_least(&mut self, n: uint);
@@ -1204,26 +1204,26 @@ impl<T> OwnedVector<T> for ~[T] {
     /// value out of the vector (from start to end). The vector cannot
     /// be used after calling this.
     ///
-    /// Note that this performs O(n) swaps, and so `consume_rev_iter`
+    /// Note that this performs O(n) swaps, and so `move_rev_iter`
     /// (which just calls `pop` repeatedly) is more efficient.
     ///
     /// # Examples
     ///
     /// ~~~ {.rust}
     /// let v = ~[~"a", ~"b"];
-    /// for s in v.consume_iter() {
+    /// for s in v.move_iter() {
     ///   // s has type ~str, not &~str
     ///   println(s);
     /// }
     /// ~~~
-    fn consume_iter(self) -> ConsumeIterator<T> {
-        ConsumeIterator { v: self, idx: 0 }
+    fn move_iter(self) -> MoveIterator<T> {
+        MoveIterator { v: self, idx: 0 }
     }
     /// Creates a consuming iterator that moves out of the vector in
-    /// reverse order. Also see `consume_iter`, however note that this
+    /// reverse order. Also see `move_iter`, however note that this
     /// is more efficient.
-    fn consume_rev_iter(self) -> ConsumeRevIterator<T> {
-        ConsumeRevIterator { v: self }
+    fn move_rev_iter(self) -> MoveRevIterator<T> {
+        MoveRevIterator { v: self }
     }
 
     /**
@@ -1540,7 +1540,7 @@ fn partition(self, f: &fn(&T) -> bool) -> (~[T], ~[T]) {
         let mut lefts  = ~[];
         let mut rights = ~[];
 
-        for elt in self.consume_iter() {
+        for elt in self.move_iter() {
             if f(&elt) {
                 lefts.push(elt);
             } else {
@@ -2148,7 +2148,7 @@ pub fn copy_memory(dst: &mut [u8], src: &[u8], count: uint) {
 impl<A:Clone> Clone for ~[A] {
     #[inline]
     fn clone(&self) -> ~[A] {
-        self.iter().transform(|item| item.clone()).collect()
+        self.iter().map(|item| item.clone()).collect()
     }
 }
 
@@ -2281,12 +2281,12 @@ pub struct VecMutIterator<'self, T> {
 
 /// An iterator that moves out of a vector.
 #[deriving(Clone)]
-pub struct ConsumeIterator<T> {
+pub struct MoveIterator<T> {
     priv v: ~[T],
     priv idx: uint,
 }
 
-impl<T> Iterator<T> for ConsumeIterator<T> {
+impl<T> Iterator<T> for MoveIterator<T> {
     fn next(&mut self) -> Option<T> {
         // this is peculiar, but is required for safety with respect
         // to dtors. It traverses the first half of the vec, and
@@ -2308,11 +2308,11 @@ fn next(&mut self) -> Option<T> {
 
 /// An iterator that moves out of a vector in reverse order.
 #[deriving(Clone)]
-pub struct ConsumeRevIterator<T> {
+pub struct MoveRevIterator<T> {
     priv v: ~[T]
 }
 
-impl<T> Iterator<T> for ConsumeRevIterator<T> {
+impl<T> Iterator<T> for MoveRevIterator<T> {
     fn next(&mut self) -> Option<T> {
         self.v.pop_opt()
     }
@@ -3323,17 +3323,17 @@ fn test_mut_rev_iterator() {
     }
 
     #[test]
-    fn test_consume_iterator() {
+    fn test_move_iterator() {
         use iterator::*;
         let xs = ~[1u,2,3,4,5];
-        assert_eq!(xs.consume_iter().fold(0, |a: uint, b: uint| 10*a + b), 12345);
+        assert_eq!(xs.move_iter().fold(0, |a: uint, b: uint| 10*a + b), 12345);
     }
 
     #[test]
-    fn test_consume_rev_iterator() {
+    fn test_move_rev_iterator() {
         use iterator::*;
         let xs = ~[1u,2,3,4,5];
-        assert_eq!(xs.consume_rev_iter().fold(0, |a: uint, b: uint| 10*a + b), 54321);
+        assert_eq!(xs.move_rev_iter().fold(0, |a: uint, b: uint| 10*a + b), 54321);
     }
 
     #[test]
@@ -3608,7 +3608,7 @@ fn test_iter_zero_sized() {
         }
         assert_eq!(cnt, 8);
 
-        for f in v.consume_iter() {
+        for f in v.move_iter() {
             assert!(f == Foo);
             cnt += 1;
         }
index 435be3c71af6f08d1fc57d644341a354cb86ddb9..17247222c3ff954783b8d5f67d39f2b29d12f5e0 100644 (file)
@@ -951,7 +951,11 @@ pub struct view_item {
 
 #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum view_item_ {
-    view_item_extern_mod(ident, ~[@MetaItem], NodeId),
+    // ident: name used to refer to this crate in the code
+    // optional @str: if present, this is a location (containing
+    // arbitrary characters) from which to fetch the crate sources
+    // For example, extern mod whatever = "github.com/mozilla/rust"
+    view_item_extern_mod(ident, Option<@str>, ~[@MetaItem], NodeId),
     view_item_use(~[@view_path]),
 }
 
index ba167fe67148ef5df984fbdf00e50495fb7f6f39..0005180ef50ff473aa2b6679cc9185ff5b322f3b 100644 (file)
@@ -247,7 +247,7 @@ pub fn unguarded_pat(a: &arm) -> Option<~[@pat]> {
 }
 
 pub fn public_methods(ms: ~[@method]) -> ~[@method] {
-    do ms.consume_iter().filter |m| {
+    do ms.move_iter().filter |m| {
         match m.vis {
             public => true,
             _   => false
@@ -419,7 +419,7 @@ fn visit_mod(@mut self,
 
     fn visit_view_item(@mut self, view_item: &view_item, env: ()) {
         match view_item.node {
-            view_item_extern_mod(_, _, node_id) => {
+            view_item_extern_mod(_, _, _, node_id) => {
                 (self.visit_callback)(node_id)
             }
             view_item_use(ref view_paths) => {
index 9edd41152f7f288ef090b2b94f555fabf4edf0b7..b0dda2b7dc89f0db4f24d7101411569e5900aeb1 100644 (file)
@@ -186,13 +186,13 @@ pub fn contains_name<AM: AttrMetaMethods>(metas: &[AM], name: &str) -> bool {
 pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str)
                                  -> Option<@str> {
     attrs.iter()
-        .find_(|at| name == at.name())
+        .find(|at| name == at.name())
         .chain(|at| at.value_str())
 }
 
 pub fn last_meta_item_value_str_by_name(items: &[@MetaItem], name: &str)
                                      -> Option<@str> {
-    items.rev_iter().find_(|mi| name == mi.name()).chain(|i| i.value_str())
+    items.rev_iter().find(|mi| name == mi.name()).chain(|i| i.value_str())
 }
 
 /* Higher-level applications */
@@ -201,7 +201,7 @@ pub fn sort_meta_items(items: &[@MetaItem]) -> ~[@MetaItem] {
     // This is sort of stupid here, but we need to sort by
     // human-readable strings.
     let mut v = items.iter()
-        .transform(|&mi| (mi.name(), mi))
+        .map(|&mi| (mi.name(), mi))
         .collect::<~[(@str, @MetaItem)]>();
 
     do extra::sort::quick_sort(v) |&(a, _), &(b, _)| {
@@ -209,7 +209,7 @@ pub fn sort_meta_items(items: &[@MetaItem]) -> ~[@MetaItem] {
     }
 
     // There doesn't seem to be a more optimal way to do this
-    do v.consume_iter().transform |(_, m)| {
+    do v.move_iter().map |(_, m)| {
         match m.node {
             MetaList(n, ref mis) => {
                 @spanned {
index ee0ec664e1b9ea22ea13f89f6502c9d1f24eedec..b5d97427baf29737216b2d2d472c9fd296d18bef 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.
 //
@@ -59,7 +59,7 @@ pub fn expand_asm(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
         match state {
             Asm => {
                 asm = expr_to_str(cx, p.parse_expr(),
-                                  ~"inline assembly must be a string literal.");
+                                  "inline assembly must be a string literal.");
             }
             Outputs => {
                 while *p.token != token::EOF &&
index dc20994b49facbb70d3d7ed0dd87d981c99985b4..dfaffa0c2759dd3fc2e52329f1c5b4dfe61a45f3 100644 (file)
@@ -148,7 +148,9 @@ fn builtin_item_tt(f: SyntaxExpanderTTItemFun) -> @Transformer {
         intern(&"auto_decode"),
         @SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
     syntax_expanders.insert(intern(&"env"),
-                            builtin_normal_tt(ext::env::expand_syntax_ext));
+                            builtin_normal_tt(ext::env::expand_env));
+    syntax_expanders.insert(intern(&"option_env"),
+                            builtin_normal_tt(ext::env::expand_option_env));
     syntax_expanders.insert(intern("bytes"),
                             builtin_normal_tt(ext::bytes::expand_syntax_ext));
     syntax_expanders.insert(intern("concat_idents"),
@@ -313,7 +315,7 @@ pub fn ident_of(&self, st: &str) -> ast::ident {
     }
 }
 
-pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: ~str) -> @str {
+pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: &str) -> @str {
     match expr.node {
       ast::expr_lit(l) => match l.node {
         ast::lit_str(s) => s,
@@ -419,12 +421,12 @@ pub enum MapChain<K,V> {
 // get the map from an env frame
 impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
     // Constructor. I don't think we need a zero-arg one.
-    fn new(init: ~HashMap<K,@V>) -> @mut MapChain<K,V> {
+    pub fn new(init: ~HashMap<K,@V>) -> @mut MapChain<K,V> {
         @mut BaseMapChain(init)
     }
 
     // add a new frame to the environment (functionally)
-    fn push_frame (@mut self) -> @mut MapChain<K,V> {
+    pub fn push_frame (@mut self) -> @mut MapChain<K,V> {
         @mut ConsMapChain(~HashMap::new() ,self)
     }
 
@@ -434,7 +436,7 @@ fn push_frame (@mut self) -> @mut MapChain<K,V> {
 
     // ugh: can't get this to compile with mut because of the
     // lack of flow sensitivity.
-    fn get_map<'a>(&'a self) -> &'a HashMap<K,@V> {
+    pub fn get_map<'a>(&'a self) -> &'a HashMap<K,@V> {
         match *self {
             BaseMapChain (~ref map) => map,
             ConsMapChain (~ref map,_) => map
@@ -444,7 +446,7 @@ fn get_map<'a>(&'a self) -> &'a HashMap<K,@V> {
 // traits just don't work anywhere...?
 //impl Map<Name,SyntaxExtension> for MapChain {
 
-    fn contains_key (&self, key: &K) -> bool {
+    pub fn contains_key (&self, key: &K) -> bool {
         match *self {
             BaseMapChain (ref map) => map.contains_key(key),
             ConsMapChain (ref map,ref rest) =>
@@ -455,17 +457,17 @@ fn contains_key (&self, key: &K) -> bool {
     // should each_key and each_value operate on shadowed
     // names? I think not.
     // delaying implementing this....
-    fn each_key (&self, _f: &fn (&K)->bool) {
+    pub fn each_key (&self, _f: &fn (&K)->bool) {
         fail!("unimplemented 2013-02-15T10:01");
     }
 
-    fn each_value (&self, _f: &fn (&V) -> bool) {
+    pub fn each_value (&self, _f: &fn (&V) -> bool) {
         fail!("unimplemented 2013-02-15T10:02");
     }
 
     // Returns a copy of the value that the name maps to.
     // Goes down the chain 'til it finds one (or bottom out).
-    fn find (&self, key: &K) -> Option<@V> {
+    pub fn find (&self, key: &K) -> Option<@V> {
         match self.get_map().find (key) {
             Some(ref v) => Some(**v),
             None => match *self {
@@ -475,7 +477,7 @@ fn find (&self, key: &K) -> Option<@V> {
         }
     }
 
-    fn find_in_topmost_frame(&self, key: &K) -> Option<@V> {
+    pub fn find_in_topmost_frame(&self, key: &K) -> Option<@V> {
         let map = match *self {
             BaseMapChain(ref map) => map,
             ConsMapChain(ref map,_) => map
@@ -485,7 +487,7 @@ fn find_in_topmost_frame(&self, key: &K) -> Option<@V> {
     }
 
     // insert the binding into the top-level map
-    fn insert (&mut self, key: K, ext: @V) -> bool {
+    pub fn insert (&mut self, key: K, ext: @V) -> bool {
         // can't abstract over get_map because of flow sensitivity...
         match *self {
             BaseMapChain (~ref mut map) => map.insert(key, ext),
@@ -497,7 +499,7 @@ fn insert (&mut self, key: K, ext: @V) -> bool {
     // ... there are definitely some opportunities for abstraction
     // here that I'm ignoring. (e.g., manufacturing a predicate on
     // the maps in the chain, and using an abstract "find".
-    fn insert_into_frame(&mut self, key: K, ext: @V, n: K, pred: &fn(&@V)->bool) {
+    pub fn insert_into_frame(&mut self, key: K, ext: @V, n: K, pred: &fn(&@V)->bool) {
         match *self {
             BaseMapChain (~ref mut map) => {
                 if satisfies_pred(map,&n,pred) {
@@ -538,8 +540,8 @@ mod test {
         a.insert (@"abc",@15);
         let m = MapChain::new(~a);
         m.insert (@"def",@16);
-        // FIXME: #4492 (ICE)  assert_eq!(m.find(&@"abc"),Some(@15));
-        //  ....               assert_eq!(m.find(&@"def"),Some(@16));
+        assert_eq!(m.find(&@"abc"),Some(@15));
+        assert_eq!(m.find(&@"def"),Some(@16));
         assert_eq!(*(m.find(&@"abc").unwrap()),15);
         assert_eq!(*(m.find(&@"def").unwrap()),16);
         let n = m.push_frame();
@@ -551,8 +553,8 @@ mod test {
         assert_eq!(*(n.find(&@"abc").unwrap()),15);
         assert_eq!(*(n.find(&@"def").unwrap()),17);
         // ... but m still has the old ones
-        // FIXME: #4492: assert_eq!(m.find(&@"abc"),Some(@15));
-        // FIXME: #4492: assert_eq!(m.find(&@"def"),Some(@16));
+        assert_eq!(m.find(&@"abc"),Some(@15));
+        assert_eq!(m.find(&@"def"),Some(@16));
         assert_eq!(*(m.find(&@"abc").unwrap()),15);
         assert_eq!(*(m.find(&@"def").unwrap()),16);
     }
index d81dca005b0a41dc99bdef621159eea0face4e9a..65032642fda789d4b441697fa4854de1b5e96156 100644 (file)
@@ -702,7 +702,7 @@ fn item_fn(&self,
     }
 
     fn variant(&self, span: span, name: ident, tys: ~[ast::Ty]) -> ast::variant {
-        let args = tys.consume_iter().transform(|ty| {
+        let args = tys.move_iter().map(|ty| {
             ast::variant_arg { ty: ty, id: self.next_id() }
         }).collect();
 
index 069cac0103677f1b9bb3ce0d32763d77cdd18aae..5f9437fd253ef7eedd6a669533c81f32a0ad2bdc 100644 (file)
@@ -39,7 +39,7 @@ pub fn expand_cfg(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacR
     // test_cfg searches for meta items looking like `cfg(foo, ...)`
     let in_cfg = &[cx.meta_list(sp, @"cfg", cfgs)];
 
-    let matches_cfg = attr::test_cfg(cx.cfg(), in_cfg.iter().transform(|&x| x));
+    let matches_cfg = attr::test_cfg(cx.cfg(), in_cfg.iter().map(|&x| x));
     let e = cx.expr_bool(sp, matches_cfg);
     MRExpr(e)
 }
index 59b7da16c2bcbb684c70ca475449a27fdff2bbdf..1abfe246f9da8b769163dff553e223b82ae842c5 100644 (file)
@@ -90,7 +90,7 @@ fn decodable_substructure(cx: @ExtCtxt, span: span,
                     }
                 }
                 Right(ref fields) => {
-                    let fields = do fields.iter().enumerate().transform |(i, f)| {
+                    let fields = do fields.iter().enumerate().map |(i, f)| {
                         cx.field_imm(span, *f, getarg(cx.str_of(*f), i))
                     }.collect();
                     cx.expr_struct_ident(span, substr.type_ident, fields)
@@ -132,7 +132,7 @@ fn decodable_substructure(cx: @ExtCtxt, span: span,
                         }
                     }
                     Right(ref fields) => {
-                        let fields = do fields.iter().enumerate().transform |(i, f)| {
+                        let fields = do fields.iter().enumerate().map |(i, f)| {
                             cx.field_imm(span, *f, getarg(i))
                         }.collect();
                         cx.expr_struct_ident(span, name, fields)
index fb1e6bf1913844c878d9e3a36702fcb686d61807..a1abe47e0909d39b98d2786e4932daa0d1fdfdee 100644 (file)
@@ -590,7 +590,7 @@ fn expand_struct_method_body(&self,
         // transpose raw_fields
         let fields = match raw_fields {
             [ref self_arg, .. rest] => {
-                do self_arg.iter().enumerate().transform |(i, &(opt_id, field))| {
+                do self_arg.iter().enumerate().map |(i, &(opt_id, field))| {
                     let other_fields = do rest.map |l| {
                         match &l[i] {
                             &(_, ex) => ex
@@ -750,7 +750,7 @@ fn build_enum_match(&self,
                     let field_tuples =
                         do self_vec.iter()
                            .zip(enum_matching_fields.iter())
-                           .transform |(&(id, self_f), other)| {
+                           .map |(&(id, self_f), other)| {
                         (id, self_f, (*other).clone())
                     }.collect();
                     substructure = EnumMatching(variant_index, variant, field_tuples);
index 2966a8c114dafa426c37342af6af99bd27dc2127..e55a96f77ff9b57e811000a58265e54a42928bc2 100644 (file)
@@ -95,7 +95,7 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
             let rand_variant = cx.expr_binary(span, ast::rem,
                                               rv_call, variant_count);
 
-            let mut arms = do variants.iter().enumerate().transform |(i, id_sum)| {
+            let mut arms = do variants.iter().enumerate().map |(i, id_sum)| {
                 let i_expr = cx.expr_uint(span, i);
                 let pat = cx.pat_lit(span, i_expr);
 
index a6cb6155878790cc3cd901507bdb0715b6b917f3..c9e01b0f0d596d3ed1a41f645b9538d052641418 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.
 //
 
 use std::os;
 
-pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
+pub fn expand_option_env(ext_cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
     -> base::MacResult {
+    let var = get_single_str_from_tts(ext_cx, sp, tts, "option_env!");
 
-    let var = get_single_str_from_tts(cx, sp, tts, "env!");
+    let e = match os::getenv(var) {
+      None => quote_expr!(::std::option::None),
+      Some(s) => quote_expr!(::std::option::Some($s))
+    };
+    MRExpr(e)
+}
 
-    // FIXME (#2248): if this was more thorough it would manufacture an
-    // Option<str> rather than just an maybe-empty string.
+pub fn expand_env(ext_cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
+    -> base::MacResult {
+    let exprs = get_exprs_from_tts(ext_cx, sp, tts);
+
+    if exprs.len() == 0 {
+        ext_cx.span_fatal(sp, "env! takes 1 or 2 arguments");
+    }
+
+    let var = expr_to_str(ext_cx, exprs[0], "expected string literal");
+    let msg = match exprs.len() {
+        1 => fmt!("Environment variable %s not defined", var).to_managed(),
+        2 => expr_to_str(ext_cx, exprs[1], "expected string literal"),
+        _ => ext_cx.span_fatal(sp, "env! takes 1 or 2 arguments")
+    };
 
     let e = match os::getenv(var) {
-      None => cx.expr_str(sp, @""),
-      Some(s) => cx.expr_str(sp, s.to_managed())
+        None => ext_cx.span_fatal(sp, msg),
+        Some(s) => ext_cx.expr_str(sp, s.to_managed())
     };
     MRExpr(e)
 }
index a928680e093929f041c275f12dc8951e77801261..1963f3aef49c1eec17b48afbc3b42e576363a9f5 100644 (file)
@@ -1075,7 +1075,6 @@ mod test {
     use parse::token::{intern, get_ident_interner};
     use print::pprust;
     use util::parser_testing::{string_to_item, string_to_pat, strs_to_idents};
-    use oldvisit::{mk_vt};
 
     // make sure that fail! is present
     #[test] fn fail_exists_test () {
index 2dbf6887a214e4b156a8f7f0cb44625cf38e1980..10f2055b5fbbae4328b239f346392439dad2353f 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.
 //
@@ -32,7 +32,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
     }
     let fmt =
         expr_to_str(cx, args[0],
-                    ~"first argument to fmt! must be a string literal.");
+                    "first argument to fmt! must be a string literal.");
     let fmtspan = args[0].span;
     debug!("Format string: %s", fmt);
     fn parse_fmt_err_(cx: @ExtCtxt, sp: span, msg: &str) -> ! {
@@ -269,7 +269,7 @@ fn log_conv(c: &Conv) {
        corresponding function in std::unstable::extfmt. Each function takes a
        buffer to insert data into along with the data being formatted. */
     let npieces = pieces.len();
-    for (i, pc) in pieces.consume_iter().enumerate() {
+    for (i, pc) in pieces.move_iter().enumerate() {
         match pc {
             /* Raw strings get appended via str::push_str */
             PieceString(s) => {
index 5cf5fdba632f4ae11e0d6ca12634af43383e286c..a3adb42425ae2bad75c892ecf62b0fe3b1cdcf32 100644 (file)
@@ -353,9 +353,9 @@ fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::expr {
         let trans_method = |method: &parse::Method| {
             let method = match *method {
                 parse::Select(ref arms, ref default) => {
-                    let arms = arms.iter().transform(|arm| {
+                    let arms = arms.iter().map(|arm| {
                         let p = self.ecx.path_global(sp, rtpath("SelectArm"));
-                        let result = arm.result.iter().transform(|p| {
+                        let result = arm.result.iter().map(|p| {
                             self.trans_piece(p)
                         }).collect();
                         let s = arm.selector.to_managed();
@@ -368,7 +368,7 @@ fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::expr {
                                                self.ecx.expr_vec_slice(sp, result)),
                         ])
                     }).collect();
-                    let default = default.iter().transform(|p| {
+                    let default = default.iter().map(|p| {
                         self.trans_piece(p)
                     }).collect();
                     self.ecx.expr_call_global(sp, rtpath("Select"), ~[
@@ -381,9 +381,9 @@ fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::expr {
                         Some(i) => { some(self.ecx.expr_uint(sp, i)) }
                         None => { none() }
                     };
-                    let arms = arms.iter().transform(|arm| {
+                    let arms = arms.iter().map(|arm| {
                         let p = self.ecx.path_global(sp, rtpath("PluralArm"));
-                        let result = arm.result.iter().transform(|p| {
+                        let result = arm.result.iter().map(|p| {
                             self.trans_piece(p)
                         }).collect();
                         let (lr, selarg) = match arm.selector {
@@ -408,7 +408,7 @@ fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::expr {
                                                self.ecx.expr_vec_slice(sp, result)),
                         ])
                     }).collect();
-                    let default = default.iter().transform(|p| {
+                    let default = default.iter().map(|p| {
                         self.trans_piece(p)
                     }).collect();
                     self.ecx.expr_call_global(sp, rtpath("Plural"), ~[
@@ -575,8 +575,8 @@ fn to_expr(&self) -> @ast::expr {
                 Some(self.format_arg(e.span, Right(name), lname));
         }
 
-        let args = names.consume_iter().transform(|a| a.unwrap());
-        let mut args = locals.consume_iter().chain_(args);
+        let args = names.move_iter().map(|a| a.unwrap());
+        let mut args = locals.move_iter().chain(args);
 
         // Next, build up the actual call to the sprintf function.
         let result = self.ecx.expr_call_global(self.fmtsp, ~[
@@ -685,7 +685,7 @@ pub fn expand_syntax_ext(ecx: @ExtCtxt, sp: span,
     };
     cx.fmtsp = efmt.span;
     let fmt = expr_to_str(ecx, efmt,
-                          ~"first argument to ifmt! must be a string literal.");
+                          "first argument to ifmt! must be a string literal.");
 
     let mut err = false;
     do parse::parse_error::cond.trap(|m| {
index 71903b9aa0204790fca3917dc093d553a67d8117..031f0fb4199aeade83ea8fe26cc0bfcd1add0a96 100644 (file)
@@ -105,7 +105,7 @@ pub fn expand_include_bin(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
     let file = get_single_str_from_tts(cx, sp, tts, "include_bin!");
     match io::read_whole_file(&res_rel_file(cx, sp, &Path(file))) {
       result::Ok(src) => {
-        let u8_exprs: ~[@ast::expr] = src.iter().transform(|char| cx.expr_u8(sp, *char)).collect();
+        let u8_exprs: ~[@ast::expr] = src.iter().map(|char| cx.expr_u8(sp, *char)).collect();
         base::MRExpr(cx.expr_vec(sp, u8_exprs))
       }
       result::Err(ref e) => {
index 0a5bc00072034a052bd9a2d865d81aabfbb4f5a5..65694f013f7517ed8bc8fc2e6647b25568917bd2 100644 (file)
@@ -176,7 +176,7 @@ pub fn fold_ty_param(tp: TyParam,
 pub fn fold_ty_params(tps: &OptVec<TyParam>,
                       fld: @ast_fold) -> OptVec<TyParam> {
     let tps = /*bad*/ (*tps).clone();
-    tps.map_consume(|tp| fold_ty_param(tp, fld))
+    tps.map_move(|tp| fold_ty_param(tp, fld))
 }
 
 pub fn fold_lifetime(l: &Lifetime,
@@ -704,7 +704,7 @@ fn fold_opt_bounds(b: &Option<OptVec<TyParamBound>>, fld: @ast_fold)
 // ...nor do modules
 pub fn noop_fold_mod(m: &_mod, fld: @ast_fold) -> _mod {
     ast::_mod {
-        view_items: m.view_items.iter().transform(|x| fld.fold_view_item(x)).collect(),
+        view_items: m.view_items.iter().map(|x| fld.fold_view_item(x)).collect(),
         items: m.items.iter().filter_map(|x| fld.fold_item(*x)).collect(),
     }
 }
@@ -713,8 +713,8 @@ fn noop_fold_foreign_mod(nm: &foreign_mod, fld: @ast_fold) -> foreign_mod {
     ast::foreign_mod {
         sort: nm.sort,
         abis: nm.abis,
-        view_items: nm.view_items.iter().transform(|x| fld.fold_view_item(x)).collect(),
-        items: nm.items.iter().transform(|x| fld.fold_foreign_item(*x)).collect(),
+        view_items: nm.view_items.iter().map(|x| fld.fold_view_item(x)).collect(),
+        items: nm.items.iter().map(|x| fld.fold_foreign_item(*x)).collect(),
     }
 }
 
@@ -734,7 +734,7 @@ fn fold_variant_arg_(va: variant_arg, fld: @ast_fold) -> variant_arg {
         struct_variant_kind(ref struct_def) => {
             kind = struct_variant_kind(@ast::struct_def {
                 fields: struct_def.fields.iter()
-                    .transform(|f| fld.fold_struct_field(*f)).collect(),
+                    .map(|f| fld.fold_struct_field(*f)).collect(),
                 ctor_id: struct_def.ctor_id.map(|c| fld.new_id(*c))
             })
         }
@@ -828,7 +828,7 @@ fn fold_crate(@self, c: &Crate) -> Crate {
     fn fold_view_item(@self, x: &view_item) -> view_item {
         ast::view_item {
             node: (self.fold_view_item)(&x.node, self as @ast_fold),
-            attrs: x.attrs.iter().transform(|a| fold_attribute_(*a, self as @ast_fold)).collect(),
+            attrs: x.attrs.iter().map(|a| fold_attribute_(*a, self as @ast_fold)).collect(),
             vis: x.vis,
             span: (self.new_span)(x.span),
         }
index 10603751a06d119e434372385b86ab8879104802..3a10206b513f8920d7adbc84a2310cb9f91b423c 100644 (file)
@@ -36,7 +36,7 @@ pub fn from<T>(t: ~[T]) -> OptVec<T> {
 }
 
 impl<T> OptVec<T> {
-    fn push(&mut self, t: T) {
+    pub fn push(&mut self, t: T) {
         match *self {
             Vec(ref mut v) => {
                 v.push(t);
@@ -50,32 +50,32 @@ fn push(&mut self, t: T) {
         *self = Vec(~[t]);
     }
 
-    fn map<U>(&self, op: &fn(&T) -> U) -> OptVec<U> {
+    pub fn map<U>(&self, op: &fn(&T) -> U) -> OptVec<U> {
         match *self {
             Empty => Empty,
             Vec(ref v) => Vec(v.map(op))
         }
     }
 
-    fn map_consume<U>(self, op: &fn(T) -> U) -> OptVec<U> {
+    pub fn map_move<U>(self, op: &fn(T) -> U) -> OptVec<U> {
         match self {
             Empty => Empty,
-            Vec(v) => Vec(v.consume_iter().transform(op).collect())
+            Vec(v) => Vec(v.move_iter().map(op).collect())
         }
     }
 
-    fn get<'a>(&'a self, i: uint) -> &'a T {
+    pub fn get<'a>(&'a self, i: uint) -> &'a T {
         match *self {
             Empty => fail!("Invalid index %u", i),
             Vec(ref v) => &v[i]
         }
     }
 
-    fn is_empty(&self) -> bool {
+    pub fn is_empty(&self) -> bool {
         self.len() == 0
     }
 
-    fn len(&self) -> uint {
+    pub fn len(&self) -> uint {
         match *self {
             Empty => 0,
             Vec(ref v) => v.len()
@@ -83,7 +83,7 @@ fn len(&self) -> uint {
     }
 
     #[inline]
-    fn iter<'r>(&'r self) -> OptVecIterator<'r, T> {
+    pub fn iter<'r>(&'r self) -> OptVecIterator<'r, T> {
         match *self {
             Empty => OptVecIterator{iter: None},
             Vec(ref v) => OptVecIterator{iter: Some(v.iter())}
@@ -91,11 +91,11 @@ fn iter<'r>(&'r self) -> OptVecIterator<'r, T> {
     }
 
     #[inline]
-    fn map_to_vec<B>(&self, op: &fn(&T) -> B) -> ~[B] {
-        self.iter().transform(op).collect()
+    pub fn map_to_vec<B>(&self, op: &fn(&T) -> B) -> ~[B] {
+        self.iter().map(op).collect()
     }
 
-    fn mapi_to_vec<B>(&self, op: &fn(uint, &T) -> B) -> ~[B] {
+    pub fn mapi_to_vec<B>(&self, op: &fn(uint, &T) -> B) -> ~[B] {
         let mut index = 0;
         self.map_to_vec(|a| {
             let i = index;
@@ -113,7 +113,7 @@ pub fn take_vec<T>(v: OptVec<T>) -> ~[T] {
 }
 
 impl<T:Clone> OptVec<T> {
-    fn prepend(&self, t: T) -> OptVec<T> {
+    pub fn prepend(&self, t: T) -> OptVec<T> {
         let mut v0 = ~[t];
         match *self {
             Empty => {}
@@ -124,7 +124,7 @@ fn prepend(&self, t: T) -> OptVec<T> {
 }
 
 impl<A:Eq> Eq for OptVec<A> {
-    fn eq(&self, other: &OptVec<A>) -> bool {
+    pub fn eq(&self, other: &OptVec<A>) -> bool {
         // Note: cannot use #[deriving(Eq)] here because
         // (Empty, Vec(~[])) ought to be equal.
         match (self, other) {
@@ -135,7 +135,7 @@ fn eq(&self, other: &OptVec<A>) -> bool {
         }
     }
 
-    fn ne(&self, other: &OptVec<A>) -> bool {
+    pub fn ne(&self, other: &OptVec<A>) -> bool {
         !self.eq(other)
     }
 }
index 41379e6599c6e8b47e3835f9d5c9b4aa5c31379e..5b9725ec6a04239ed225ee18cd9ad80ed3d44d77 100644 (file)
@@ -115,7 +115,7 @@ fn horizontal_trim(lines: ~[~str]) -> ~[~str] {
     if comment.starts_with("/*") {
         let lines = comment.slice(3u, comment.len() - 2u)
             .any_line_iter()
-            .transform(|s| s.to_owned())
+            .map(|s| s.to_owned())
             .collect::<~[~str]>();
 
         let lines = vertical_trim(lines);
index dcab89930dc56cf1c938c46994197f28b0346dfd..77c50a779c03fcd11edb0f82882e804e807f7c66 100644 (file)
@@ -4183,8 +4183,16 @@ fn parse_item_foreign_mod(&self,
                                  self.this_token_to_str()));
         }
 
-        let (sort, ident) = match *self.token {
-            token::IDENT(*) => (ast::named, self.parse_ident()),
+        let (sort, maybe_path, ident) = match *self.token {
+            token::IDENT(*) => {
+                let the_ident = self.parse_ident();
+                let path = if *self.token == token::EQ {
+                    self.bump();
+                    Some(self.parse_str())
+                }
+                else { None };
+                (ast::named, path, the_ident)
+            }
             _ => {
                 if must_be_named_mod {
                     self.span_fatal(*self.span,
@@ -4193,7 +4201,7 @@ fn parse_item_foreign_mod(&self,
                                          self.this_token_to_str()));
                 }
 
-                (ast::anonymous,
+                (ast::anonymous, None,
                  special_idents::clownshoes_foreign_mod)
             }
         };
@@ -4232,7 +4240,7 @@ fn parse_item_foreign_mod(&self,
         let metadata = self.parse_optional_meta();
         self.expect(&token::SEMI);
         iovi_view_item(ast::view_item {
-            node: view_item_extern_mod(ident, metadata, self.get_id()),
+            node: view_item_extern_mod(ident, maybe_path, metadata, self.get_id()),
             attrs: attrs,
             vis: visibility,
             span: mk_sp(lo, self.last_span.hi)
@@ -4304,7 +4312,7 @@ fn parse_enum_def(&self, _generics: &ast::Generics) -> enum_def {
                     seq_sep_trailing_disallowed(token::COMMA),
                     |p| p.parse_ty(false)
                 );
-                for ty in arg_tys.consume_iter() {
+                for ty in arg_tys.move_iter() {
                     args.push(ast::variant_arg {
                         ty: ty,
                         id: self.get_id(),
@@ -4824,8 +4832,13 @@ fn parse_view_item(
         } else if self.eat_keyword(keywords::Extern) {
             self.expect_keyword(keywords::Mod);
             let ident = self.parse_ident();
+            let path = if *self.token == token::EQ {
+                self.bump();
+                Some(self.parse_str())
+            }
+            else { None };
             let metadata = self.parse_optional_meta();
-            view_item_extern_mod(ident, metadata, self.get_id())
+            view_item_extern_mod(ident, path, metadata, self.get_id())
         } else {
             self.bug("expected view item");
         };
index f517179f6036613e100e2ed9290820d934db96b8..ffe9575a8644eaada860dbfd552cdd76e5487a70 100644 (file)
@@ -1856,9 +1856,13 @@ pub fn print_view_item(s: @ps, item: &ast::view_item) {
     print_outer_attributes(s, item.attrs);
     print_visibility(s, item.vis);
     match item.node {
-        ast::view_item_extern_mod(id, ref mta, _) => {
+        ast::view_item_extern_mod(id, ref optional_path, ref mta, _) => {
             head(s, "extern mod");
             print_ident(s, id);
+            for p in optional_path.iter() {
+                word(s.s, "=");
+                print_string(s, *p);
+            }
             if !mta.is_empty() {
                 popen(s);
                 commasep(s, consistent, *mta, |p, &i| print_meta_item(p, i));
index 012333b931ec7005a9c1efabc193be12df750fec..0d3d6c019f89f025a0e5aee8747ec94d40daf272 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#include "memory_region.h"
 #include "boxed_region.h"
 #include "rust_globals.h"
-#include "rust_task.h"
 #include "rust_env.h"
 #include "rust_util.h"
 
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp
deleted file mode 100644 (file)
index 803da32..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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.
-
-/**
- * Main entry point into the Rust runtime. Here we initialize the kernel,
- * create the initial scheduler and run the main task.
- */
-
-#include "rust_globals.h"
-#include "rust_kernel.h"
-#include "rust_util.h"
-#include "rust_scheduler.h"
-#include "rust_gc_metadata.h"
-
-void* global_crate_map = NULL;
-
-/**
-   The runtime entrypoint. The (C ABI) main function generated by rustc calls
-   `rust_start`, providing the address of the Rust ABI main function, the
-   platform argument vector, and a `crate_map` the provides some logging
-   metadata.
-*/
-extern "C" CDECL int
-rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
-
-    // Load runtime configuration options from the environment.
-    // FIXME #1497: Should provide a way to get these from the command
-    // line as well.
-    rust_env *env = load_env(argc, argv);
-
-    global_crate_map = crate_map;
-
-    update_gc_metadata(crate_map);
-
-    update_log_settings(crate_map, env->logspec);
-
-    rust_kernel *kernel = new rust_kernel(env);
-
-    // Create the main task
-    rust_sched_id sched_id = kernel->main_sched_id();
-    rust_scheduler *sched = kernel->get_scheduler_by_id(sched_id);
-    assert(sched != NULL);
-    rust_task *root_task = sched->create_task(NULL, "main");
-
-    // Schedule the main Rust task
-    root_task->start((spawn_fn)main_fn, NULL, NULL);
-
-    // At this point the task lifecycle is responsible for it
-    // and our pointer may not be valid
-    root_task = NULL;
-
-    // Run the kernel until all schedulers exit
-    int ret = kernel->run();
-
-    delete kernel;
-    free_env(env);
-
-    return ret;
-}
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
index d77a9f58a38531f795d470a5523cb655c41350ed..ddd452deef2cb59bad8834c259772af61c3789ea 100644 (file)
 
 /* Foreign builtins. */
 
-#include "rust_sched_loop.h"
-#include "rust_task.h"
 #include "rust_util.h"
-#include "rust_scheduler.h"
 #include "sync/timer.h"
 #include "sync/rust_thread.h"
+#include "sync/lock_and_signal.h"
+#include "memory_region.h"
+#include "boxed_region.h"
 #include "rust_abi.h"
+#include "rust_rng.h"
 #include "vg/valgrind.h"
+#include "sp.h"
 
 #include <time.h>
 
@@ -68,12 +70,6 @@ rust_env_pairs() {
 }
 #endif
 
-extern "C" CDECL void *
-rust_local_realloc(rust_opaque_box *ptr, size_t size) {
-    rust_task *task = rust_get_current_task();
-    return task->boxed.realloc(ptr, size);
-}
-
 extern "C" CDECL size_t
 rand_seed_size() {
     return rng_seed_size();
@@ -150,12 +146,6 @@ debug_static_mut_check_four() {
     assert(debug_static_mut == 4);
 }
 
-extern "C" CDECL void *
-debug_get_stk_seg() {
-    rust_task *task = rust_get_current_task();
-    return task->stk;
-}
-
 extern "C" CDECL char*
 #if defined(__WIN32__)
 rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
@@ -302,10 +292,9 @@ void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
 
     if (zone != NULL) {
         size_t size = strlen(zone);
-        reserve_vec_exact(&out_tm->tm_zone, size + 1);
+        reserve_vec_exact(&out_tm->tm_zone, size);
         memcpy(out_tm->tm_zone->data, zone, size);
-        out_tm->tm_zone->fill = size + 1;
-        out_tm->tm_zone->data[size] = '\0';
+        out_tm->tm_zone->fill = size;
     }
 }
 
@@ -383,162 +372,25 @@ rust_mktime(rust_tm* timeptr) {
     return mktime(&t);
 }
 
-extern "C" CDECL rust_sched_id
-rust_get_sched_id() {
-    rust_task *task = rust_get_current_task();
-    return task->sched->get_id();
-}
-
-extern "C" CDECL int
-rust_get_argc() {
-    rust_task *task = rust_get_current_task();
-    return task->kernel->env->argc;
-}
-
-extern "C" CDECL char**
-rust_get_argv() {
-    rust_task *task = rust_get_current_task();
-    return task->kernel->env->argv;
-}
-
-extern "C" CDECL rust_sched_id
-rust_new_sched(uintptr_t threads) {
-    rust_task *task = rust_get_current_task();
-    assert(threads > 0 && "Can't create a scheduler with no threads, silly!");
-    return task->kernel->create_scheduler(threads);
-}
-
-extern "C" CDECL rust_task_id
-get_task_id() {
-    rust_task *task = rust_get_current_task();
-    return task->id;
-}
-
-static rust_task*
-new_task_common(rust_scheduler *sched, rust_task *parent) {
-    return sched->create_task(parent, NULL);
-}
-
-extern "C" CDECL rust_task*
-new_task() {
-    rust_task *task = rust_get_current_task();
-    rust_sched_id sched_id = task->kernel->main_sched_id();
-    rust_scheduler *sched = task->kernel->get_scheduler_by_id(sched_id);
-    assert(sched != NULL && "should always have a main scheduler");
-    return new_task_common(sched, task);
-}
-
-extern "C" CDECL rust_task*
-rust_new_task_in_sched(rust_sched_id id) {
-    rust_task *task = rust_get_current_task();
-    rust_scheduler *sched = task->kernel->get_scheduler_by_id(id);
-    if (sched == NULL)
-        return NULL;
-    return new_task_common(sched, task);
-}
-
-extern "C" rust_task *
-rust_get_task() {
-    return rust_get_current_task();
-}
-
-extern "C" rust_task *
-rust_try_get_task() {
-    return rust_try_get_current_task();
-}
-
-extern "C" CDECL stk_seg *
-rust_get_stack_segment() {
-    return rust_get_current_task()->stk;
-}
-
-extern "C" CDECL stk_seg *
-rust_get_c_stack() {
-    return rust_get_current_task()->get_c_stack();
-}
-
-extern "C" CDECL void
-start_task(rust_task *target, fn_env_pair *f) {
-    target->start(f->f, f->env, NULL);
-}
-
-// This is called by an intrinsic on the Rust stack and must run
-// entirely in the red zone. Do not call on the C stack.
-extern "C" CDECL MUST_CHECK bool
-rust_task_yield(rust_task *task, bool *killed) {
-    return task->yield();
-}
-
-extern "C" CDECL void
-rust_set_exit_status(intptr_t code) {
-    rust_task *task = rust_get_current_task();
-    task->kernel->set_exit_status((int)code);
-}
-
-extern void log_console_on();
+static lock_and_signal log_lock;
+static bool log_to_console = true;
 
 extern "C" CDECL void
 rust_log_console_on() {
-    log_console_on();
+    scoped_lock with(log_lock);
+    log_to_console = true;
 }
 
-extern void log_console_off();
-
 extern "C" CDECL void
 rust_log_console_off() {
-    log_console_off();
+    scoped_lock with(log_lock);
+    log_to_console = false;
 }
 
-extern bool should_log_console();
-
 extern "C" CDECL uintptr_t
 rust_should_log_console() {
-    return (uintptr_t)should_log_console();
-}
-
-extern "C" CDECL rust_sched_id
-rust_osmain_sched_id() {
-    rust_task *task = rust_get_current_task();
-    return task->kernel->osmain_sched_id();
-}
-
-extern "C" void
-rust_task_inhibit_kill(rust_task *task) {
-    task->inhibit_kill();
-}
-
-extern "C" void
-rust_task_allow_kill(rust_task *task) {
-    task->allow_kill();
-}
-
-extern "C" void
-rust_task_inhibit_yield(rust_task *task) {
-    task->inhibit_yield();
-}
-
-extern "C" void
-rust_task_allow_yield(rust_task *task) {
-    task->allow_yield();
-}
-
-extern "C" void
-rust_task_kill_other(rust_task *task) { /* Used for linked failure */
-    task->kill();
-}
-
-extern "C" void
-rust_task_kill_all(rust_task *task) { /* Used for linked failure */
-    task->fail_sched_loop();
-    // This must not happen twice.
-    static bool main_taskgroup_failed = false;
-    assert(!main_taskgroup_failed);
-    main_taskgroup_failed = true;
-}
-
-extern "C" CDECL
-bool rust_task_is_unwinding(rust_task *rt) {
-    return rt->unwinding;
+    scoped_lock with(log_lock);
+    return log_to_console;
 }
 
 extern "C" lock_and_signal*
@@ -561,71 +413,6 @@ rust_unlock_little_lock(lock_and_signal *lock) {
     lock->unlock();
 }
 
-// get/atexit task_local_data can run on the rust stack for speed.
-extern "C" void **
-rust_get_task_local_data(rust_task *task) {
-    return &task->task_local_data;
-}
-extern "C" void
-rust_task_local_data_atexit(rust_task *task, void (*cleanup_fn)(void *data)) {
-    task->task_local_data_cleanup = cleanup_fn;
-}
-
-// set/get/atexit task_borrow_list can run on the rust stack for speed.
-extern "C" void *
-rust_take_task_borrow_list(rust_task *task) {
-    void *r = task->borrow_list;
-    task->borrow_list = NULL;
-    return r;
-}
-extern "C" void
-rust_set_task_borrow_list(rust_task *task, void *data) {
-    assert(task->borrow_list == NULL);
-    assert(data != NULL);
-    task->borrow_list = data;
-}
-
-extern "C" void
-task_clear_event_reject(rust_task *task) {
-    task->clear_event_reject();
-}
-
-// Waits on an event, returning the pointer to the event that unblocked this
-// task.
-extern "C" MUST_CHECK bool
-task_wait_event(rust_task *task, void **result) {
-    // Maybe (if not too slow) assert that the passed in task is the currently
-    // running task. We wouldn't want to wait some other task.
-
-    return task->wait_event(result);
-}
-
-extern "C" void
-task_signal_event(rust_task *target, void *event) {
-    target->signal_event(event);
-}
-
-// Can safely run on the rust stack.
-extern "C" void
-rust_task_ref(rust_task *task) {
-    task->ref();
-}
-
-// Don't run on the rust stack!
-extern "C" void
-rust_task_deref(rust_task *task) {
-    task->deref();
-}
-
-// Don't run on the Rust stack!
-extern "C" void
-rust_log_str(uint32_t level, const char *str, size_t size) {
-    rust_task *task = rust_get_current_task();
-    task->sched_loop->get_log().log(task, level, "%.*s", (int)size, str);
-}
-
-extern "C" CDECL void      record_sp_limit(void *limit);
-
 class raw_thread: public rust_thread {
 public:
     fn_env_pair fn;
@@ -684,12 +471,6 @@ rust_readdir() {
 
 #endif
 
-extern "C" rust_env*
-rust_get_rt_env() {
-    rust_task *task = rust_get_current_task();
-    return task->kernel->env;
-}
-
 #ifndef _WIN32
 pthread_key_t rt_key = -1;
 #else
@@ -737,12 +518,6 @@ rust_delete_memory_region(memory_region *region) {
     delete region;
 }
 
-extern "C" CDECL boxed_region*
-rust_current_boxed_region() {
-    rust_task *task = rust_get_current_task();
-    return &task->boxed;
-}
-
 extern "C" CDECL boxed_region*
 rust_new_boxed_region(memory_region *region,
                       uintptr_t poison_on_free) {
@@ -848,6 +623,12 @@ rust_drop_change_dir_lock() {
     change_dir_lock.unlock();
 }
 
+// Used by i386 __morestack
+extern "C" CDECL uintptr_t
+rust_get_task() {
+    return 0;
+}
+
 //
 // Local Variables:
 // mode: C++
index 64d17ebc3ad266be757929590ee0929ebc78f57d..80b969d6f6d7d7ebf6a728a00b2609afc71a59ab 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef RUST_CRATE_MAP_H
 #define RUST_CRATE_MAP_H
 
-#include "rust_log.h"
+#include "rust_globals.h"
 #include <stdint.h>
 
 struct mod_entry {
diff --git a/src/rt/rust_debug.cpp b/src/rt/rust_debug.cpp
deleted file mode 100644 (file)
index f403b04..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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.
-
-// Routines useful when debugging the Rust runtime.
-
-#include "rust_globals.h"
-#include "rust_abi.h"
-#include "rust_debug.h"
-#include "rust_task.h"
-
-#include <iostream>
-#include <string>
-#include <sstream>
-
-namespace {
-
-debug::flag track_origins("RUST_TRACK_ORIGINS");
-
-}   // end anonymous namespace
-
-namespace debug {
-
-void
-maybe_track_origin(rust_task *task, void *ptr) {
-    if (!*track_origins)
-        return;
-    task->debug.origins[ptr] =
-        stack_walk::symbolicate(stack_walk::backtrace());
-}
-
-void
-maybe_untrack_origin(rust_task *task, void *ptr) {
-    if (!*track_origins)
-        return;
-    task->debug.origins.erase(ptr);
-}
-
-// This function is intended to be called by the debugger.
-void
-dump_origin(rust_task *task, void *ptr) {
-    if (!*track_origins) {
-        std::cerr << "Try again with RUST_TRACK_ORIGINS=1." << std::endl;
-    } else if (task->debug.origins.find(ptr) == task->debug.origins.end()) {
-        std::cerr << "Pointer " << std::hex << (uintptr_t)ptr <<
-                     " does not have a tracked origin." << std::endl;
-    } else {
-        std::cerr << "Origin of pointer " << std::hex << (uintptr_t)ptr <<
-                     ":" << std::endl << task->debug.origins[ptr] <<
-                     std::endl;
-    }
-}
-
-}   // end namespace debug
diff --git a/src/rt/rust_debug.h b/src/rt/rust_debug.h
deleted file mode 100644 (file)
index 951d2c3..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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.
-
-// Routines useful when debugging the Rust runtime.
-
-#ifndef RUST_DEBUG_H
-#define RUST_DEBUG_H
-
-#include <map>
-#include <string>
-#include <cstdlib>
-
-struct rust_task;
-
-namespace debug {
-
-class flag {
-private:
-    const char *name;
-    bool valid;
-    bool value;
-
-public:
-    flag(const char *in_name) : name(in_name), valid(false) {}
-
-    bool operator*() {
-        // FIXME (#2689): We ought to lock this.
-        if (!valid) {
-            char *ev = getenv(name);
-            value = ev && ev[0] != '\0' && ev[0] != '0';
-            valid = true;
-        }
-        return value;
-    }
-};
-
-class task_debug_info {
-public:
-    std::map<void *,std::string> origins;
-};
-
-std::string backtrace();
-
-void maybe_track_origin(rust_task *task, void *ptr);
-void maybe_untrack_origin(rust_task *task, void *ptr);
-
-// This function is intended to be called by the debugger.
-void dump_origin(rust_task *task, void *ptr);
-
-}   // end namespace debug
-
-#endif
diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp
deleted file mode 100644 (file)
index 814cfbb..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-// 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.
-
-
-
-#include "rust_kernel.h"
-#include "rust_util.h"
-#include "rust_scheduler.h"
-#include "rust_sched_launcher.h"
-#include <algorithm>
-
-#define KLOG_(...)                              \
-    KLOG(this, kern, __VA_ARGS__)
-#define KLOG_ERR_(field, ...)                   \
-    KLOG_LVL(this, field, log_err, __VA_ARGS__)
-
-rust_kernel::rust_kernel(rust_env *env) :
-    _log(NULL),
-    max_task_id(INIT_TASK_ID-1), // sync_add_and_fetch increments first
-    rval(0),
-    max_sched_id(1),
-    killed(false),
-    already_exiting(false),
-    sched_reaper(this),
-    osmain_driver(NULL),
-    non_weak_tasks(0),
-    env(env)
-{
-    // Create the single threaded scheduler that will run on the platform's
-    // main thread
-    rust_manual_sched_launcher_factory *osmain_launchfac =
-        new rust_manual_sched_launcher_factory();
-    osmain_scheduler = create_scheduler(osmain_launchfac, 1, false);
-    osmain_driver = osmain_launchfac->get_driver();
-
-    // Create the primary scheduler
-    rust_thread_sched_launcher_factory *main_launchfac =
-        new rust_thread_sched_launcher_factory();
-    main_scheduler = create_scheduler(main_launchfac,
-                                      env->num_sched_threads,
-                                      false);
-
-    sched_reaper.start();
-}
-
-void
-rust_kernel::log(uint32_t level, char const *fmt, ...) {
-    char buf[BUF_BYTES];
-    va_list args;
-    va_start(args, fmt);
-    vsnprintf(buf, sizeof(buf), fmt, args);
-    _log.trace_ln(NULL, level, buf);
-    va_end(args);
-}
-
-void
-rust_kernel::fatal(char const *fmt, ...) {
-    char buf[BUF_BYTES];
-    va_list args;
-    va_start(args, fmt);
-    vsnprintf(buf, sizeof(buf), fmt, args);
-    _log.trace_ln(NULL, (uint32_t)0, buf);
-    exit(1);
-    va_end(args);
-}
-
-void *
-rust_kernel::malloc(size_t size, const char *tag) {
-    return exchange_alloc.malloc(size);
-}
-
-void *
-rust_kernel::realloc(void *mem, size_t size) {
-    return exchange_alloc.realloc(mem, size);
-}
-
-void rust_kernel::free(void *mem) {
-    exchange_alloc.free(mem);
-}
-
-rust_sched_id
-rust_kernel::create_scheduler(size_t num_threads) {
-    rust_thread_sched_launcher_factory *launchfac =
-        new rust_thread_sched_launcher_factory();
-    return create_scheduler(launchfac, num_threads, true);
-}
-
-rust_sched_id
-rust_kernel::create_scheduler(rust_sched_launcher_factory *launchfac,
-                              size_t num_threads, bool allow_exit) {
-    rust_sched_id id;
-    rust_scheduler *sched;
-    {
-        scoped_lock with(sched_lock);
-
-        /*if (sched_table.size() == 2) {
-            // The main and OS main schedulers may not exit while there are
-            // other schedulers
-            KLOG_("Disallowing main scheduler to exit");
-            rust_scheduler *main_sched =
-                get_scheduler_by_id_nolock(main_scheduler);
-            assert(main_sched != NULL);
-            main_sched->disallow_exit();
-        }
-        if (sched_table.size() == 1) {
-            KLOG_("Disallowing osmain scheduler to exit");
-            rust_scheduler *osmain_sched =
-                get_scheduler_by_id_nolock(osmain_scheduler);
-            assert(osmain_sched != NULL);
-            osmain_sched->disallow_exit();
-            }*/
-
-        id = max_sched_id++;
-        assert(id != INTPTR_MAX && "Hit the maximum scheduler id");
-        sched = new (this, "rust_scheduler")
-            rust_scheduler(this, num_threads, id, allow_exit, killed,
-                           launchfac);
-        bool is_new = sched_table
-            .insert(std::pair<rust_sched_id,
-                              rust_scheduler*>(id, sched)).second;
-        assert(is_new && "Reusing a sched id?");
-    }
-    sched->start_task_threads();
-    return id;
-}
-
-rust_scheduler *
-rust_kernel::get_scheduler_by_id(rust_sched_id id) {
-    scoped_lock with(sched_lock);
-    return get_scheduler_by_id_nolock(id);
-}
-
-rust_scheduler *
-rust_kernel::get_scheduler_by_id_nolock(rust_sched_id id) {
-    if (id == 0) {
-        return NULL;
-    }
-    sched_lock.must_have_lock();
-    sched_map::iterator iter = sched_table.find(id);
-    if (iter != sched_table.end()) {
-        return iter->second;
-    } else {
-        return NULL;
-    }
-}
-
-void
-rust_kernel::release_scheduler_id(rust_sched_id id) {
-    scoped_lock with(sched_lock);
-    join_list.push_back(id);
-    sched_lock.signal();
-}
-
-/*
-Called by rust_sched_reaper to join every terminating scheduler thread,
-so that we can be sure they have completely exited before the process exits.
-If we don't join them then we can see valgrind errors due to un-freed pthread
-memory.
- */
-void
-rust_kernel::wait_for_schedulers()
-{
-    scoped_lock with(sched_lock);
-    while (!sched_table.empty()) {
-        while (!join_list.empty()) {
-            rust_sched_id id = join_list.back();
-            KLOG_("Deleting scheduler %d", id);
-            join_list.pop_back();
-            sched_map::iterator iter = sched_table.find(id);
-            assert(iter != sched_table.end());
-            rust_scheduler *sched = iter->second;
-            sched_table.erase(iter);
-            sched->join_task_threads();
-            sched->deref();
-            /*if (sched_table.size() == 2) {
-                KLOG_("Allowing main scheduler to exit");
-                // It's only the main schedulers left. Tell them to exit
-                rust_scheduler *main_sched =
-                    get_scheduler_by_id_nolock(main_scheduler);
-                assert(main_sched != NULL);
-                main_sched->allow_exit();
-            }
-            if (sched_table.size() == 1) {
-                KLOG_("Allowing osmain scheduler to exit");
-                rust_scheduler *osmain_sched =
-                    get_scheduler_by_id_nolock(osmain_scheduler);
-                assert(osmain_sched != NULL);
-                osmain_sched->allow_exit();
-            }*/
-        }
-        if (!sched_table.empty()) {
-            sched_lock.wait();
-        }
-    }
-}
-
-/* Called on the main thread to run the osmain scheduler to completion,
-   then wait for schedulers to exit */
-int
-rust_kernel::run() {
-    assert(osmain_driver != NULL);
-    osmain_driver->start_main_loop();
-    sched_reaper.join();
-    return rval;
-}
-
-void
-rust_kernel::fail() {
-    // FIXME (#908): On windows we're getting "Application has
-    // requested the Runtime to terminate it in an unusual way" when
-    // trying to shutdown cleanly.
-    set_exit_status(PROC_FAIL_CODE);
-#if defined(__WIN32__)
-    exit(rval);
-#endif
-    // I think this only needs to be done by one task ever; as it is,
-    // multiple tasks invoking kill_all might get here. Currently libcore
-    // ensures only one task will ever invoke it, but this would really be
-    // fine either way, so I'm leaving it as it is. -- bblum
-
-    // Copy the list of schedulers so that we don't hold the lock while
-    // running kill_all_tasks. Refcount to ensure they stay alive.
-    std::vector<rust_scheduler*> scheds;
-    {
-        scoped_lock with(sched_lock);
-        // All schedulers created after this flag is set will be doomed.
-        killed = true;
-        for (sched_map::iterator iter = sched_table.begin();
-             iter != sched_table.end(); iter++) {
-            iter->second->ref();
-            scheds.push_back(iter->second);
-        }
-    }
-
-    for (std::vector<rust_scheduler*>::iterator iter = scheds.begin();
-         iter != scheds.end(); iter++) {
-        (*iter)->kill_all_tasks();
-        (*iter)->deref();
-    }
-}
-
-rust_task_id
-rust_kernel::generate_task_id() {
-    rust_task_id id = sync::increment(max_task_id);
-    assert(id != INTPTR_MAX && "Hit the maximum task id");
-    return id;
-}
-
-void
-rust_kernel::set_exit_status(int code) {
-    scoped_lock with(rval_lock);
-    // If we've already failed then that's the code we're going to use
-    if (rval != PROC_FAIL_CODE) {
-        rval = code;
-    }
-}
-
-void
-rust_kernel::inc_live_count() {
-    uintptr_t new_non_weak_tasks = sync::increment(non_weak_tasks);
-    KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
-}
-
-void
-rust_kernel::dec_live_count() {
-    uintptr_t new_non_weak_tasks = sync::decrement(non_weak_tasks);
-    KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
-    if (new_non_weak_tasks == 0) {
-        begin_shutdown();
-    }
-}
-
-void
-rust_kernel::allow_scheduler_exit() {
-    scoped_lock with(sched_lock);
-
-    KLOG_("Allowing main scheduler to exit");
-    // It's only the main schedulers left. Tell them to exit
-    rust_scheduler *main_sched =
-        get_scheduler_by_id_nolock(main_scheduler);
-    assert(main_sched != NULL);
-    main_sched->allow_exit();
-
-    KLOG_("Allowing osmain scheduler to exit");
-    rust_scheduler *osmain_sched =
-        get_scheduler_by_id_nolock(osmain_scheduler);
-    assert(osmain_sched != NULL);
-    osmain_sched->allow_exit();
-}
-
-void
-rust_kernel::begin_shutdown() {
-    {
-        scoped_lock with(sched_lock);
-        // FIXME #4410: This shouldn't be necessary, but because of
-        // unweaken_task this may end up getting called multiple times.
-        if (already_exiting) {
-            return;
-        } else {
-            already_exiting = true;
-        }
-    }
-
-    allow_scheduler_exit();
-}
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h
deleted file mode 100644 (file)
index 0fe3f76..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-// 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.
-
-
-/**
-   A single runtime instance.
-
-   The kernel is primarily responsible for managing the lifetime of
-   schedulers, which in turn run rust tasks. It provides a memory
-   allocator and logging service for use by other runtime components,
-   it creates unique task ids.
-
-   The kernel runs until there are no live schedulers.
-
-   The kernel internally runs an additional, special scheduler called
-   the 'osmain' (or platform) scheduler, which schedules tasks on the
-   thread that is running the kernel (normally the thread on which the
-   C main function was called). This scheduler may be used by Rust
-   code for interacting with platform APIs that insist on being called
-   from the main thread.
-
-   The requirements of the osmain scheduler has resulted in a complex
-   process for creating and running scheduler loops that involves
-   a thing called a 'rust_sched_launcher_factory' whose function I've
-   already forgotten. rust_scheduler is the main scheduler class,
-   and tasks are scheduled on individual threads by rust_sched_loop.
-
-   Ideally all the in-memory Rust state is encapsulated by a kernel
-   instance, but there is still some truly global data in the runtime
-   (like the check claims flag).
- */
-
-#ifndef RUST_KERNEL_H
-#define RUST_KERNEL_H
-
-#include "rust_globals.h"
-
-#include <map>
-#include <vector>
-
-#include "rust_exchange_alloc.h"
-#include "rust_log.h"
-#include "rust_sched_reaper.h"
-#include "rust_type.h"
-#include "sync/lock_and_signal.h"
-
-class rust_scheduler;
-class rust_sched_driver;
-class rust_sched_launcher_factory;
-struct rust_task_thread;
-
-// Scheduler, task handles. These uniquely identify within a
-// single kernel instance the objects they represent.
-typedef intptr_t rust_sched_id;
-typedef intptr_t rust_task_id;
-
-typedef std::map<rust_sched_id, rust_scheduler*> sched_map;
-
-class rust_kernel {
-    rust_exchange_alloc exchange_alloc;
-    rust_log _log;
-
-    // The next task id
-    rust_task_id max_task_id;
-
-    lock_and_signal rval_lock;
-    int rval;
-
-    // Protects max_sched_id and sched_table, join_list, killed,
-    // already_exiting
-    lock_and_signal sched_lock;
-    // The next scheduler id
-    rust_sched_id max_sched_id;
-    // A map from scheduler ids to schedulers. When this is empty
-    // the kernel terminates
-    sched_map sched_table;
-    // A list of scheduler ids that are ready to exit
-    std::vector<rust_sched_id> join_list;
-    // Whether or not the runtime has to die (triggered when the root/main
-    // task group fails). This propagates to all new schedulers and tasks
-    // created after it is set.
-    bool killed;
-    bool already_exiting;
-
-
-    rust_sched_reaper sched_reaper;
-
-    // The primary scheduler
-    rust_sched_id main_scheduler;
-    // The single-threaded scheduler that uses the main thread
-    rust_sched_id osmain_scheduler;
-    // Runs the single-threaded scheduler that executes tasks
-    // on the main thread
-    rust_sched_driver *osmain_driver;
-
-    // An atomically updated count of the live, 'non-weak' tasks
-    uintptr_t non_weak_tasks;
-
-    rust_scheduler* get_scheduler_by_id_nolock(rust_sched_id id);
-    void allow_scheduler_exit();
-    void begin_shutdown();
-
-public:
-    struct rust_env *env;
-
-    rust_kernel(rust_env *env);
-
-    void log(uint32_t level, char const *fmt, ...);
-    void fatal(char const *fmt, ...);
-
-    void *malloc(size_t size, const char *tag);
-    void *realloc(void *mem, size_t size);
-    void free(void *mem);
-    rust_exchange_alloc *region() { return &exchange_alloc; }
-
-    void fail();
-
-    rust_sched_id create_scheduler(size_t num_threads);
-    rust_sched_id create_scheduler(rust_sched_launcher_factory *launchfac,
-                                   size_t num_threads, bool allow_exit);
-    rust_scheduler* get_scheduler_by_id(rust_sched_id id);
-    // Called by a scheduler to indicate that it is terminating
-    void release_scheduler_id(rust_sched_id id);
-    void wait_for_schedulers();
-    int run();
-
-    rust_task_id generate_task_id();
-
-    void set_exit_status(int code);
-
-    rust_sched_id main_sched_id() { return main_scheduler; }
-    rust_sched_id osmain_sched_id() { return osmain_scheduler; }
-
-    void inc_live_count();
-    void dec_live_count();
-
-};
-
-template <typename T> struct kernel_owned {
-    inline void *operator new(size_t size, rust_kernel *kernel,
-                              const char *tag) {
-        return kernel->malloc(size, tag);
-    }
-
-    void operator delete(void *ptr) {
-        ((T *)ptr)->kernel->free(ptr);
-    }
-};
-
-#endif /* RUST_KERNEL_H */
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
index f7b117a8cb1bdf6940573e1c6be691feccf8a547..25b246c69f51a10a0877d9d72f0e781308f42495 100644 (file)
 #include "rust_crate_map.h"
 #include "util/array_list.h"
 #include "rust_util.h"
-#include "rust_task.h"
-
-/**
- * Synchronizes access to the underlying logging mechanism.
- */
-static lock_and_signal _log_lock;
-/**
- * Indicates whether we are outputting to the console.
- * Protected by _log_lock;
- */
-static bool _log_to_console = true;
-
-/*
- * Request that console logging be turned on.
- */
-void
-log_console_on() {
-    scoped_lock with(_log_lock);
-    _log_to_console = true;
-}
-
-/*
- * Request that console logging be turned off. Can be
- * overridden by the environment.
- */
-void
-log_console_off() {
-    scoped_lock with(_log_lock);
-    _log_to_console = false;
-}
-
-bool
-should_log_console() {
-    scoped_lock with(_log_lock);
-    return _log_to_console;
-}
-
-rust_log::rust_log(rust_sched_loop *sched_loop) :
-    _sched_loop(sched_loop) {
-}
-
-rust_log::~rust_log() {
-
-}
-
-const uint16_t
-hash(uintptr_t ptr) {
-#   if(ULONG_MAX == 0xFFFFFFFF)
-    // Robert Jenkins' 32 bit integer hash function
-    ptr = (ptr + 0x7ed55d16) + (ptr << 12);
-    ptr = (ptr ^ 0xc761c23c) ^ (ptr >> 19);
-    ptr = (ptr + 0x165667b1) + (ptr << 5);
-    ptr = (ptr + 0xd3a2646c) ^ (ptr << 9);
-    ptr = (ptr + 0xfd7046c5) + (ptr << 3);
-    ptr = (ptr ^ 0xb55a4f09) ^ (ptr >> 16);
-#   elif(ULONG_MAX == 0xFFFFFFFFFFFFFFFF)
-    // "hash64shift()" from http://www.concentric.net/~Ttwang/tech/inthash.htm
-    ptr = (~ptr) + (ptr << 21); // ptr = (ptr << 21) - ptr - 1;
-    ptr = ptr ^ (ptr >> 24);
-    ptr = (ptr + (ptr << 3)) + (ptr << 8); // ptr * 265
-    ptr = ptr ^ (ptr >> 14);
-    ptr = (ptr + (ptr << 2)) + (ptr << 4); // ptr * 21
-    ptr = ptr ^ (ptr >> 28);
-    ptr = ptr + (ptr << 31);
-#   else
-#   error "hash() not defined for this pointer size"
-#   endif
-    return (uint16_t) ptr;
-}
-
-char *
-copy_string(char *dst, const char *src, size_t length) {
-    return strncpy(dst, src, length) + length;
-}
-
-char *
-append_string(char *buffer, const char *format, ...) {
-    if (buffer != NULL && format) {
-        va_list args;
-        va_start(args, format);
-        size_t off = strlen(buffer);
-        vsnprintf(buffer + off, BUF_BYTES - off, format, args);
-        va_end(args);
-    }
-    return buffer;
-}
-
-void
-rust_log::log(rust_task* task, uint32_t level, char const *fmt, ...) {
-    char buf[BUF_BYTES];
-    va_list args;
-    va_start(args, fmt);
-    int formattedbytes = vsnprintf(buf, sizeof(buf), fmt, args);
-    if( formattedbytes and (unsigned)formattedbytes > BUF_BYTES ){
-        const char truncatedstr[] = "[...]";
-        memcpy( &buf[BUF_BYTES-sizeof(truncatedstr)],
-                truncatedstr,
-                sizeof(truncatedstr));
-    }
-    trace_ln(task, level, buf);
-    va_end(args);
-}
-
-void
-rust_log::trace_ln(char *prefix, char *message) {
-    char buffer[BUF_BYTES] = "";
-    _log_lock.lock();
-    append_string(buffer, "%s", prefix);
-    append_string(buffer, "%s", message);
-    if (_log_to_console) {
-        fprintf(stderr, "rust: %s\n", buffer);
-        fflush(stderr);
-    }
-    _log_lock.unlock();
-}
-
-void
-rust_log::trace_ln(rust_task *task, uint32_t level, char *message) {
-
-    if (task) {
-        // There is not enough room to be logging on the rust stack
-        assert(!task->on_rust_stack() && "logging on rust stack");
-    }
-
-    // FIXME (#2672): The scheduler and task names used to have meaning,
-    // but they are always equal to 'main' currently
-#if 0
-
-#if defined(__WIN32__)
-    uint32_t thread_id = 0;
-#else
-    uint32_t thread_id = hash((uintptr_t) pthread_self());
-#endif
-
-    char prefix[BUF_BYTES] = "";
-    if (_sched_loop && _sched_loop-.name) {
-        append_string(prefix, "%04" PRIxPTR ":%.10s:",
-                      thread_id, _sched_loop->name);
-    } else {
-        append_string(prefix, "%04" PRIxPTR ":0x%08" PRIxPTR ":",
-                      thread_id, (uintptr_t) _sched_loop);
-    }
-    if (task) {
-        if (task->name) {
-            append_string(prefix, "%.10s:", task->name);
-        } else {
-            append_string(prefix, "0x%08" PRIxPTR ":", (uintptr_t) task);
-        }
-    }
-#else
-    char prefix[BUF_BYTES] = "";
-#endif
-
-    trace_ln(prefix, message);
-}
 
 // Reading log directives and setting log level vars
 
index b98d8477dbc0879c86951dd52d18c550b871c603..e3d61b8ab5d5a7c829ea5bcbcf5f2f622ec5f1f4 100644 (file)
@@ -18,53 +18,6 @@ const uint32_t log_warn = 2;
 const uint32_t log_info = 3;
 const uint32_t log_debug = 4;
 
-#define LOG(task, field, ...)                                   \
-    DLOG_LVL(log_debug, task, task->sched_loop, field, __VA_ARGS__)
-#define LOG_ERR(task, field, ...)                               \
-    DLOG_LVL(log_err, task, task->sched_loop, field, __VA_ARGS__)
-#define DLOG(sched_loop, field, ...)                                   \
-    DLOG_LVL(log_debug, NULL, sched_loop, field, __VA_ARGS__)
-#define DLOG_ERR(sched_loop, field, ...)                               \
-    DLOG_LVL(log_err, NULL, sched_loop, field, __VA_ARGS__)
-#define LOGPTR(sched_loop, msg, ptrval)                                \
-    DLOG_LVL(log_debug, NULL, sched_loop, mem, "%s 0x%" PRIxPTR, msg, ptrval)
-#define DLOG_LVL(lvl, task, sched_loop, field, ...)                    \
-    do {                                                        \
-        rust_sched_loop* _d_ = sched_loop;                      \
-        if (log_rt_##field >= lvl && _d_->log_lvl >= lvl) {     \
-            _d_->get_log().log(task, lvl, __VA_ARGS__);         \
-        }                                                       \
-    } while (0)
-
-#define KLOG(k, field, ...) \
-    KLOG_LVL(k, field, log_debug, __VA_ARGS__)
-#define KLOG_LVL(k, field, lvl, ...)                          \
-    do {                                                      \
-        if (log_rt_##field >= lvl) {                          \
-            (k)->log(lvl, __VA_ARGS__);                       \
-        }                                                     \
-    } while (0)
-
-struct rust_sched_loop;
-struct rust_task;
-
-class rust_log {
-
-public:
-    rust_log(rust_sched_loop *sched_loop);
-    virtual ~rust_log();
-
-    void log(rust_task* task, uint32_t level, char const *fmt, ...);
-    void trace_ln(rust_task *task, uint32_t level, char *message);
-    void trace_ln(char *prefix, char *message);
-    bool is_tracing(uint32_t type_bits);
-
-private:
-    rust_sched_loop *_sched_loop;
-    bool _use_labels;
-    void trace_ln(rust_task *task, char *message);
-};
-
 void update_log_settings(void* crate_map, char* settings);
 
 extern uint32_t log_rt_mem;
index 0ba760786914006dc1f58c5660a52c9e18bec374..25cbaf822f04f80e98433fec9031eb06213fd31e 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-#include "rust_kernel.h"
+#include "rust_globals.h"
 
 #ifdef __APPLE__
 #include <crt_externs.h>
diff --git a/src/rt/rust_sched_driver.cpp b/src/rt/rust_sched_driver.cpp
deleted file mode 100644 (file)
index c8f59b1..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// 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.
-
-
-#include "rust_globals.h"
-#include "rust_sched_driver.h"
-#include "rust_sched_loop.h"
-
-rust_sched_driver::rust_sched_driver(rust_sched_loop *sched_loop)
-    : sched_loop(sched_loop),
-      signalled(false) {
-
-    assert(sched_loop != NULL);
-    sched_loop->on_pump_loop(this);
-}
-
-/**
- * Starts the main scheduler loop which performs task scheduling for this
- * domain.
- *
- * Returns once no more tasks can be scheduled and all task ref_counts
- * drop to zero.
- */
-void
-rust_sched_driver::start_main_loop() {
-    assert(sched_loop != NULL);
-
-#ifdef __APPLE__
-    {
-        char buf[64];
-        snprintf(buf, sizeof(buf), "scheduler loop %d", sched_loop->get_id());
-        // pthread_setname_np seems to have a different signature and
-        // different behavior on different platforms. Thus, this is
-        // only for Mac at the moment. There are equivalent versions
-        // for Linux that we can add if needed.
-        pthread_setname_np(buf);
-    }
-#endif
-
-    rust_sched_loop_state state = sched_loop_state_keep_going;
-    while (state != sched_loop_state_exit) {
-        DLOG(sched_loop, dom, "pumping scheduler");
-        state = sched_loop->run_single_turn();
-
-        if (state == sched_loop_state_block) {
-            scoped_lock with(lock);
-            if (!signalled) {
-                DLOG(sched_loop, dom, "blocking scheduler");
-                lock.wait();
-            }
-            signalled = false;
-        }
-    }
-}
-
-void
-rust_sched_driver::signal() {
-    scoped_lock with(lock);
-    signalled = true;
-    lock.signal();
-}
diff --git a/src/rt/rust_sched_driver.h b/src/rt/rust_sched_driver.h
deleted file mode 100644 (file)
index 9824c5e..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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.
-
-#ifndef RUST_SCHED_DRIVER_H
-#define RUST_SCHED_DRIVER_H
-
-#include "sync/lock_and_signal.h"
-#include "rust_signal.h"
-
-struct rust_sched_loop;
-
-class rust_sched_driver : public rust_signal {
-private:
-    rust_sched_loop *sched_loop;
-    lock_and_signal lock;
-    bool signalled;
-
-public:
-    rust_sched_driver(rust_sched_loop *sched_loop);
-
-    void start_main_loop();
-
-    virtual void signal();
-};
-
-#endif /* RUST_SCHED_DRIVER_H */
diff --git a/src/rt/rust_sched_launcher.cpp b/src/rt/rust_sched_launcher.cpp
deleted file mode 100644 (file)
index a951453..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-
-
-#include "rust_sched_launcher.h"
-#include "rust_scheduler.h"
-
-const size_t SCHED_STACK_SIZE = 1024*100;
-
-rust_sched_launcher::rust_sched_launcher(rust_scheduler *sched, int id,
-                                         bool killed)
-    : kernel(sched->kernel),
-      sched_loop(sched, id, killed),
-      driver(&sched_loop) {
-}
-
-rust_thread_sched_launcher::rust_thread_sched_launcher(rust_scheduler *sched,
-                                                       int id, bool killed)
-    : rust_sched_launcher(sched, id, killed),
-      rust_thread(SCHED_STACK_SIZE) {
-}
-
-rust_manual_sched_launcher::rust_manual_sched_launcher(rust_scheduler *sched,
-                                                       int id, bool killed)
-    : rust_sched_launcher(sched, id, killed) {
-}
-
-rust_sched_launcher *
-rust_thread_sched_launcher_factory::create(rust_scheduler *sched, int id,
-                                           bool killed) {
-    return new(sched->kernel, "rust_thread_sched_launcher")
-        rust_thread_sched_launcher(sched, id, killed);
-}
-
-rust_sched_launcher *
-rust_manual_sched_launcher_factory::create(rust_scheduler *sched, int id,
-                                           bool killed) {
-    assert(launcher == NULL && "I can only track one sched_launcher");
-    launcher = new(sched->kernel, "rust_manual_sched_launcher")
-        rust_manual_sched_launcher(sched, id, killed);
-    return launcher;
-}
diff --git a/src/rt/rust_sched_launcher.h b/src/rt/rust_sched_launcher.h
deleted file mode 100644 (file)
index a981fad..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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.
-
-#ifndef RUST_SCHED_LAUNCHER_H
-#define RUST_SCHED_LAUNCHER_H
-
-#include "sync/rust_thread.h"
-#include "rust_sched_driver.h"
-#include "rust_kernel.h"
-#include "rust_sched_loop.h"
-
-class rust_sched_launcher : public kernel_owned<rust_sched_launcher> {
-public:
-    rust_kernel *kernel;
-
-private:
-    rust_sched_loop sched_loop;
-
-private:
-    // private and undefined to disable copying
-    rust_sched_launcher(const rust_sched_launcher& rhs);
-    rust_sched_launcher& operator=(const rust_sched_launcher& rhs);
-
-protected:
-    rust_sched_driver driver;
-
-public:
-    rust_sched_launcher(rust_scheduler *sched, int id, bool killed);
-    virtual ~rust_sched_launcher() { }
-
-    virtual void start() = 0;
-    virtual void join() = 0;
-    rust_sched_loop *get_loop() { return &sched_loop; }
-};
-
-class rust_thread_sched_launcher
-  :public rust_sched_launcher,
-   private rust_thread {
-public:
-    rust_thread_sched_launcher(rust_scheduler *sched, int id, bool killed);
-    virtual void start() { rust_thread::start(); }
-    virtual void join() { rust_thread::join(); }
-    virtual void run() { driver.start_main_loop(); }
-};
-
-class rust_manual_sched_launcher : public rust_sched_launcher {
-public:
-    rust_manual_sched_launcher(rust_scheduler *sched, int id, bool killed);
-    virtual void start() { }
-    virtual void join() { }
-    rust_sched_driver *get_driver() { return &driver; };
-};
-
-class rust_sched_launcher_factory {
-public:
-    virtual ~rust_sched_launcher_factory() { }
-    virtual rust_sched_launcher *
-    create(rust_scheduler *sched, int id, bool killed) = 0;
-};
-
-class rust_thread_sched_launcher_factory
-    : public rust_sched_launcher_factory {
-public:
-    virtual rust_sched_launcher *create(rust_scheduler *sched, int id,
-                                        bool killed);
-};
-
-class rust_manual_sched_launcher_factory
-    : public rust_sched_launcher_factory {
-private:
-    rust_manual_sched_launcher *launcher;
-public:
-    rust_manual_sched_launcher_factory() : launcher(NULL) { }
-    virtual rust_sched_launcher *create(rust_scheduler *sched, int id,
-                                        bool killed);
-    rust_sched_driver *get_driver() {
-        assert(launcher != NULL);
-        return launcher->get_driver();
-    }
-};
-
-#endif // RUST_SCHED_LAUNCHER_H
diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp
deleted file mode 100644 (file)
index 1f718df..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-// 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.
-
-
-#include "rust_sched_loop.h"
-#include "rust_util.h"
-#include "rust_scheduler.h"
-
-#ifndef _WIN32
-pthread_key_t rust_sched_loop::task_key;
-#else
-DWORD rust_sched_loop::task_key;
-#endif
-
-const size_t C_STACK_SIZE = 2*1024*1024;
-
-bool rust_sched_loop::tls_initialized = false;
-
-rust_sched_loop::rust_sched_loop(rust_scheduler *sched, int id, bool killed) :
-    _log(this),
-    id(id),
-    should_exit(false),
-    cached_c_stack(NULL),
-    extra_c_stack(NULL),
-    cached_big_stack(NULL),
-    extra_big_stack(NULL),
-    dead_task(NULL),
-    killed(killed),
-    pump_signal(NULL),
-    kernel(sched->kernel),
-    sched(sched),
-    log_lvl(log_debug),
-    min_stack_size(kernel->env->min_stack_size),
-    local_region(false, kernel->env->detailed_leaks, kernel->env->poison_on_free),
-    // FIXME #2891: calculate a per-scheduler name.
-    name("main")
-{
-    LOGPTR(this, "new dom", (uintptr_t)this);
-    rng_init(&rng, kernel->env->rust_seed, NULL, 0);
-
-    if (!tls_initialized)
-        init_tls();
-}
-
-void
-rust_sched_loop::activate(rust_task *task) {
-    lock.must_have_lock();
-    task->ctx.next = &c_context;
-    DLOG(this, task, "descheduling...");
-    lock.unlock();
-    prepare_c_stack(task);
-    task->ctx.swap(c_context);
-    task->cleanup_after_turn();
-    unprepare_c_stack();
-    lock.lock();
-    DLOG(this, task, "task has returned");
-}
-
-
-void
-rust_sched_loop::fail() {
-    _log.log(NULL, log_err, "domain %s @0x%" PRIxPTR " root task failed",
-        name, this);
-    kernel->fail();
-}
-
-void
-rust_sched_loop::kill_all_tasks() {
-    std::vector<rust_task*> all_tasks;
-
-    {
-        scoped_lock with(lock);
-        // Any task created after this will be killed. See transition, below.
-        killed = true;
-
-        for (size_t i = 0; i < running_tasks.length(); i++) {
-            rust_task *t = running_tasks[i];
-            t->ref();
-            all_tasks.push_back(t);
-        }
-
-        for (size_t i = 0; i < blocked_tasks.length(); i++) {
-            rust_task *t = blocked_tasks[i];
-            t->ref();
-            all_tasks.push_back(t);
-        }
-    }
-
-    while (!all_tasks.empty()) {
-        rust_task *task = all_tasks.back();
-        all_tasks.pop_back();
-        task->kill();
-        task->deref();
-    }
-}
-
-size_t
-rust_sched_loop::number_of_live_tasks() {
-    lock.must_have_lock();
-    return running_tasks.length() + blocked_tasks.length();
-}
-
-/**
- * Delete any dead tasks.
- */
-void
-rust_sched_loop::reap_dead_tasks() {
-    lock.must_have_lock();
-
-    if (dead_task == NULL) {
-        return;
-    }
-
-    // Dereferencing the task will probably cause it to be released
-    // from the scheduler, which may end up trying to take this lock
-    lock.unlock();
-
-    dead_task->delete_all_stacks();
-    // Deref the task, which may cause it to request us to release it
-    dead_task->deref();
-    dead_task = NULL;
-
-    lock.lock();
-}
-
-void
-rust_sched_loop::release_task(rust_task *task) {
-    // Nobody should have a ref to the task at this point
-    assert(task->get_ref_count() == 0);
-    // Now delete the task, which will require using this thread's
-    // memory region.
-    delete task;
-    // Now release the task from the scheduler, which may trigger this
-    // thread to exit
-    sched->release_task();
-}
-
-/**
- * Schedules a running task for execution. Only running tasks can be
- * activated.  Blocked tasks have to be unblocked before they can be
- * activated.
- *
- * Returns NULL if no tasks can be scheduled.
- */
-rust_task *
-rust_sched_loop::schedule_task() {
-    lock.must_have_lock();
-    size_t tasks = running_tasks.length();
-    if (tasks > 0) {
-        size_t i = (tasks > 1) ? (rng_gen_u32(&rng) % tasks) : 0;
-        return running_tasks[i];
-    }
-    return NULL;
-}
-
-void
-rust_sched_loop::log_state() {
-    if (log_rt_task < log_debug) return;
-
-    if (!running_tasks.is_empty()) {
-        _log.log(NULL, log_debug, "running tasks:");
-        for (size_t i = 0; i < running_tasks.length(); i++) {
-            _log.log(NULL, log_debug, "\t task: %s @0x%" PRIxPTR,
-                running_tasks[i]->name,
-                running_tasks[i]);
-        }
-    }
-
-    if (!blocked_tasks.is_empty()) {
-        _log.log(NULL, log_debug, "blocked tasks:");
-        for (size_t i = 0; i < blocked_tasks.length(); i++) {
-            _log.log(NULL, log_debug, "\t task: %s @0x%" PRIxPTR
-                ", blocked on: 0x%" PRIxPTR " '%s'",
-                blocked_tasks[i]->name, blocked_tasks[i],
-                blocked_tasks[i]->get_cond(),
-                blocked_tasks[i]->get_cond_name());
-        }
-    }
-}
-
-void
-rust_sched_loop::on_pump_loop(rust_signal *signal) {
-    assert(pump_signal == NULL);
-    assert(signal != NULL);
-    pump_signal = signal;
-}
-
-void
-rust_sched_loop::pump_loop() {
-    assert(pump_signal != NULL);
-    pump_signal->signal();
-}
-
-rust_sched_loop_state
-rust_sched_loop::run_single_turn() {
-    DLOG(this, task,
-         "scheduler %d resuming ...", id);
-
-    lock.lock();
-
-    if (!should_exit) {
-        assert(dead_task == NULL && "Tasks should only die after running");
-
-        DLOG(this, dom, "worker %d, number_of_live_tasks = %d",
-             id, number_of_live_tasks());
-
-        rust_task *scheduled_task = schedule_task();
-
-        if (scheduled_task == NULL) {
-            log_state();
-            DLOG(this, task,
-                 "all tasks are blocked, scheduler id %d yielding ...",
-                 id);
-
-            lock.unlock();
-            return sched_loop_state_block;
-        }
-
-        scheduled_task->assert_is_running();
-
-        DLOG(this, task,
-             "activating task %s 0x%" PRIxPTR
-             ", state: %s",
-             scheduled_task->name,
-             (uintptr_t)scheduled_task,
-             state_name(scheduled_task->get_state()));
-
-        place_task_in_tls(scheduled_task);
-
-        DLOG(this, task,
-             "Running task %p on worker %d",
-             scheduled_task, id);
-        activate(scheduled_task);
-
-        DLOG(this, task,
-             "returned from task %s @0x%" PRIxPTR
-             " in state '%s', worker id=%d" PRIxPTR,
-             scheduled_task->name,
-             (uintptr_t)scheduled_task,
-             state_name(scheduled_task->get_state()),
-             id);
-
-        reap_dead_tasks();
-
-        lock.unlock();
-        return sched_loop_state_keep_going;
-    } else {
-        assert(running_tasks.is_empty() && "Should have no running tasks");
-        assert(blocked_tasks.is_empty() && "Should have no blocked tasks");
-        assert(dead_task == NULL && "Should have no dead tasks");
-
-        DLOG(this, dom, "finished main-loop %d", id);
-
-        lock.unlock();
-
-        assert(!extra_c_stack);
-        if (cached_c_stack) {
-            destroy_exchange_stack(kernel->region(), cached_c_stack);
-            cached_c_stack = NULL;
-        }
-        assert(!extra_big_stack);
-        if (cached_big_stack) {
-            destroy_exchange_stack(kernel->region(), cached_big_stack);
-            cached_big_stack = NULL;
-        }
-
-        sched->release_task_thread();
-        return sched_loop_state_exit;
-    }
-}
-
-rust_task *
-rust_sched_loop::create_task(rust_task *spawner, const char *name) {
-    rust_task *task =
-        new (this->kernel, "rust_task")
-        rust_task(this, task_state_newborn,
-                  name, kernel->env->min_stack_size);
-    DLOG(this, task, "created task: " PTR ", spawner: %s, name: %s",
-                        task, spawner ? spawner->name : "(none)", name);
-
-    task->id = kernel->generate_task_id();
-    return task;
-}
-
-rust_task_list *
-rust_sched_loop::state_list(rust_task_state state) {
-    switch (state) {
-    case task_state_running:
-        return &running_tasks;
-    case task_state_blocked:
-        return &blocked_tasks;
-    default:
-        return NULL;
-    }
-}
-
-const char *
-rust_sched_loop::state_name(rust_task_state state) {
-    switch (state) {
-    case task_state_newborn:
-        return "newborn";
-    case task_state_running:
-        return "running";
-    case task_state_blocked:
-        return "blocked";
-    case task_state_dead:
-        return "dead";
-    default:
-        assert(false);
-        return "";
-    }
-}
-
-void
-rust_sched_loop::transition(rust_task *task,
-                             rust_task_state src, rust_task_state dst,
-                             rust_cond *cond, const char* cond_name) {
-    scoped_lock with(lock);
-    DLOG(this, task,
-         "task %s " PTR " state change '%s' -> '%s' while in '%s'",
-         name, (uintptr_t)this, state_name(src), state_name(dst),
-         state_name(task->get_state()));
-    assert(task->get_state() == src);
-    rust_task_list *src_list = state_list(src);
-    if (src_list) {
-        src_list->remove(task);
-    }
-    rust_task_list *dst_list = state_list(dst);
-    if (dst_list) {
-        dst_list->append(task);
-    }
-    if (dst == task_state_dead) {
-        assert(dead_task == NULL);
-        dead_task = task;
-    }
-    task->set_state(dst, cond, cond_name);
-
-    // If the entire runtime is failing, newborn tasks must be doomed.
-    if (src == task_state_newborn && killed) {
-        task->kill_inner();
-    }
-
-    pump_loop();
-}
-
-#ifndef _WIN32
-void
-rust_sched_loop::init_tls() {
-    int result = pthread_key_create(&task_key, NULL);
-    assert(!result && "Couldn't create the TLS key!");
-    tls_initialized = true;
-}
-
-void
-rust_sched_loop::place_task_in_tls(rust_task *task) {
-    int result = pthread_setspecific(task_key, task);
-    assert(!result && "Couldn't place the task in TLS!");
-    task->record_stack_limit();
-}
-#else
-void
-rust_sched_loop::init_tls() {
-    task_key = TlsAlloc();
-    assert(task_key != TLS_OUT_OF_INDEXES && "Couldn't create the TLS key!");
-    tls_initialized = true;
-}
-
-void
-rust_sched_loop::place_task_in_tls(rust_task *task) {
-    BOOL result = TlsSetValue(task_key, task);
-    assert(result && "Couldn't place the task in TLS!");
-    task->record_stack_limit();
-}
-#endif
-
-void
-rust_sched_loop::exit() {
-    scoped_lock with(lock);
-    DLOG(this, dom, "Requesting exit for thread %d", id);
-    should_exit = true;
-    pump_loop();
-}
-
-// Before activating each task, make sure we have a C stack available.
-// It needs to be allocated ahead of time (while we're on our own
-// stack), because once we're on the Rust stack we won't have enough
-// room to do the allocation
-void
-rust_sched_loop::prepare_c_stack(rust_task *task) {
-    assert(!extra_c_stack);
-    if (!cached_c_stack && !task->have_c_stack()) {
-        cached_c_stack = create_exchange_stack(kernel->region(),
-                                               C_STACK_SIZE);
-    }
-    assert(!extra_big_stack);
-    if (!cached_big_stack) {
-        cached_big_stack = create_exchange_stack(kernel->region(),
-                                                 C_STACK_SIZE +
-                                                 (C_STACK_SIZE * 2));
-        cached_big_stack->is_big = 1;
-    }
-}
-
-void
-rust_sched_loop::unprepare_c_stack() {
-    if (extra_c_stack) {
-        destroy_exchange_stack(kernel->region(), extra_c_stack);
-        extra_c_stack = NULL;
-    }
-    if (extra_big_stack) {
-        destroy_exchange_stack(kernel->region(), extra_big_stack);
-        extra_big_stack = NULL;
-    }
-}
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 70;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
diff --git a/src/rt/rust_sched_loop.h b/src/rt/rust_sched_loop.h
deleted file mode 100644 (file)
index e0101c4..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-// 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.
-
-#ifndef RUST_SCHED_LOOP_H
-#define RUST_SCHED_LOOP_H
-
-#include "rust_globals.h"
-#include "rust_log.h"
-#include "rust_rng.h"
-#include "rust_stack.h"
-#include "rust_signal.h"
-#include "context.h"
-#include "util/indexed_list.h"
-
-enum rust_task_state {
-    task_state_newborn,
-    task_state_running,
-    task_state_blocked,
-    task_state_dead
-};
-
-/*
-The result of every turn of the scheduler loop. Instructs the loop
-driver how to proceed.
- */
-enum rust_sched_loop_state {
-    sched_loop_state_keep_going,
-    sched_loop_state_block,
-    sched_loop_state_exit
-};
-
-class rust_kernel;
-class rust_scheduler;
-struct rust_task;
-
-typedef indexed_list<rust_task> rust_task_list;
-
-struct rust_sched_loop
-{
-private:
-
-    lock_and_signal lock;
-
-    // Fields known only by the runtime:
-    rust_log _log;
-
-    const int id;
-
-    static bool tls_initialized;
-
-#ifndef __WIN32__
-    static pthread_key_t task_key;
-#else
-    static DWORD task_key;
-#endif
-
-    context c_context;
-    rust_rng rng;
-    bool should_exit;
-
-    stk_seg *cached_c_stack;
-    stk_seg *extra_c_stack;
-    stk_seg *cached_big_stack;
-    stk_seg *extra_big_stack;
-
-    rust_task_list running_tasks;
-    rust_task_list blocked_tasks;
-    rust_task *dead_task;
-    bool killed;
-
-    rust_signal *pump_signal;
-
-    void prepare_c_stack(rust_task *task);
-    void unprepare_c_stack();
-
-    rust_task_list *state_list(rust_task_state state);
-    const char *state_name(rust_task_state state);
-
-    void pump_loop();
-
-private:
-    // private and undefined to disable copying
-    rust_sched_loop(const rust_sched_loop& rhs);
-    rust_sched_loop& operator=(const rust_sched_loop& rhs);
-
-public:
-    rust_kernel *kernel;
-    rust_scheduler *sched;
-
-    // NB: this is used to filter *runtime-originating* debug
-    // logging, on a per-scheduler basis. It's not likely what
-    // you want to expose to the user in terms of per-task
-    // or per-module logging control. By default all schedulers
-    // are set to debug-level logging here, and filtered by
-    // runtime category using the pseudo-modules ::rt::foo.
-    uint32_t log_lvl;
-
-    size_t min_stack_size;
-    memory_region local_region;
-
-    const char *const name; // Used for debugging
-
-    // Only a pointer to 'name' is kept, so it must live as long as this
-    // domain.
-    rust_sched_loop(rust_scheduler *sched, int id, bool killed);
-    void activate(rust_task *task);
-    rust_log & get_log();
-    void fail();
-
-    size_t number_of_live_tasks();
-
-    void reap_dead_tasks();
-    rust_task *schedule_task();
-
-    void on_pump_loop(rust_signal *signal);
-    rust_sched_loop_state run_single_turn();
-
-    void log_state();
-
-    void kill_all_tasks();
-    bool doomed();
-
-    rust_task *create_task(rust_task *spawner, const char *name);
-
-    void transition(rust_task *task,
-                    rust_task_state src, rust_task_state dst,
-                    rust_cond *cond, const char* cond_name);
-
-    void init_tls();
-    void place_task_in_tls(rust_task *task);
-
-    static rust_task *get_task_tls();
-    static rust_task *try_get_task_tls();
-
-    // Called by each task when they are ready to be destroyed
-    void release_task(rust_task *task);
-
-    // Tells the scheduler to exit it's scheduling loop and thread
-    void exit();
-
-    // Called by tasks when they need a stack on which to run C code
-    stk_seg *borrow_c_stack();
-    void return_c_stack(stk_seg *stack);
-
-    // Called by tasks when they need a big stack
-    stk_seg *borrow_big_stack();
-    void return_big_stack(stk_seg *stack);
-
-    int get_id() { return this->id; }
-};
-
-inline rust_log &
-rust_sched_loop::get_log() {
-    return _log;
-}
-
-inline rust_task* rust_sched_loop::try_get_task_tls()
-{
-    if (!tls_initialized)
-        return NULL;
-#ifdef __WIN32__
-    rust_task *task = reinterpret_cast<rust_task *>
-        (TlsGetValue(task_key));
-#else
-    rust_task *task = reinterpret_cast<rust_task *>
-        (pthread_getspecific(task_key));
-#endif
-    return task;
-}
-
-inline rust_task* rust_sched_loop::get_task_tls()
-{
-    rust_task *task = try_get_task_tls();
-    assert(task && "Couldn't get the task from TLS!");
-    return task;
-}
-
-// NB: Runs on the Rust stack
-inline stk_seg *
-rust_sched_loop::borrow_c_stack() {
-    assert(cached_c_stack);
-    stk_seg *your_stack;
-    if (extra_c_stack) {
-        your_stack = extra_c_stack;
-        extra_c_stack = NULL;
-    } else {
-        your_stack = cached_c_stack;
-        cached_c_stack = NULL;
-    }
-    return your_stack;
-}
-
-// NB: Runs on the Rust stack
-inline void
-rust_sched_loop::return_c_stack(stk_seg *stack) {
-    assert(!extra_c_stack);
-    if (!cached_c_stack) {
-        cached_c_stack = stack;
-    } else {
-        extra_c_stack = stack;
-    }
-}
-
-// NB: Runs on the Rust stack. Might return NULL!
-inline stk_seg *
-rust_sched_loop::borrow_big_stack() {
-    stk_seg *your_stack;
-    if (extra_big_stack) {
-        your_stack = extra_big_stack;
-        extra_big_stack = NULL;
-    } else {
-        // NB: This may be null if we're asking for a *second*
-        // big stack, in which case the caller will fall back to a slow path
-        your_stack = cached_big_stack;
-        cached_big_stack = NULL;
-    }
-    return your_stack;
-}
-
-// NB: Runs on the Rust stack
-inline void
-rust_sched_loop::return_big_stack(stk_seg *stack) {
-    assert(!extra_big_stack);
-    assert(stack);
-    if (!cached_big_stack)
-        cached_big_stack = stack;
-    else
-        extra_big_stack = stack;
-}
-
-// this is needed to appease the circular dependency gods
-#include "rust_task.h"
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
-// End:
-//
-
-#endif /* RUST_SCHED_LOOP_H */
diff --git a/src/rt/rust_sched_reaper.cpp b/src/rt/rust_sched_reaper.cpp
deleted file mode 100644 (file)
index 1aef9cd..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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.
-
-
-#include "rust_kernel.h"
-#include "rust_sched_reaper.h"
-
-// NB: We're using a very small stack here
-const size_t STACK_SIZE = 1024*20;
-
-rust_sched_reaper::rust_sched_reaper(rust_kernel *kernel)
-    : rust_thread(STACK_SIZE), kernel(kernel) {
-}
-
-void
-rust_sched_reaper::run() {
-    kernel->wait_for_schedulers();
-}
diff --git a/src/rt/rust_sched_reaper.h b/src/rt/rust_sched_reaper.h
deleted file mode 100644 (file)
index 75a8d18..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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.
-
-#ifndef RUST_SCHED_REAPER_H
-#define RUST_SCHED_REAPER_H
-
-#include "sync/rust_thread.h"
-
-class rust_kernel;
-
-/* Responsible for joining with rust_schedulers */
-class rust_sched_reaper : public rust_thread {
-private:
-    rust_kernel *kernel;
-public:
-    rust_sched_reaper(rust_kernel *kernel);
-    virtual void run();
-};
-
-#endif /* RUST_SCHED_REAPER_H */
diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp
deleted file mode 100644 (file)
index e3a5d9d..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-// 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.
-
-
-#include "rust_globals.h"
-#include "rust_scheduler.h"
-#include "rust_task.h"
-#include "rust_util.h"
-#include "rust_sched_launcher.h"
-
-rust_scheduler::rust_scheduler(rust_kernel *kernel,
-                               size_t max_num_threads,
-                               rust_sched_id id,
-                               bool allow_exit,
-                               bool killed,
-                               rust_sched_launcher_factory *launchfac) :
-    ref_count(1),
-    kernel(kernel),
-    live_threads(0),
-    live_tasks(0),
-    cur_thread(0),
-    may_exit(allow_exit),
-    killed(killed),
-    launchfac(launchfac),
-    max_num_threads(max_num_threads),
-    id(id)
-{
-    // Create the first thread
-    scoped_lock with(lock);
-    threads.push(create_task_thread(0));
-}
-
-void rust_scheduler::delete_this() {
-    destroy_task_threads();
-    delete launchfac;
-    delete this;
-}
-
-rust_sched_launcher *
-rust_scheduler::create_task_thread(int id) {
-    lock.must_have_lock();
-    live_threads++;
-    rust_sched_launcher *thread = launchfac->create(this, id, killed);
-    KLOG(kernel, kern, "created task thread: " PTR
-         ", id: %d, live_threads: %d",
-         thread, id, live_threads);
-    return thread;
-}
-
-void
-rust_scheduler::destroy_task_thread(rust_sched_launcher *thread) {
-    KLOG(kernel, kern, "deleting task thread: " PTR, thread);
-    delete thread;
-}
-
-void
-rust_scheduler::destroy_task_threads() {
-    scoped_lock with(lock);
-    for(size_t i = 0; i < threads.size(); ++i) {
-        destroy_task_thread(threads[i]);
-    }
-}
-
-void
-rust_scheduler::start_task_threads()
-{
-    scoped_lock with(lock);
-    for(size_t i = 0; i < threads.size(); ++i) {
-        rust_sched_launcher *thread = threads[i];
-        thread->start();
-    }
-}
-
-void
-rust_scheduler::join_task_threads()
-{
-    scoped_lock with(lock);
-    for(size_t i = 0; i < threads.size(); ++i) {
-        rust_sched_launcher *thread = threads[i];
-        thread->join();
-    }
-}
-
-void
-rust_scheduler::kill_all_tasks() {
-    array_list<rust_sched_launcher *> copied_threads;
-    {
-        scoped_lock with(lock);
-        killed = true;
-        for (size_t i = 0; i < threads.size(); ++i) {
-            copied_threads.push(threads[i]);
-        }
-    }
-    for(size_t i = 0; i < copied_threads.size(); ++i) {
-        rust_sched_launcher *thread = copied_threads[i];
-        thread->get_loop()->kill_all_tasks();
-    }
-}
-
-rust_task *
-rust_scheduler::create_task(rust_task *spawner, const char *name) {
-    size_t thread_no;
-    {
-        scoped_lock with(lock);
-        live_tasks++;
-
-        if (cur_thread < threads.size()) {
-            thread_no = cur_thread;
-        } else {
-            assert(threads.size() < max_num_threads);
-            thread_no = threads.size();
-            rust_sched_launcher *thread = create_task_thread(thread_no);
-            thread->start();
-            threads.push(thread);
-        }
-        cur_thread = (thread_no + 1) % max_num_threads;
-    }
-    KLOG(kernel, kern, "Creating task %s, on thread %d.", name, thread_no);
-    kernel->inc_live_count();
-    rust_sched_launcher *thread = threads[thread_no];
-    return thread->get_loop()->create_task(spawner, name);
-}
-
-void
-rust_scheduler::release_task() {
-    bool need_exit = false;
-    {
-        scoped_lock with(lock);
-        live_tasks--;
-        if (live_tasks == 0 && may_exit) {
-            need_exit = true;
-        }
-    }
-    kernel->dec_live_count();
-    if (need_exit) {
-        exit();
-    }
-}
-
-void
-rust_scheduler::exit() {
-    // Take a copy of the number of threads. After the last thread exits this
-    // scheduler will get destroyed, and our fields will cease to exist.
-    //
-    // This is also the reason we can't use the lock here (as in the other
-    // cases when accessing `threads`), after the loop the lock won't exist
-    // anymore. This is safe because this method is only called when all the
-    // task are dead, so there is no chance of a task trying to create new
-    // threads.
-    size_t current_num_threads = threads.size();
-    for(size_t i = 0; i < current_num_threads; ++i) {
-        threads[i]->get_loop()->exit();
-    }
-}
-
-size_t
-rust_scheduler::max_number_of_threads() {
-    return max_num_threads;
-}
-
-size_t
-rust_scheduler::number_of_threads() {
-    scoped_lock with(lock);
-    return threads.size();
-}
-
-void
-rust_scheduler::release_task_thread() {
-    uintptr_t new_live_threads;
-    {
-        scoped_lock with(lock);
-        new_live_threads = --live_threads;
-    }
-    if (new_live_threads == 0) {
-        kernel->release_scheduler_id(id);
-    }
-}
-
-void
-rust_scheduler::allow_exit() {
-    bool need_exit = false;
-    {
-        scoped_lock with(lock);
-        may_exit = true;
-        need_exit = live_tasks == 0;
-    }
-    if (need_exit) {
-        exit();
-    }
-}
-
-void
-rust_scheduler::disallow_exit() {
-    scoped_lock with(lock);
-    may_exit = false;
-}
diff --git a/src/rt/rust_scheduler.h b/src/rt/rust_scheduler.h
deleted file mode 100644 (file)
index 30e0626..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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.
-
-/**
-   The rust scheduler. Schedulers may be added to the kernel
-   dynamically and they run until there are no more tasks to
-   schedule. Most of the scheduler work is carried out in worker
-   threads by rust_sched_loop.
- */
-
-#ifndef RUST_SCHEDULER_H
-#define RUST_SCHEDULER_H
-
-#include "rust_globals.h"
-#include "util/array_list.h"
-#include "rust_kernel.h"
-#include "rust_refcount.h"
-
-class rust_sched_launcher;
-class rust_sched_launcher_factory;
-
-class rust_scheduler : public kernel_owned<rust_scheduler> {
-    RUST_ATOMIC_REFCOUNT();
-    // FIXME (#2693): Make these private
-public:
-    rust_kernel *kernel;
-private:
-    // Protects live_threads, live_tasks, cur_thread, may_exit
-    lock_and_signal lock;
-    // When this hits zero we'll tell the kernel to release us
-    uintptr_t live_threads;
-    // When this hits zero we'll tell the threads to exit
-    uintptr_t live_tasks;
-    size_t cur_thread;
-    bool may_exit;
-    bool killed;
-
-    rust_sched_launcher_factory *launchfac;
-    array_list<rust_sched_launcher *> threads;
-    const size_t max_num_threads;
-
-    rust_sched_id id;
-
-    void destroy_task_threads();
-
-    rust_sched_launcher *create_task_thread(int id);
-    void destroy_task_thread(rust_sched_launcher *thread);
-
-    void exit();
-
-    // Called when refcount reaches zero
-    void delete_this();
-
-private:
-    // private and undefined to disable copying
-    rust_scheduler(const rust_scheduler& rhs);
-    rust_scheduler& operator=(const rust_scheduler& rhs);
-
-public:
-    rust_scheduler(rust_kernel *kernel, size_t max_num_threads,
-                   rust_sched_id id, bool allow_exit, bool killed,
-                   rust_sched_launcher_factory *launchfac);
-
-    void start_task_threads();
-    void join_task_threads();
-    void kill_all_tasks();
-    rust_task* create_task(rust_task *spawner, const char *name);
-
-    void release_task();
-
-    size_t max_number_of_threads();
-    size_t number_of_threads();
-    // Called by each thread when it terminates. When all threads
-    // terminate the scheduler does as well.
-    void release_task_thread();
-
-    rust_sched_id get_id() { return id; }
-    // Tells the scheduler that as soon as it runs out of tasks
-    // to run it should exit
-    void allow_exit();
-    void disallow_exit();
-};
-
-#endif /* RUST_SCHEDULER_H */
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
deleted file mode 100644 (file)
index 2f6b8ac..0000000
+++ /dev/null
@@ -1,742 +0,0 @@
-// 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.
-
-
-#ifndef __WIN32__
-#ifdef __ANDROID__
-#include "rust_android_dummy.h"
-#else
-#include <execinfo.h>
-#endif
-#endif
-#include <iostream>
-#include <algorithm>
-
-#include "rust_task.h"
-#include "rust_env.h"
-#include "rust_globals.h"
-#include "rust_crate_map.h"
-
-// Tasks
-rust_task::rust_task(rust_sched_loop *sched_loop, rust_task_state state,
-                     const char *name, size_t init_stack_sz) :
-    ref_count(1),
-    id(0),
-    stk(NULL),
-    runtime_sp(0),
-    sched(sched_loop->sched),
-    sched_loop(sched_loop),
-    kernel(sched_loop->kernel),
-    name(name),
-    list_index(-1),
-    boxed(&local_region, sched_loop->kernel->env->poison_on_free),
-    local_region(&sched_loop->local_region),
-    unwinding(false),
-    total_stack_sz(0),
-    task_local_data(NULL),
-    task_local_data_cleanup(NULL),
-    borrow_list(NULL),
-    state(state),
-    cond(NULL),
-    cond_name("none"),
-    event_reject(false),
-    event(NULL),
-    killed(false),
-    reentered_rust_stack(false),
-    disallow_kill(0),
-    disallow_yield(0),
-    c_stack(NULL),
-    next_c_sp(0),
-    next_rust_sp(0)
-{
-    LOGPTR(sched_loop, "new task", (uintptr_t)this);
-    DLOG(sched_loop, task, "sizeof(task) = %d (0x%x)",
-         sizeof *this, sizeof *this);
-
-    new_stack(init_stack_sz);
-}
-
-// NB: This does not always run on the task's scheduler thread
-void
-rust_task::delete_this()
-{
-    DLOG(sched_loop, task, "~rust_task %s @0x%" PRIxPTR ", refcnt=%d",
-         name, (uintptr_t)this, ref_count);
-
-    /* FIXME (#2677): tighten this up, there are some more
-       assertions that hold at task-lifecycle events. */
-    assert(ref_count == 0); // ||
-    //   (ref_count == 1 && this == sched->root_task));
-
-    // The borrow list should be freed in the task annihilator
-    assert(!borrow_list);
-
-    sched_loop->release_task(this);
-}
-
-// All failure goes through me. Put your breakpoints here!
-extern "C" void
-rust_task_fail(rust_task *task,
-               char const *expr,
-               char const *file,
-               size_t line) {
-    assert(task != NULL);
-    task->begin_failure(expr, file, line);
-}
-
-struct spawn_args {
-    rust_task *task;
-    spawn_fn f;
-    rust_opaque_box *envptr;
-    void *argptr;
-};
-
-struct cleanup_args {
-    spawn_args *spargs;
-    bool threw_exception;
-};
-
-void
-annihilate_boxes(rust_task *task);
-
-void
-cleanup_task(cleanup_args *args) {
-    spawn_args *a = args->spargs;
-    bool threw_exception = args->threw_exception;
-    rust_task *task = a->task;
-
-    {
-        scoped_lock with(task->lifecycle_lock);
-        if (task->killed && !threw_exception) {
-            LOG(task, task, "Task killed during termination");
-            threw_exception = true;
-        }
-    }
-
-    // Clean up TLS. This will only be set if TLS was used to begin with.
-    // Because this is a crust function, it must be called from the C stack.
-    if (task->task_local_data_cleanup != NULL) {
-        // This assert should hold but it's not our job to ensure it (and
-        // the condition might change). Handled in libcore/task.rs.
-        // assert(task->task_local_data != NULL);
-        task->task_local_data_cleanup(task->task_local_data);
-        task->task_local_data = NULL;
-    } else if (threw_exception && task->id == INIT_TASK_ID) {
-        // Edge case: If main never spawns any tasks, but fails anyway, TLS
-        // won't be around to take down the kernel (task.rs:kill_taskgroup,
-        // rust_task_kill_all). Do it here instead.
-        // (Note that children tasks can not init their TLS if they were
-        // killed too early, so we need to check main's task id too.)
-        task->fail_sched_loop();
-        // This must not happen twice.
-        static bool main_task_failed_without_spawning = false;
-        assert(!main_task_failed_without_spawning);
-        main_task_failed_without_spawning = true;
-    }
-
-    // Call the box annihilator.
-    cratemap* map = reinterpret_cast<cratemap*>(global_crate_map);
-    task->call_on_rust_stack(NULL, const_cast<void*>(map->annihilate_fn()));
-
-    task->die();
-
-#ifdef __WIN32__
-    assert(!threw_exception && "No exception-handling yet on windows builds");
-#endif
-}
-
-// This runs on the Rust stack
-void task_start_wrapper(spawn_args *a)
-{
-    rust_task *task = a->task;
-
-    bool threw_exception = false;
-    try {
-        a->f(a->envptr, a->argptr);
-    } catch (rust_task *ex) {
-        assert(ex == task && "Expected this task to be thrown for unwinding");
-        threw_exception = true;
-
-        if (task->c_stack) {
-            task->return_c_stack();
-        }
-
-        // Since we call glue code below we need to make sure we
-        // have the stack limit set up correctly
-        task->reset_stack_limit();
-    }
-
-    // We should have returned any C stack by now
-    assert(task->c_stack == NULL);
-
-    rust_opaque_box* env = a->envptr;
-    if(env) {
-        // free the environment (which should be a unique closure).
-        const type_desc *td = env->td;
-        td->drop_glue(NULL,
-                      box_body(env));
-        task->kernel->region()->free(env);
-    }
-
-    // The cleanup work needs lots of stack
-    cleanup_args ca = {a, threw_exception};
-    task->call_on_c_stack(&ca, (void*)cleanup_task);
-
-    task->ctx.next->swap(task->ctx);
-}
-
-void
-rust_task::start(spawn_fn spawnee_fn,
-                 rust_opaque_box *envptr,
-                 void *argptr)
-{
-    LOG(this, task, "starting task from fn 0x%" PRIxPTR
-        " with env 0x%" PRIxPTR " and arg 0x%" PRIxPTR,
-        spawnee_fn, envptr, argptr);
-
-    assert(stk->data != NULL);
-
-    char *sp = (char *)stk->end;
-
-    sp -= sizeof(spawn_args);
-
-    spawn_args *a = (spawn_args *)sp;
-
-    a->task = this;
-    a->envptr = envptr;
-    a->argptr = argptr;
-    a->f = spawnee_fn;
-
-    ctx.call((void *)task_start_wrapper, a, sp);
-
-    this->start();
-}
-
-void rust_task::start()
-{
-    transition(task_state_newborn, task_state_running, NULL, "none");
-}
-
-bool
-rust_task::must_fail_from_being_killed() {
-    scoped_lock with(lifecycle_lock);
-    return must_fail_from_being_killed_inner();
-}
-
-bool
-rust_task::must_fail_from_being_killed_inner() {
-    lifecycle_lock.must_have_lock();
-    return killed && !reentered_rust_stack && disallow_kill == 0;
-}
-
-void rust_task_yield_fail(rust_task *task) {
-    LOG_ERR(task, task, "task %" PRIxPTR " yielded in an atomic section",
-            task);
-    task->fail();
-}
-
-// Only run this on the rust stack
-MUST_CHECK bool rust_task::yield() {
-    bool killed = false;
-
-    if (disallow_yield > 0) {
-        call_on_c_stack(this, (void *)rust_task_yield_fail);
-    }
-
-    // This check is largely superfluous; it's the one after the context swap
-    // that really matters. This one allows us to assert a useful invariant.
-
-    // NB: This takes lifecycle_lock three times, and I believe that none of
-    // them are actually necessary, as per #3213. Removing the locks here may
-    // cause *harmless* races with a killer... but I didn't observe any
-    // substantial performance improvement from removing them, even with
-    // msgsend-ring-pipes, and also it's my last day, so I'm not about to
-    // remove them.  -- bblum
-    if (must_fail_from_being_killed()) {
-        {
-            scoped_lock with(lifecycle_lock);
-            assert(!(state == task_state_blocked));
-        }
-        killed = true;
-    }
-
-    // Return to the scheduler.
-    ctx.next->swap(ctx);
-
-    if (must_fail_from_being_killed()) {
-        killed = true;
-    }
-    return killed;
-}
-
-void
-rust_task::kill() {
-    scoped_lock with(lifecycle_lock);
-    kill_inner();
-}
-
-void rust_task::kill_inner() {
-    lifecycle_lock.must_have_lock();
-
-    // Multiple kills should be able to safely race, but check anyway.
-    if (killed) {
-        LOG(this, task, "task %s @0x%" PRIxPTR " already killed", name, this);
-        return;
-    }
-
-    // Note the distinction here: kill() is when you're in an upcall
-    // from task A and want to force-fail task B, you do B->kill().
-    // If you want to fail yourself you do self->fail().
-    LOG(this, task, "killing task %s @0x%" PRIxPTR, name, this);
-    // When the task next goes to yield or resume it will fail
-    killed = true;
-    // Unblock the task so it can unwind.
-
-    if (state == task_state_blocked &&
-        must_fail_from_being_killed_inner()) {
-        wakeup_inner(cond);
-    }
-
-    LOG(this, task, "preparing to unwind task: 0x%" PRIxPTR, this);
-}
-
-void
-rust_task::fail() {
-    // See note in ::kill() regarding who should call this.
-    fail(NULL, NULL, 0);
-}
-
-void
-rust_task::fail(char const *expr, char const *file, size_t line) {
-    rust_task_fail(this, expr, file, line);
-}
-
-// Called only by rust_task_fail
-void
-rust_task::begin_failure(char const *expr, char const *file, size_t line) {
-
-    if (expr) {
-        LOG_ERR(this, task, "task failed at '%s', %s:%" PRIdPTR,
-                expr, file, line);
-    }
-
-    DLOG(sched_loop, task, "task %s @0x%" PRIxPTR " failing", name, this);
-    backtrace();
-    unwinding = true;
-#ifndef __WIN32__
-    throw this;
-#else
-    die();
-    // FIXME (#908): Need unwinding on windows. This will end up aborting
-    fail_sched_loop();
-#endif
-}
-
-void rust_task::fail_sched_loop() {
-    sched_loop->fail();
-}
-
-void rust_task::assert_is_running()
-{
-    scoped_lock with(lifecycle_lock);
-    assert(state == task_state_running);
-}
-
-// FIXME (#2851) Remove this code when rust_port goes away?
-bool
-rust_task::blocked_on(rust_cond *on)
-{
-    lifecycle_lock.must_have_lock();
-    return cond == on;
-}
-
-void *
-rust_task::malloc(size_t sz, const char *tag, type_desc *td)
-{
-    return local_region.malloc(sz, tag);
-}
-
-void *
-rust_task::realloc(void *data, size_t sz)
-{
-    return local_region.realloc(data, sz);
-}
-
-void
-rust_task::free(void *p)
-{
-    local_region.free(p);
-}
-
-void
-rust_task::transition(rust_task_state src, rust_task_state dst,
-                      rust_cond *cond, const char* cond_name) {
-    scoped_lock with(lifecycle_lock);
-    transition_inner(src, dst, cond, cond_name);
-}
-
-void rust_task::transition_inner(rust_task_state src, rust_task_state dst,
-                                  rust_cond *cond, const char* cond_name) {
-    lifecycle_lock.must_have_lock();
-    sched_loop->transition(this, src, dst, cond, cond_name);
-}
-
-void
-rust_task::set_state(rust_task_state state,
-                     rust_cond *cond, const char* cond_name) {
-    lifecycle_lock.must_have_lock();
-    this->state = state;
-    this->cond = cond;
-    this->cond_name = cond_name;
-}
-
-bool
-rust_task::block(rust_cond *on, const char* name) {
-    scoped_lock with(lifecycle_lock);
-    return block_inner(on, name);
-}
-
-bool
-rust_task::block_inner(rust_cond *on, const char* name) {
-    if (must_fail_from_being_killed_inner()) {
-        // We're already going to die. Don't block. Tell the task to fail
-        return false;
-    }
-
-    LOG(this, task, "Blocking on 0x%" PRIxPTR ", cond: 0x%" PRIxPTR,
-                         (uintptr_t) on, (uintptr_t) cond);
-    assert(cond == NULL && "Cannot block an already blocked task.");
-    assert(on != NULL && "Cannot block on a NULL object.");
-
-    transition_inner(task_state_running, task_state_blocked, on, name);
-
-    return true;
-}
-
-void
-rust_task::wakeup(rust_cond *from) {
-    scoped_lock with(lifecycle_lock);
-    wakeup_inner(from);
-}
-
-void
-rust_task::wakeup_inner(rust_cond *from) {
-    assert(cond != NULL && "Cannot wake up unblocked task.");
-    LOG(this, task, "Blocked on 0x%" PRIxPTR " woken up on 0x%" PRIxPTR,
-                        (uintptr_t) cond, (uintptr_t) from);
-    assert(cond == from && "Cannot wake up blocked task on wrong condition.");
-
-    transition_inner(task_state_blocked, task_state_running, NULL, "none");
-}
-
-void
-rust_task::die() {
-    transition(task_state_running, task_state_dead, NULL, "none");
-}
-
-void
-rust_task::backtrace() {
-    if (log_rt_backtrace <= log_err) return;
-#ifndef __WIN32__
-    void *call_stack[256];
-    int nframes = ::backtrace(call_stack, 256);
-    backtrace_symbols_fd(call_stack + 1, nframes - 1, 2);
-#endif
-}
-
-size_t
-rust_task::get_next_stack_size(size_t min, size_t current, size_t requested) {
-    LOG(this, mem, "calculating new stack size for 0x%" PRIxPTR, this);
-    LOG(this, mem,
-        "min: %" PRIdPTR " current: %" PRIdPTR " requested: %" PRIdPTR,
-        min, current, requested);
-
-    // Allocate at least enough to accomodate the next frame, plus a little
-    // slack to avoid thrashing
-    size_t sz = std::max(min, requested + (requested / 2));
-
-    // And double the stack size each allocation
-    const size_t max = 1024 * 1024;
-    size_t next = std::min(max, current * 2);
-
-    sz = std::max(sz, next);
-
-    LOG(this, mem, "next stack size: %" PRIdPTR, sz);
-    assert(requested <= sz);
-    return sz;
-}
-
-void
-rust_task::free_stack(stk_seg *stk) {
-    LOGPTR(sched_loop, "freeing stk segment", (uintptr_t)stk);
-    total_stack_sz -= user_stack_size(stk);
-    destroy_stack(&local_region, stk);
-}
-
-void
-new_stack_slow(new_stack_args *args) {
-    args->task->new_stack(args->requested_sz);
-}
-
-void
-rust_task::new_stack(size_t requested_sz) {
-    LOG(this, mem, "creating new stack for task %" PRIxPTR, this);
-    if (stk) {
-        ::check_stack_canary(stk);
-    }
-
-    // The minimum stack size, in bytes, of a Rust stack, excluding red zone
-    size_t min_sz = sched_loop->min_stack_size;
-
-    // Try to reuse an existing stack segment
-    while (stk != NULL && stk->next != NULL) {
-        size_t next_sz = user_stack_size(stk->next);
-        if (min_sz <= next_sz && requested_sz <= next_sz) {
-            LOG(this, mem, "reusing existing stack");
-            stk = stk->next;
-            return;
-        } else {
-            LOG(this, mem, "existing stack is not big enough");
-            stk_seg *new_next = stk->next->next;
-            free_stack(stk->next);
-            stk->next = new_next;
-            if (new_next) {
-                new_next->prev = stk;
-            }
-        }
-    }
-
-    // The size of the current stack segment, excluding red zone
-    size_t current_sz = 0;
-    if (stk != NULL) {
-        current_sz = user_stack_size(stk);
-    }
-    // The calculated size of the new stack, excluding red zone
-    size_t rust_stk_sz = get_next_stack_size(min_sz,
-                                             current_sz, requested_sz);
-
-    size_t max_stack = kernel->env->max_stack_size;
-    size_t used_stack = total_stack_sz + rust_stk_sz;
-
-    // Don't allow stacks to grow forever. During unwinding we have to allow
-    // for more stack than normal in order to allow destructors room to run,
-    // arbitrarily selected as 2x the maximum stack size.
-    if (!unwinding && used_stack > max_stack) {
-        LOG_ERR(this, task, "task %" PRIxPTR " ran out of stack", this);
-        abort();
-    } else if (unwinding && used_stack > max_stack * 2) {
-        LOG_ERR(this, task,
-                "task %" PRIxPTR " ran out of stack during unwinding", this);
-        abort();
-    }
-
-    size_t sz = rust_stk_sz + RED_ZONE_SIZE;
-    stk_seg *new_stk = create_stack(&local_region, sz);
-    LOGPTR(sched_loop, "new stk", (uintptr_t)new_stk);
-    new_stk->task = this;
-    new_stk->next = NULL;
-    new_stk->prev = stk;
-    if (stk) {
-        stk->next = new_stk;
-    }
-    LOGPTR(sched_loop, "stk end", new_stk->end);
-
-    stk = new_stk;
-    total_stack_sz += user_stack_size(new_stk);
-}
-
-void
-rust_task::cleanup_after_turn() {
-    // Delete any spare stack segments that were left
-    // behind by calls to prev_stack
-    assert(stk);
-
-    while (stk->next) {
-        stk_seg *new_next = stk->next->next;
-        assert (!stk->next->is_big);
-        free_stack(stk->next);
-
-        stk->next = new_next;
-    }
-}
-
-// NB: Runs on the Rust stack. Returns true if we successfully allocated the big
-// stack and false otherwise.
-bool
-rust_task::new_big_stack() {
-    assert(stk);
-
-    stk_seg *borrowed_big_stack = sched_loop->borrow_big_stack();
-    if (!borrowed_big_stack) {
-        return false;
-    }
-
-    borrowed_big_stack->task = this;
-    borrowed_big_stack->next = stk->next;
-    if (borrowed_big_stack->next)
-        borrowed_big_stack->next->prev = borrowed_big_stack;
-    borrowed_big_stack->prev = stk;
-    stk->next = borrowed_big_stack;
-
-    stk = borrowed_big_stack;
-
-    return true;
-}
-
-static bool
-sp_in_stk_seg(uintptr_t sp, stk_seg *stk) {
-    // Not positive these bounds for sp are correct.  I think that the first
-    // possible value for esp on a new stack is stk->end, which points to the
-    // address before the first value to be pushed onto a new stack. The last
-    // possible address we can push data to is stk->data.  Regardless, there's
-    // so much slop at either end that we should never hit one of these
-    // boundaries.
-    return (uintptr_t)stk->data <= sp && sp <= stk->end;
-}
-
-/*
-Called by landing pads during unwinding to figure out which stack segment we
-are currently running on and record the stack limit (which was not restored
-when unwinding through __morestack).
- */
-void
-rust_task::reset_stack_limit() {
-    uintptr_t sp = get_sp();
-    bool reseted = false;
-    while (!sp_in_stk_seg(sp, stk)) {
-        reseted = true;
-        prev_stack();
-        assert(stk != NULL && "Failed to find the current stack");
-    }
-
-    // Each call to prev_stack will record the stack limit. If we *didn't*
-    // call prev_stack then we still need to record it now to catch a corner case:
-    // the throw to initiate unwinding starts on the C stack while sp limit is 0.
-    // If we don't set the limit here then the rust code run subsequently will
-    // will veer into the red zone. Lame!
-    if (!reseted) {
-        record_stack_limit();
-    }
-}
-
-void
-rust_task::check_stack_canary() {
-    ::check_stack_canary(stk);
-}
-
-void
-rust_task::delete_all_stacks() {
-    assert(!on_rust_stack());
-    // Delete all the stacks. There may be more than one if the task failed
-    // and no landing pads stopped to clean up.
-    assert(stk->next == NULL);
-    while (stk != NULL) {
-        stk_seg *prev = stk->prev;
-
-        if (stk->is_big)
-            sched_loop->return_big_stack(stk);
-        else
-            free_stack(stk);
-
-        stk = prev;
-    }
-}
-
-/*
-Returns true if we're currently running on the Rust stack
- */
-bool
-rust_task::on_rust_stack() {
-    if (stk == NULL) {
-        // This only happens during construction
-        return false;
-    }
-
-    uintptr_t sp = get_sp();
-    bool in_first_segment = sp_in_stk_seg(sp, stk);
-    if (in_first_segment) {
-        return true;
-    } else if (stk->prev != NULL) {
-        // This happens only when calling the upcall to delete
-        // a stack segment
-        bool in_second_segment = sp_in_stk_seg(sp, stk->prev);
-        return in_second_segment;
-    } else {
-        return false;
-    }
-}
-
-// NB: In inhibit_kill and allow_kill, helgrind would complain that we need to
-// hold lifecycle_lock while accessing disallow_kill. Even though another
-// killing task may access disallow_kill concurrently, this is not racy
-// because the killer only cares if this task is blocking, and block() already
-// uses proper locking. See https://github.com/mozilla/rust/issues/3213 .
-
-void
-rust_task::inhibit_kill() {
-    // Here might be good, though not mandatory, to check if we have to die.
-    disallow_kill++;
-}
-
-void
-rust_task::allow_kill() {
-    assert(disallow_kill > 0 && "Illegal allow_kill(): already killable!");
-    disallow_kill--;
-}
-
-void rust_task::inhibit_yield() {
-    disallow_yield++;
-}
-
-void rust_task::allow_yield() {
-    assert(disallow_yield > 0 && "Illegal allow_yield(): already yieldable!");
-    disallow_yield--;
-}
-
-MUST_CHECK bool rust_task::wait_event(void **result) {
-    bool killed = false;
-    scoped_lock with(lifecycle_lock);
-
-    if(!event_reject) {
-        block_inner(&event_cond, "waiting on event");
-        lifecycle_lock.unlock();
-        killed = yield();
-        lifecycle_lock.lock();
-    } else if (must_fail_from_being_killed_inner()) {
-        // If the deschedule was rejected, yield won't do our killed check for
-        // us. For thoroughness, do it here. FIXME (#524)
-        killed = true;
-    }
-
-    event_reject = false;
-    *result = event;
-    return killed;
-}
-
-void
-rust_task::signal_event(void *event) {
-    scoped_lock with(lifecycle_lock);
-
-    this->event = event;
-    event_reject = true;
-    if(task_state_blocked == state) {
-        wakeup_inner(&event_cond);
-    }
-}
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h
deleted file mode 100644 (file)
index 1735d35..0000000
+++ /dev/null
@@ -1,681 +0,0 @@
-// 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.
-
-/**
-   The rust task is a cooperatively-scheduled green thread that executes
-   Rust code on a segmented stack.
-
-   This class has too many responsibilities:
-
-   * Working with the scheduler loop to signal and respond to state changes,
-   and dealing with all the thread synchronization issues involved
-
-   * Managing the dynamically resizing list of Rust stack segments
-
-   * Switching between running Rust code on the Rust segmented stack and
-   foreign C code on large stacks owned by the scheduler
-
-   # Lifetime
-
-   The lifetime of a rust_task object closely mirrors that of a running Rust
-   task object, but they are not identical. In particular, the rust_task is an
-   atomically reference counted object that might be accessed from arbitrary
-   threads at any time. This may keep the task from being destroyed even after
-   the task is dead from a Rust task lifecycle perspective. The rust_tasks are
-   reference counted in the following places:
-
-   * By the task's lifetime (i.e., running tasks hold a reference to themself)
-
-   * In the rust_task_kill_all -> rust_kernel::fail ->
-     rust_sched_loop::kill_all_tasks path. When a task brings down the whole
-     runtime, each sched_loop must use refcounts to take a 'snapshot' of all
-     existing tasks so it can be sure to kill all of them.
-
-   * In core::pipes, tasks that use select() use reference counts to avoid
-     use-after-free races with multiple different signallers.
-
-   # Death
-
-   All task death goes through a single central path: The task invokes
-   rust_task::die(), which invokes transition(task_state_dead), which pumps
-   the scheduler loop, which switches to rust_sched_loop::run_single_turn(),
-   which calls reap_dead_tasks(), which cleans up the task's stack segments
-   and drops the reference count.
-
-   When a task's reference count hits zero, rust_sched_loop::release_task()
-   is called. This frees the memory and deregisters the task from the kernel,
-   which may trigger the sched_loop, the scheduler, and/or the kernel to exit
-   completely in the case it was the last task alive.
-
-   die() is called from two places: the successful exit path, in cleanup_task,
-   and on failure (on linux, this is also in cleanup_task, after unwinding
-   completes; on windows, it is in begin_failure).
-
-   Tasks do not force-quit other tasks; a task die()s only itself. However...
-
-   # Killing
-
-   Tasks may kill each other. This happens when propagating failure between
-   tasks (see the task::spawn options interface). The code path for this is
-   rust_task_kill_other() -> rust_task::kill().
-
-   It also happens when the main ("root") task (or any task in that task's
-   linked-failure-group) fails: this brings down the whole runtime, and kills
-   all tasks in all groups. The code path for this is rust_task_kill_all() ->
-   rust_kernel::fail() -> rust_scheduler::kill_all_tasks() ->
-   rust_sched_loop::kill_all_tasks() -> rust_task::kill().
-
-   In either case, killing a task involves, under the protection of its
-   lifecycle_lock, (a) setting the 'killed' flag, and (b) checking if it is
-   'blocked'* and if so punting it awake.
-   (* and also isn't unkillable, which may happen via task::unkillable()
-   or via calling an extern rust function from C.)
-
-   The killed task will then (wake up if it was asleep, and) eventually call
-   yield() (or wait_event()), which will check the killed flag, see that it is
-   true, and then invoke 'fail', which begins the death process described
-   above.
-
-   Three things guarantee concurrency safety in this whole affair:
-
-   * The lifecycle_lock protects tasks accessing each other's state: it makes
-     killing-and-waking up atomic with respect to a task in block() deciding
-     whether it's allowed to go to sleep, so tasks can't 'escape' being woken.
-
-   * In the case of linked failure propagation, we ensure (in task.rs) that
-     tasks can only see another task's rust_task pointer if that task is
-     already alive. Even before entering the runtime failure path, a task will
-     access (locked) the linked-failure data structures to remove its task
-     pointer so that no subsequently-failing tasks will do a use-after-free.
-
-   * In the case of bringing down the whole runtime, each sched_loop takes an
-     "atomic snapshot" of all its tasks, protected by the sched_loop's lock,
-     and also sets a 'failing' flag so that any subsequently-failing task will
-     know that it must fail immediately upon creation (which is also checked
-     under the same lock). A similar process exists at the one-step-higher
-     level of the kernel killing all the schedulers (the kernel snapshots all
-     the schedulers and sets a 'failing' flag in the scheduler table).
- */
-
-#ifndef RUST_TASK_H
-#define RUST_TASK_H
-
-#include <map>
-
-#include "rust_globals.h"
-#include "util/array_list.h"
-#include "context.h"
-#include "rust_debug.h"
-#include "rust_kernel.h"
-#include "boxed_region.h"
-#include "rust_stack.h"
-#include "rust_type.h"
-#include "rust_sched_loop.h"
-#include "sp.h"
-
-// The amount of extra space at the end of each stack segment, available
-// to the rt, compiler and dynamic linker for running small functions
-// FIXME (#1509): We want this to be 128 but need to slim the red zone calls
-// down, disable lazy symbol relocation, and other things we haven't
-// discovered yet
-#define RZ_LINUX_32 (1024*2)
-#define RZ_LINUX_64 (1024*2)
-#define RZ_MAC_32   (1024*20)
-#define RZ_MAC_64   (1024*20)
-#define RZ_WIN_32   (1024*20)
-#define RZ_BSD_32   (1024*20)
-#define RZ_BSD_64   (1024*20)
-
-// The threshold beyond which we switch to the C stack.
-#define STACK_THRESHOLD (1024 * 1024)
-
-#ifdef __linux__
-#ifdef __i386__
-#define RED_ZONE_SIZE RZ_LINUX_32
-#endif
-#ifdef __x86_64__
-#define RED_ZONE_SIZE RZ_LINUX_64
-#endif
-#ifdef __mips__
-#define RED_ZONE_SIZE RZ_MAC_32
-#endif
-#ifdef __arm__
-#define RED_ZONE_SIZE RZ_LINUX_32
-#endif
-#endif
-#ifdef __APPLE__
-#ifdef __i386__
-#define RED_ZONE_SIZE RZ_MAC_32
-#endif
-#ifdef __x86_64__
-#define RED_ZONE_SIZE RZ_MAC_64
-#endif
-#endif
-#ifdef __WIN32__
-#ifdef __i386__
-#define RED_ZONE_SIZE RZ_WIN_32
-#endif
-#ifdef __x86_64__
-#define RED_ZONE_SIZE RZ_WIN_64
-#endif
-#endif
-#ifdef __FreeBSD__
-#ifdef __i386__
-#define RED_ZONE_SIZE RZ_BSD_32
-#endif
-#ifdef __x86_64__
-#define RED_ZONE_SIZE RZ_BSD_64
-#endif
-#endif
-#ifdef __ANDROID__
-#define RED_ZONE_SIZE RZ_MAC_32
-#endif
-
-#ifndef RED_ZONE_SIZE
-# error "Red zone not defined for this platform"
-#endif
-
-struct frame_glue_fns {
-    uintptr_t mark_glue_off;
-    uintptr_t drop_glue_off;
-    uintptr_t reloc_glue_off;
-};
-
-// std::lib::task::task_result
-typedef unsigned long task_result;
-#define tr_success 0
-#define tr_failure 1
-
-struct spawn_args;
-struct cleanup_args;
-struct reset_args;
-struct new_stack_args;
-
-// std::lib::task::task_notification
-//
-// since it's currently a unary tag, we only add the fields.
-struct task_notification {
-    rust_task_id id;
-    task_result result; // task_result
-};
-
-extern "C" void
-rust_task_fail(rust_task *task,
-               char const *expr,
-               char const *file,
-               size_t line);
-
-struct
-rust_task : public kernel_owned<rust_task>
-{
-    RUST_ATOMIC_REFCOUNT();
-
-    rust_task_id id;
-
-    context ctx;
-    stk_seg *stk;
-    uintptr_t runtime_sp;      // Runtime sp while task running.
-    rust_scheduler *sched;
-    rust_sched_loop *sched_loop;
-
-    // Fields known only to the runtime.
-    rust_kernel *kernel;
-    const char *const name;
-    int32_t list_index;
-
-    boxed_region boxed;
-    memory_region local_region;
-
-    // Indicates that fail() has been called and we are cleaning up.
-    // We use this to suppress the "killed" flag during calls to yield.
-    bool unwinding;
-
-    bool propagate_failure;
-
-    debug::task_debug_info debug;
-
-    // The amount of stack we're using, excluding red zones
-    size_t total_stack_sz;
-
-    // Used by rust task management routines in libcore/task.rs.
-    void *task_local_data;
-    void (*task_local_data_cleanup)(void *data);
-
-    // Contains a ~[BorrowRecord] pointer, or NULL.
-    //
-    // Used by borrow management code in libcore/unstable/lang.rs.
-    void *borrow_list;
-
-private:
-
-    // Protects state, cond, cond_name
-    // Protects the killed flag, disallow_kill flag, reentered_rust_stack
-    lock_and_signal lifecycle_lock;
-    rust_task_state state;
-    rust_cond *cond;
-    const char *cond_name;
-
-    bool event_reject;
-    rust_cond event_cond;
-    void *event;
-
-    // Indicates that the task was killed and needs to unwind
-    bool killed;
-    // Indicates that we've called back into Rust from C
-    bool reentered_rust_stack;
-    unsigned long disallow_kill;
-    unsigned long disallow_yield;
-
-    // The stack used for running C code, borrowed from the scheduler thread
-    stk_seg *c_stack;
-    uintptr_t next_c_sp;
-    uintptr_t next_rust_sp;
-
-    // Called when the atomic refcount reaches zero
-    void delete_this();
-
-    bool new_big_stack();
-    void new_stack_fast(size_t requested_sz);
-    void new_stack(size_t requested_sz);
-    void free_stack(stk_seg *stk);
-    size_t get_next_stack_size(size_t min, size_t current, size_t requested);
-
-    void return_c_stack();
-
-    void transition(rust_task_state src, rust_task_state dst,
-                    rust_cond *cond, const char* cond_name);
-    void transition_inner(rust_task_state src, rust_task_state dst,
-                           rust_cond *cond, const char* cond_name);
-
-    bool must_fail_from_being_killed_inner();
-    // Called by rust_task_fail to unwind on failure
-    void begin_failure(char const *expr,
-                       char const *file,
-                       size_t line);
-
-    friend void task_start_wrapper(spawn_args *a);
-    friend void cleanup_task(cleanup_args *a);
-    friend void reset_stack_limit_on_c_stack(reset_args *a);
-    friend void new_stack_slow(new_stack_args *a);
-    friend void rust_task_fail(rust_task *task,
-                               char const *expr,
-                               char const *file,
-                               size_t line);
-
-    bool block_inner(rust_cond *on, const char* name);
-    void wakeup_inner(rust_cond *from);
-    bool blocked_on(rust_cond *cond);
-
-private:
-    // private and undefined to disable copying
-    rust_task(const rust_task& rhs);
-    rust_task& operator=(const rust_task& rhs);
-
-public:
-
-    // Only a pointer to 'name' is kept, so it must live as long as this task.
-    rust_task(rust_sched_loop *sched_loop,
-              rust_task_state state,
-              const char *name,
-              size_t init_stack_sz);
-
-    void start(spawn_fn spawnee_fn,
-               rust_opaque_box *env,
-               void *args);
-    void start();
-    void assert_is_running();
-
-    void *malloc(size_t sz, const char *tag, type_desc *td=0);
-    void *realloc(void *data, size_t sz);
-    void free(void *p);
-
-    void set_state(rust_task_state state,
-                   rust_cond *cond, const char* cond_name);
-
-    bool block(rust_cond *on, const char* name);
-    void wakeup(rust_cond *from);
-    void die();
-
-    // Print a backtrace, if the "bt" logging option is on.
-    void backtrace();
-
-    // Yields control to the scheduler. Called from the Rust stack
-    // Returns TRUE if the task was killed and needs to fail.
-    MUST_CHECK bool yield();
-
-    // Fail this task (assuming caller-on-stack is different task).
-    void kill();
-    void kill_inner();
-
-    // Indicates that we've been killed and now is an apropriate
-    // time to fail as a result
-    bool must_fail_from_being_killed();
-
-    // Fail self, assuming caller-on-stack is this task.
-    void fail();
-    void fail(char const *expr, char const *file, size_t line);
-
-    // Propagate failure to the entire rust runtime.
-    void fail_sched_loop();
-
-    void *calloc(size_t size, const char *tag);
-
-    // Use this function sparingly. Depending on the ref count is generally
-    // not at all safe.
-    intptr_t get_ref_count() const { return ref_count; }
-
-    void *next_stack(size_t stk_sz, void *args_addr, size_t args_sz);
-    void prev_stack();
-    void record_stack_limit();
-    void reset_stack_limit();
-
-    bool on_rust_stack();
-    void check_stack_canary();
-    void delete_all_stacks();
-
-    void call_on_c_stack(void *args, void *fn_ptr);
-    void call_on_rust_stack(void *args, void *fn_ptr);
-    bool have_c_stack() { return c_stack != NULL; }
-    stk_seg *get_c_stack() { return c_stack; }
-
-    rust_task_state get_state() { return state; }
-    rust_cond *get_cond() { return cond; }
-    const char *get_cond_name() { return cond_name; }
-
-    void clear_event_reject() {
-        this->event_reject = false;
-    }
-
-    // Returns TRUE if the task was killed and needs to fail.
-    MUST_CHECK bool wait_event(void **result);
-    void signal_event(void *event);
-
-    void cleanup_after_turn();
-
-    void inhibit_kill();
-    void allow_kill();
-    void inhibit_yield();
-    void allow_yield();
-};
-
-template <typename T> struct task_owned {
-    inline void *operator new(size_t size, rust_task *task,
-                                             const char *tag) {
-        return task->malloc(size, tag);
-    }
-
-    inline void *operator new[](size_t size, rust_task *task,
-                                               const char *tag) {
-        return task->malloc(size, tag);
-    }
-
-    inline void *operator new(size_t size, rust_task &task,
-                                             const char *tag) {
-        return task.malloc(size, tag);
-    }
-
-    inline void *operator new[](size_t size, rust_task &task,
-                                               const char *tag) {
-        return task.malloc(size, tag);
-    }
-
-    void operator delete(void *ptr) {
-        ((T *)ptr)->task->free(ptr);
-    }
-};
-
-// This is the function that switches between the C and the Rust stack by
-// calling another function with a single void* argument while changing the
-// stack pointer. It has a funny name because gdb doesn't normally like to
-// backtrace through split stacks (thinks it indicates a bug), but has a
-// special case to allow functions named __morestack to move the stack pointer
-// around.
-extern "C" void __morestack(void *args, void *fn_ptr, uintptr_t stack_ptr);
-
-inline static uintptr_t
-sanitize_next_sp(uintptr_t next_sp) {
-
-    // Since I'm not precisely sure where the next stack pointer sits in
-    // relation to where the context switch actually happened, nor in relation
-    // to the amount of stack needed for calling __morestack I've added some
-    // extra bytes here.
-
-    // FIXME (#2698): On the rust stack this potentially puts is quite far
-    // into the red zone. Might want to just allocate a new rust stack every
-    // time we switch back to rust.
-    const uintptr_t padding = 16;
-
-    return align_down(next_sp - padding);
-}
-
-inline void
-rust_task::call_on_c_stack(void *args, void *fn_ptr) {
-    // Too expensive to check
-    // assert(on_rust_stack());
-
-    // The shim functions generated by rustc contain the morestack prologue,
-    // so we need to let them know they have enough stack.
-    record_sp_limit(0);
-
-    uintptr_t prev_rust_sp = next_rust_sp;
-    next_rust_sp = get_sp();
-
-    bool borrowed_a_c_stack = false;
-    uintptr_t sp;
-    if (c_stack == NULL) {
-        c_stack = sched_loop->borrow_c_stack();
-        next_c_sp = align_down(c_stack->end);
-        sp = next_c_sp;
-        borrowed_a_c_stack = true;
-    } else {
-        sp = sanitize_next_sp(next_c_sp);
-    }
-
-    __morestack(args, fn_ptr, sp);
-
-    // Note that we may not actually get here if we threw an exception,
-    // in which case we will return the c stack when the exception is caught.
-    if (borrowed_a_c_stack) {
-        return_c_stack();
-    }
-
-    next_rust_sp = prev_rust_sp;
-
-    record_stack_limit();
-}
-
-inline void
-rust_task::call_on_rust_stack(void *args, void *fn_ptr) {
-    // Too expensive to check
-    // assert(!on_rust_stack());
-
-    // Because of the hack in the other function that disables the stack limit
-    // when entering the C stack, here we restore the stack limit again.
-    record_stack_limit();
-
-    assert(get_sp_limit() != 0 && "Stack must be configured");
-    assert(next_rust_sp);
-
-    // Unlocked access. Might "race" a killer, but harmlessly. This code is
-    // only run by the task itself, so cannot race itself. See the comment
-    // above inhibit_kill (or #3213) in rust_task.cpp for justification.
-    bool had_reentered_rust_stack = reentered_rust_stack;
-    reentered_rust_stack = true;
-
-    uintptr_t prev_c_sp = next_c_sp;
-    next_c_sp = get_sp();
-
-    uintptr_t sp = sanitize_next_sp(next_rust_sp);
-
-    // FIXME (#2047): There are times when this is called and needs
-    // to be able to throw, and we don't account for that.
-    __morestack(args, fn_ptr, sp);
-
-    next_c_sp = prev_c_sp;
-    reentered_rust_stack = had_reentered_rust_stack;
-
-    record_sp_limit(0);
-}
-
-inline void
-rust_task::return_c_stack() {
-    // Too expensive to check
-    // assert(on_rust_stack());
-    assert(c_stack != NULL);
-    sched_loop->return_c_stack(c_stack);
-    c_stack = NULL;
-    next_c_sp = 0;
-}
-
-// NB: This runs on the Rust stack
-inline void *
-rust_task::next_stack(size_t stk_sz, void *args_addr, size_t args_sz) {
-    new_stack_fast(stk_sz + args_sz);
-    assert(stk->end - (uintptr_t)stk->data >= stk_sz + args_sz
-      && "Did not receive enough stack");
-    uint8_t *new_sp = (uint8_t*)stk->end;
-    // Push the function arguments to the new stack
-    new_sp = align_down(new_sp - args_sz);
-
-    // I don't know exactly where the region ends that valgrind needs us
-    // to mark accessible. On x86_64 these extra bytes aren't needed, but
-    // on i386 we get errors without.
-    const int fudge_bytes = 16;
-    reuse_valgrind_stack(stk, new_sp - fudge_bytes);
-
-    memcpy(new_sp, args_addr, args_sz);
-    record_stack_limit();
-    return new_sp;
-}
-
-// The amount of stack in a segment available to Rust code
-inline size_t
-user_stack_size(stk_seg *stk) {
-    return (size_t)(stk->end
-                    - (uintptr_t)&stk->data[0]
-                    - RED_ZONE_SIZE);
-}
-
-struct new_stack_args {
-    rust_task *task;
-    size_t requested_sz;
-};
-
-void
-new_stack_slow(new_stack_args *args);
-
-// NB: This runs on the Rust stack
-// This is the new stack fast path, in which we
-// reuse the next cached stack segment
-inline void
-rust_task::new_stack_fast(size_t requested_sz) {
-    // The minimum stack size, in bytes, of a Rust stack, excluding red zone
-    size_t min_sz = sched_loop->min_stack_size;
-
-    if (requested_sz > STACK_THRESHOLD) {
-        if (new_big_stack())
-            return;
-    }
-
-    // Try to reuse an existing stack segment
-    if (stk != NULL && stk->next != NULL) {
-        size_t next_sz = user_stack_size(stk->next);
-        if (min_sz <= next_sz && requested_sz <= next_sz) {
-            stk = stk->next;
-            return;
-        }
-    }
-
-    new_stack_args args = {this, requested_sz};
-    call_on_c_stack(&args, (void*)new_stack_slow);
-}
-
-// NB: This runs on the Rust stack
-inline void
-rust_task::prev_stack() {
-    // We're not going to actually delete anything now because that would
-    // require switching to the C stack and be costly. Instead we'll just move
-    // up the link list and clean up later, either in new_stack or after our
-    // turn ends on the scheduler.
-    if (stk->is_big) {
-        stk_seg *ss = stk;
-        stk = stk->prev;
-
-        // Unlink the big stack.
-        if (ss->next)
-            ss->next->prev = ss->prev;
-        if (ss->prev)
-            ss->prev->next = ss->next;
-
-        sched_loop->return_big_stack(ss);
-    } else {
-        stk = stk->prev;
-    }
-
-    record_stack_limit();
-}
-
-// The LLVM-generated segmented-stack function prolog compares the amount of
-// stack needed for each frame to the end-of-stack pointer stored in the
-// TCB. As an optimization, when the frame size is less than 256 bytes, it
-// will simply compare %esp to the stack limit instead of subtracting the
-// frame size. As a result we need our stack limit to account for those 256
-// bytes.
-const unsigned LIMIT_OFFSET = 256;
-
-inline void
-rust_task::record_stack_limit() {
-    assert(stk);
-    assert((uintptr_t)stk->end - RED_ZONE_SIZE
-      - (uintptr_t)stk->data >= LIMIT_OFFSET
-           && "Stack size must be greater than LIMIT_OFFSET");
-    record_sp_limit(stk->data + LIMIT_OFFSET + RED_ZONE_SIZE);
-}
-
-inline rust_task* rust_try_get_current_task() {
-    uintptr_t sp_limit = get_sp_limit();
-
-    // FIXME (#1226) - Because of a hack in upcall_call_shim_on_c_stack this
-    // value is sometimes inconveniently set to 0, so we can't use this
-    // method of retreiving the task pointer and need to fall back to TLS.
-    if (sp_limit == 0)
-        return rust_sched_loop::try_get_task_tls();
-
-    // The stack pointer boundary is stored in a quickly-accessible location
-    // in the TCB. From that we can calculate the address of the stack segment
-    // structure it belongs to, and in that structure is a pointer to the task
-    // that owns it.
-    uintptr_t seg_addr =
-        sp_limit - RED_ZONE_SIZE - LIMIT_OFFSET - sizeof(stk_seg);
-    stk_seg *stk = (stk_seg*) seg_addr;
-
-    // Make sure we've calculated the right address
-    ::check_stack_canary(stk);
-    assert(stk->task != NULL && "task pointer not in stack structure");
-    return stk->task;
-}
-
-inline rust_task* rust_get_current_task() {
-    rust_task* task = rust_try_get_current_task();
-    assert(task != NULL && "no current task");
-    return task;
-}
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
-
-#endif /* RUST_TASK_H */
index 492874a0c26fb28c11cee3a2725be242427fa29c..b0aab9672ea8f2b64109c93aa208ddf9ff7c6a8b 100644 (file)
 
 // Helper functions used only in tests
 
-#include "rust_sched_loop.h"
-#include "rust_task.h"
 #include "rust_util.h"
-#include "rust_scheduler.h"
 #include "sync/timer.h"
 #include "sync/rust_thread.h"
+#include "sync/lock_and_signal.h"
 #include "rust_abi.h"
 
 // These functions are used in the unit tests for C ABI calls.
index c011219ade8b4438ac67a7fc6ecc60bb38ff7d27..f1b31e89df8ca0c219810832b1d75a155a402220 100644 (file)
@@ -17,8 +17,6 @@
  */
 
 #include "rust_globals.h"
-#include "rust_task.h"
-#include "rust_sched_loop.h"
 #include "rust_upcall.h"
 #include "rust_util.h"
 
@@ -29,28 +27,6 @@ typedef int _Unwind_Action;
 struct _Unwind_Context;
 struct _Unwind_Exception;
 
-#ifdef __GNUC__
-#define LOG_UPCALL_ENTRY(task)                            \
-    LOG(task, upcall,                                     \
-        "> UPCALL %s - task: %s 0x%" PRIxPTR              \
-        " retpc: x%" PRIxPTR,                             \
-        __FUNCTION__,                                     \
-        (task)->name, (task),                             \
-        __builtin_return_address(0));
-#else
-#define LOG_UPCALL_ENTRY(task)                            \
-    LOG(task, upcall, "> UPCALL task: %s @x%" PRIxPTR,    \
-        (task)->name, (task));
-#endif
-
-#define UPCALL_SWITCH_STACK(T, A, F) \
-    call_upcall_on_c_stack(T, (void*)A, (void*)F)
-
-inline void
-call_upcall_on_c_stack(rust_task *task, void *args, void *fn_ptr) {
-    task->call_on_c_stack(args, fn_ptr);
-}
-
 typedef void (*CDECL stack_switch_shim)(void*);
 
 /**********************************************************************
@@ -62,21 +38,8 @@ typedef void (*CDECL stack_switch_shim)(void*);
  */
 extern "C" CDECL void
 upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
-    rust_task *task = rust_try_get_current_task();
-
-    if (task) {
-        // We're running in task context, do a stack switch
-        try {
-            task->call_on_c_stack(args, fn_ptr);
-        } catch (...) {
-            // Logging here is not reliable
-            assert(false && "Foreign code threw an exception");
-        }
-    } else {
-        // There's no task. Call the function and hope for the best
-        stack_switch_shim f = (stack_switch_shim)fn_ptr;
-        f(args);
-    }
+    stack_switch_shim f = (stack_switch_shim)fn_ptr;
+    f(args);
 }
 
 /*
@@ -85,171 +48,9 @@ upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
  */
 extern "C" CDECL void
 upcall_call_shim_on_rust_stack(void *args, void *fn_ptr) {
-    rust_task *task = rust_try_get_current_task();
-
-    if (task) {
-        try {
-            task->call_on_rust_stack(args, fn_ptr);
-        } catch (...) {
-            // We can't count on being able to unwind through arbitrary
-            // code. Our best option is to just fail hard.
-            // Logging here is not reliable
-            assert(false
-                   && "Rust task failed after reentering the Rust stack");
-        }
-    } else {
-        // There's no task. Call the function and hope for the best
-        stack_switch_shim f = (stack_switch_shim)fn_ptr;
-        f(args);
-    }
-}
-
-/**********************************************************************/
-
-struct s_fail_args {
-    rust_task *task;
-    char const *expr;
-    char const *file;
-    size_t line;
-};
-
-extern "C" CDECL void
-upcall_s_fail(s_fail_args *args) {
-    rust_task *task = args->task;
-    LOG_UPCALL_ENTRY(task);
-    task->fail(args->expr, args->file, args->line);
-}
-
-extern "C" CDECL void
-upcall_fail(char const *expr,
-            char const *file,
-            size_t line) {
-    rust_task *task = rust_try_get_current_task();
-    if (task == NULL) {
-        // FIXME #5161: Need to think about what to do here
-        printf("failure outside of a task");
-        abort();
-    }
-    s_fail_args args = {task,expr,file,line};
-    UPCALL_SWITCH_STACK(task, &args, upcall_s_fail);
-}
-
-// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
-// autogenerated wrappers for upcall_fail. Remove this when we fully move away
-// away from the C upcall path.
-extern "C" CDECL void
-rust_upcall_fail(char const *expr,
-                 char const *file,
-                 size_t line) {
-    upcall_fail(expr, file, line);
-}
-
-struct s_trace_args {
-    rust_task *task;
-    char const *msg;
-    char const *file;
-    size_t line;
-};
-
-/**********************************************************************
- * Allocate an object in the task-local heap.
- */
-
-struct s_malloc_args {
-    rust_task *task;
-    uintptr_t retval;
-    type_desc *td;
-    uintptr_t size;
-};
-
-extern "C" CDECL void
-upcall_s_malloc(s_malloc_args *args) {
-    rust_task *task = args->task;
-    LOG_UPCALL_ENTRY(task);
-    LOG(task, mem, "upcall malloc(0x%" PRIxPTR ")", args->td);
-
-    rust_opaque_box *box = task->boxed.malloc(args->td, args->size);
-    void *body = box_body(box);
-
-    debug::maybe_track_origin(task, box);
-
-    LOG(task, mem,
-        "upcall malloc(0x%" PRIxPTR ") = box 0x%" PRIxPTR
-        " with body 0x%" PRIxPTR,
-        args->td, (uintptr_t)box, (uintptr_t)body);
-
-    args->retval = (uintptr_t)box;
-}
-
-extern "C" CDECL uintptr_t
-upcall_malloc(type_desc *td, uintptr_t size) {
-    rust_task *task = rust_get_current_task();
-    s_malloc_args args = {task, 0, td, size};
-    UPCALL_SWITCH_STACK(task, &args, upcall_s_malloc);
-    return args.retval;
-}
-
-// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
-// autogenerated wrappers for upcall_malloc. Remove this when we fully move
-// away from the C upcall path.
-extern "C" CDECL uintptr_t
-rust_upcall_malloc(type_desc *td, uintptr_t size) {
-    return upcall_malloc(td, size);
-}
-
-extern "C" CDECL uintptr_t
-rust_upcall_malloc_noswitch(type_desc *td, uintptr_t size) {
-    rust_task *task = rust_get_current_task();
-    s_malloc_args args = {task, 0, td, size};
-    upcall_s_malloc(&args);
-    return args.retval;
-}
-
-/**********************************************************************
- * Called whenever an object in the task-local heap is freed.
- */
-
-struct s_free_args {
-    rust_task *task;
-    void *ptr;
-};
-
-extern "C" CDECL void
-upcall_s_free(s_free_args *args) {
-    rust_task *task = args->task;
-    LOG_UPCALL_ENTRY(task);
-
-    rust_sched_loop *sched_loop = task->sched_loop;
-    DLOG(sched_loop, mem,
-             "upcall free(0x%" PRIxPTR ", is_gc=%" PRIdPTR ")",
-             (uintptr_t)args->ptr);
-
-    debug::maybe_untrack_origin(task, args->ptr);
-
-    rust_opaque_box *box = (rust_opaque_box*) args->ptr;
-    task->boxed.free(box);
-}
-
-extern "C" CDECL void
-upcall_free(void* ptr) {
-    rust_task *task = rust_get_current_task();
-    s_free_args args = {task,ptr};
-    UPCALL_SWITCH_STACK(task, &args, upcall_s_free);
-}
-
-// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
-// autogenerated wrappers for upcall_free. Remove this when we fully move away
-// away from the C upcall path.
-extern "C" CDECL void
-rust_upcall_free(void* ptr) {
-    upcall_free(ptr);
-}
-
-extern "C" CDECL void
-rust_upcall_free_noswitch(void* ptr) {
-    rust_task *task = rust_get_current_task();
-    s_free_args args = {task,ptr};
-    upcall_s_free(&args);
+    // There's no task. Call the function and hope for the best
+    stack_switch_shim f = (stack_switch_shim)fn_ptr;
+    f(args);
 }
 
 /**********************************************************************/
@@ -293,41 +94,21 @@ upcall_rust_personality(int version,
     s_rust_personality_args args = {(_Unwind_Reason_Code)0,
                                     version, actions, exception_class,
                                     ue_header, context};
-    rust_task *task = rust_try_get_current_task();
-
-    if (task == NULL) {
-        // Assuming we're running with the new scheduler
-        upcall_s_rust_personality(&args);
-        return args.retval;
-    }
-
-    // The personality function is run on the stack of the
-    // last function that threw or landed, which is going
-    // to sometimes be the C stack. If we're on the Rust stack
-    // then switch to the C stack.
-
-    if (task->on_rust_stack()) {
-        UPCALL_SWITCH_STACK(task, &args, upcall_s_rust_personality);
-    } else {
-        upcall_s_rust_personality(&args);
-    }
+    upcall_s_rust_personality(&args);
     return args.retval;
 }
 
 // NB: This needs to be blazing fast. Don't switch stacks
 extern "C" CDECL void *
 upcall_new_stack(size_t stk_sz, void *args_addr, size_t args_sz) {
-    rust_task *task = rust_get_current_task();
-    return task->next_stack(stk_sz,
-                            args_addr,
-                            args_sz);
+    assert(false && "newsched shouldn't be growing the stack");
+    return NULL;
 }
 
 // NB: This needs to be blazing fast. Don't switch stacks
 extern "C" CDECL void
 upcall_del_stack() {
-    rust_task *task = rust_get_current_task();
-    task->prev_stack();
+    assert(false && "newsched shouldn't be growing the stack");
 }
 
 // Landing pads need to call this to insert the
@@ -336,12 +117,6 @@ upcall_del_stack() {
 // needs to acquire the value of the stack pointer
 extern "C" CDECL void
 upcall_reset_stack_limit() {
-    rust_task *task = rust_try_get_current_task();
-    if (task != NULL) {
-        task->reset_stack_limit();
-    } else {
-        // We must be in a newsched task
-    }
 }
 
 //
index 95651c686029fa5e66f825ebbfb662cf827d9e37..30d4fcbdc49664e7090f96c09a6ec988361d2528 100644 (file)
@@ -12,7 +12,8 @@
 #define RUST_UTIL_H
 
 #include <limits.h>
-#include "rust_task.h"
+#include "rust_exchange_alloc.h"
+#include "rust_type.h"
 #include "rust_env.h"
 
 extern struct type_desc str_body_tydesc;
index 19162b8df6b0f163ee0bd8f4af692a34ffb7b18c..f537e866dfcabf0baec19051b2553cc3054c715c 100644 (file)
@@ -16,8 +16,6 @@
 #include "uv.h"
 
 #include "rust_globals.h"
-#include "rust_task.h"
-#include "rust_log.h"
 
 // extern fn pointers
 typedef void (*extern_async_op_cb)(uv_loop_t* loop, void* data,
@@ -35,43 +33,6 @@ struct handle_data {
     extern_close_cb close_cb;
 };
 
-// helpers
-static void*
-current_kernel_malloc(size_t size, const char* tag) {
-  void* ptr = rust_get_current_task()->kernel->malloc(size, tag);
-  return ptr;
-}
-
-static void
-current_kernel_free(void* ptr) {
-  rust_get_current_task()->kernel->free(ptr);
-}
-
-static handle_data*
-new_handle_data_from(uint8_t* buf, extern_simple_cb cb) {
-    handle_data* data = (handle_data*)current_kernel_malloc(
-            sizeof(handle_data),
-            "handle_data");
-    memcpy(data->id_buf, buf, RUST_UV_HANDLE_LEN);
-    data->cb = cb;
-    return data;
-}
-
-// libuv callback impls
-static void
-foreign_extern_async_op_cb(uv_async_t* handle, int status) {
-    extern_async_op_cb cb = (extern_async_op_cb)handle->data;
-    void* loop_data = handle->loop->data;
-    cb(handle->loop, loop_data, handle);
-}
-
-static void
-foreign_async_cb(uv_async_t* handle, int status) {
-    handle_data* handle_d = (handle_data*)handle->data;
-    void* loop_data = handle->loop->data;
-    handle_d->cb(handle_d->id_buf, loop_data);
-}
-
 static void
 foreign_timer_cb(uv_timer_t* handle, int status) {
     handle_data* handle_d = (handle_data*)handle->data;
@@ -84,18 +45,6 @@ foreign_close_cb(uv_handle_t* handle) {
     handle_data* data = (handle_data*)handle->data;
     data->close_cb(data->id_buf, handle, handle->loop->data);
 }
-
-static void
-foreign_close_op_cb(uv_handle_t* op_handle) {
-    current_kernel_free(op_handle);
-    // uv_run() should return after this..
-}
-
-// foreign fns bound in rust
-extern "C" void
-rust_uv_free(void* ptr) {
-    current_kernel_free(ptr);
-}
 extern "C" void*
 rust_uv_loop_new() {
     return (void*)uv_loop_new();
@@ -127,24 +76,6 @@ rust_uv_loop_set_data(uv_loop_t* loop, void* data) {
     loop->data = data;
 }
 
-extern "C" void*
-rust_uv_bind_op_cb(uv_loop_t* loop, extern_async_op_cb cb) {
-    uv_async_t* async = (uv_async_t*)current_kernel_malloc(
-            sizeof(uv_async_t),
-            "uv_async_t");
-    uv_async_init(loop, async, foreign_extern_async_op_cb);
-    async->data = (void*)cb;
-    // decrement the ref count, so that our async bind
-    // doesn't count towards keeping the loop alive
-    //uv_unref(loop);
-    return async;
-}
-
-extern "C" void
-rust_uv_stop_op_cb(uv_handle_t* op_handle) {
-    uv_close(op_handle, foreign_close_op_cb);
-}
-
 extern "C" void
 rust_uv_run(uv_loop_t* loop) {
     uv_run(loop, UV_RUN_DEFAULT);
@@ -167,18 +98,6 @@ rust_uv_hilvl_close(uv_handle_t* handle, extern_close_cb cb) {
     uv_close(handle, foreign_close_cb);
 }
 
-extern "C" void
-rust_uv_hilvl_close_async(uv_async_t* handle) {
-    current_kernel_free(handle->data);
-    current_kernel_free(handle);
-}
-
-extern "C" void
-rust_uv_hilvl_close_timer(uv_async_t* handle) {
-    current_kernel_free(handle->data);
-    current_kernel_free(handle);
-}
-
 extern "C" void
 rust_uv_async_send(uv_async_t* handle) {
     uv_async_send(handle);
@@ -191,32 +110,6 @@ rust_uv_async_init(uv_loop_t* loop_handle,
     return uv_async_init(loop_handle, async_handle, cb);
 }
 
-extern "C" void*
-rust_uv_hilvl_async_init(uv_loop_t* loop, extern_simple_cb cb,
-        uint8_t* buf) {
-    uv_async_t* async = (uv_async_t*)current_kernel_malloc(
-            sizeof(uv_async_t),
-            "uv_async_t");
-    uv_async_init(loop, async, foreign_async_cb);
-    handle_data* data = new_handle_data_from(buf, cb);
-    async->data = data;
-
-    return async;
-}
-
-extern "C" void*
-rust_uv_hilvl_timer_init(uv_loop_t* loop, extern_simple_cb cb,
-        uint8_t* buf) {
-    uv_timer_t* new_timer = (uv_timer_t*)current_kernel_malloc(
-            sizeof(uv_timer_t),
-            "uv_timer_t");
-    uv_timer_init(loop, new_timer);
-    handle_data* data = new_handle_data_from(buf, cb);
-    new_timer->data = data;
-
-    return new_timer;
-}
-
 extern "C" void
 rust_uv_hilvl_timer_start(uv_timer_t* the_timer, uint32_t timeout,
         uint32_t repeat) {
@@ -469,15 +362,6 @@ rust_uv_get_stream_handle_from_write_req(uv_write_t* write_req) {
     return write_req->handle;
 }
 
-extern "C" uv_buf_t
-current_kernel_malloc_alloc_cb(uv_handle_t* handle,
-        size_t suggested_size) {
-    char* base_ptr = (char*)current_kernel_malloc(sizeof(char)
-            * suggested_size,
-            "uv_buf_t_base_val");
-    return uv_buf_init(base_ptr, suggested_size);
-}
-
 extern "C" void
 rust_uv_buf_init(uv_buf_t* out_buf, char* base, size_t len) {
     *out_buf = uv_buf_init(base, len);
@@ -563,16 +447,6 @@ rust_uv_read_stop(uv_stream_t* stream) {
     return uv_read_stop(stream);
 }
 
-extern "C" char*
-rust_uv_malloc_buf_base_of(size_t suggested_size) {
-    return (char*) current_kernel_malloc(sizeof(char)*suggested_size,
-            "uv_buf_t base");
-}
-extern "C" void
-rust_uv_free_base_of_buf(uv_buf_t buf) {
-    current_kernel_free(buf.base);
-}
-
 extern "C" struct sockaddr_in
 rust_uv_ip4_addr(const char* ip, int port) {
     struct sockaddr_in addr = uv_ip4_addr(ip, port);
@@ -639,16 +513,6 @@ rust_uv_ip6_port(struct sockaddr_in6* src) {
     return ntohs(src->sin6_port);
 }
 
-extern "C" void*
-rust_uv_current_kernel_malloc(size_t size) {
-    return current_kernel_malloc(size, "rust_uv_current_kernel_malloc");
-}
-
-extern "C" void
-rust_uv_current_kernel_free(void* mem) {
-    current_kernel_free(mem);
-}
-
 extern  "C" int
 rust_uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* handle,
                     uv_getaddrinfo_cb cb,
index 75e02d0a103ddae013665dbeee02e8c85426b035..b5ce0400c1e940514766f3e4c4142a5b571254a9 100644 (file)
@@ -1,27 +1,19 @@
-debug_get_stk_seg
 debug_abi_1
 debug_abi_2
 debug_static_mut
 debug_static_mut_check_four
-get_task_id
 get_time
 rust_tzset
 rust_gmtime
 rust_localtime
 rust_timegm
 rust_mktime
-new_task
 precise_time_ns
 rand_free
 rand_new_seeded
 rand_seed_size
 rand_gen_seed
 rand_next
-rust_get_sched_id
-rust_get_argc
-rust_get_argv
-rust_new_sched
-rust_new_task_in_sched
 rust_path_is_dir
 rust_path_exists
 rust_get_stdin
@@ -35,55 +27,26 @@ rust_log_console_off
 rust_should_log_console
 rust_set_environ
 rust_unset_sigprocmask
-rust_set_exit_status
-rust_start
 rust_env_pairs
-rust_task_yield
-rust_task_is_unwinding
-rust_get_task
-rust_try_get_task
-rust_get_stack_segment
-rust_get_c_stack
-rust_log_str
-start_task
-rust_local_realloc
-task_clear_event_reject
-task_wait_event
-task_signal_event
-upcall_fail
-upcall_free
-upcall_malloc
 upcall_rust_personality
 upcall_call_shim_on_c_stack
 upcall_call_shim_on_rust_stack
 upcall_new_stack
 upcall_del_stack
 upcall_reset_stack_limit
-rust_upcall_fail
-rust_upcall_free
-rust_upcall_free_noswitch
-rust_upcall_malloc
-rust_upcall_malloc_noswitch
 rust_uv_loop_new
 rust_uv_loop_delete
 rust_uv_walk
 rust_uv_loop_set_data
-rust_uv_bind_op_cb
-rust_uv_stop_op_cb
 rust_uv_run
 rust_uv_close
 rust_uv_hilvl_close
-rust_uv_hilvl_close_async
-rust_uv_hilvl_close_timer
 rust_uv_async_send
 rust_uv_async_init
-rust_uv_hilvl_async_init
-rust_uv_hilvl_timer_init
 rust_uv_hilvl_timer_start
 rust_uv_timer_init
 rust_uv_timer_start
 rust_uv_timer_stop
-rust_uv_free
 rust_uv_tcp_init
 rust_uv_buf_init
 rust_uv_last_error
@@ -124,8 +87,6 @@ rust_uv_accept
 rust_uv_write
 rust_uv_read_start
 rust_uv_read_stop
-rust_uv_malloc_buf_base_of
-rust_uv_free_base_of_buf
 rust_uv_is_ipv4_addrinfo
 rust_uv_is_ipv6_addrinfo
 rust_uv_get_next_addrinfo
@@ -155,8 +116,6 @@ rust_uv_get_data_for_req
 rust_uv_set_data_for_req
 rust_uv_get_base_from_buf
 rust_uv_get_len_from_buf
-rust_uv_current_kernel_malloc
-rust_uv_current_kernel_free
 rust_uv_getaddrinfo
 rust_uv_freeaddrinfo
 rust_uv_idle_new
@@ -172,21 +131,10 @@ rust_dbg_lock_wait
 rust_dbg_lock_signal
 rust_dbg_call
 rust_dbg_do_nothing
-rust_osmain_sched_id
-rust_task_inhibit_kill
-rust_task_allow_kill
-rust_task_inhibit_yield
-rust_task_allow_yield
-rust_task_kill_other
-rust_task_kill_all
 rust_create_little_lock
 rust_destroy_little_lock
 rust_lock_little_lock
 rust_unlock_little_lock
-rust_get_task_local_data
-rust_task_local_data_atexit
-rust_task_ref
-rust_task_deref
 tdefl_compress_mem_to_heap
 tinfl_decompress_mem_to_heap
 rust_gc_metadata
@@ -221,7 +169,6 @@ rust_dbg_extern_return_TwoU32s
 rust_dbg_extern_return_TwoU64s
 rust_dbg_extern_identity_double
 rust_dbg_extern_identity_u8
-rust_get_rt_env
 rust_uv_handle_size
 rust_uv_req_size
 rust_uv_handle_type_max
@@ -241,8 +188,6 @@ rust_boxed_region_realloc
 rust_boxed_region_free
 rust_try
 rust_begin_unwind
-rust_take_task_borrow_list
-rust_set_task_borrow_list
 rust_valgrind_stack_register
 rust_valgrind_stack_deregister
 rust_take_env_lock
@@ -251,7 +196,6 @@ rust_update_log_settings
 rust_running_on_valgrind
 rust_get_num_cpus
 rust_get_global_args_ptr
-rust_current_boxed_region
 rust_take_global_args_lock
 rust_drop_global_args_lock
 rust_set_exit_status_newrt
@@ -259,3 +203,4 @@ rust_get_exit_status_newrt
 rust_take_change_dir_lock
 rust_drop_change_dir_lock
 rust_get_test_int
+rust_get_task
\ No newline at end of file
index 05325c3b935c436cc7108497f889360396328351..8290f62bada26aed8db31e617f91a21765dcebbb 100644 (file)
@@ -1,9 +1,33 @@
 #[crate_type="lib"];
 
-pub struct Foo {
+pub struct Struct {
     x: int
 }
 
-impl Foo {
-    fn new() -> Foo { Foo { x: 1 } }
+impl Struct {
+    fn static_meth_struct() -> Struct {
+        Struct { x: 1 }
+    }
+
+    fn meth_struct(&self) -> int {
+        self.x
+    }
+}
+
+pub enum Enum {
+    Variant1(int),
+    Variant2(int)
+}
+
+impl Enum {
+    fn static_meth_enum() -> Enum {
+        Variant2(10)
+    }
+
+    fn meth_enum(&self) -> int {
+        match *self {
+            Variant1(x) |
+            Variant2(x) => x
+        }
+    }
 }
index 2f4d763b84d778ab750446de95e447dd2b0cb122..9725297bace53b12371bef8e7c5c9eabe9bf4980 100644 (file)
@@ -96,9 +96,9 @@ fn make_graph(N: uint, edges: ~[(node_id, node_id)]) -> graph {
         }
     }
 
-    do graph.consume_iter().transform |v| {
+    do graph.move_iter().map |v| {
         let mut vec = ~[];
-        for i in v.consume() {
+        for i in v.move_iter() {
             vec.push(i);
         }
         vec
@@ -119,7 +119,7 @@ fn gen_search_keys(graph: &[~[node_id]], n: uint) -> ~[node_id] {
         }
     }
     let mut vec = ~[];
-    for i in keys.consume() {
+    for i in keys.move_iter() {
         vec.push(i);
     }
     return vec;
@@ -193,7 +193,7 @@ fn is_gray(c: &color) -> bool {
         // Do the BFS.
         info!("PBFS iteration %?", i);
         i += 1;
-        colors = do colors.iter().enumerate().transform |(i, c)| {
+        colors = do colors.iter().enumerate().map |(i, c)| {
             let c : color = *c;
             match c {
               white => {
@@ -220,7 +220,7 @@ fn is_gray(c: &color) -> bool {
     }
 
     // Convert the results.
-    do colors.iter().transform |c| {
+    do colors.iter().map |c| {
         match *c {
           white => { -1i64 }
           black(parent) => { parent }
diff --git a/src/test/bench/rt-messaging-ping-pong.rs b/src/test/bench/rt-messaging-ping-pong.rs
new file mode 100644 (file)
index 0000000..3d38d61
--- /dev/null
@@ -0,0 +1,82 @@
+// 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.
+
+extern mod extra;
+
+use std::task::spawn;
+use std::os;
+use std::uint;
+use std::rt::test::spawntask_later;
+use std::cell::Cell;
+
+// This is a simple bench that creates M pairs of of tasks. These
+// tasks ping-pong back and forth over a pair of streams. This is a
+// cannonical message-passing benchmark as it heavily strains message
+// passing and almost nothing else.
+
+fn ping_pong_bench(n: uint, m: uint) {
+
+    // Create pairs of tasks that pingpong back and forth.
+    fn run_pair(n: uint) {
+            // Create a stream A->B
+            let (pa,ca) = stream::<()>();
+            // Create a stream B->A
+            let (pb,cb) = stream::<()>();
+
+            let pa = Cell::new(pa);
+            let ca = Cell::new(ca);
+            let pb = Cell::new(pb);
+            let cb = Cell::new(cb);
+
+        do spawntask_later() || {
+            let chan = ca.take();
+            let port = pb.take();
+            do n.times {
+                chan.send(());
+                port.recv();
+            }
+        }
+
+        do spawntask_later() || {
+            let chan = cb.take();
+            let port = pa.take();
+            do n.times {
+                port.recv();
+                chan.send(());
+            }
+        }
+    }
+
+    do m.times {
+        run_pair(n)
+    }
+
+}
+
+
+
+fn main() {
+
+    let args = os::args();
+    let n = if args.len() == 3 {
+        uint::from_str(args[1]).unwrap()
+    } else {
+        10000
+    };
+
+    let m = if args.len() == 3 {
+        uint::from_str(args[2]).unwrap()
+    } else {
+        4
+    };
+
+    ping_pong_bench(n, m);
+
+}
diff --git a/src/test/bench/rt-parfib.rs b/src/test/bench/rt-parfib.rs
new file mode 100644 (file)
index 0000000..6669342
--- /dev/null
@@ -0,0 +1,49 @@
+// 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.
+
+extern mod extra;
+
+use std::task::spawn;
+use std::os;
+use std::uint;
+use std::rt::test::spawntask_later;
+use std::cell::Cell;
+use std::comm::*;
+
+// A simple implementation of parfib. One subtree is found in a new
+// task and communicated over a oneshot pipe, the other is found
+// locally. There is no sequential-mode threshold.
+
+fn parfib(n: uint) -> uint {
+    if(n == 0 || n == 1) {
+        return 1;
+    }
+
+    let (port,chan) = oneshot::<uint>();
+    let chan = Cell::new(chan);
+    do spawntask_later {
+        chan.take().send(parfib(n-1));
+    };
+    let m2 = parfib(n-2);
+    return (port.recv() + m2);
+}
+
+fn main() {
+
+    let args = os::args();
+    let n = if args.len() == 2 {
+        uint::from_str(args[1]).unwrap()
+    } else {
+        10
+    };
+
+    parfib(n);
+
+}
diff --git a/src/test/bench/rt-spawn-rate.rs b/src/test/bench/rt-spawn-rate.rs
new file mode 100644 (file)
index 0000000..ff578ed
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+extern mod extra;
+
+use std::task::spawn;
+use std::os;
+use std::uint;
+
+// Very simple spawn rate test. Spawn N tasks that do nothing and
+// return.
+
+fn main() {
+
+    let args = os::args();
+    let n = if args.len() == 2 {
+        uint::from_str(args[1]).unwrap()
+    } else {
+        100000
+    };
+
+    do n.times {
+        do spawn || {};
+    }
+
+}
index 2b177ccb98fcc194a0dbf743619ac82764b6a447..f82c5e692e44d21a796314875b1d2774cff9684c 100644 (file)
@@ -150,7 +150,7 @@ fn rendezvous(nn: uint, set: ~[color]) {
 
     // these channels will allow us to talk to each creature by 'name'/index
     let to_creature: ~[Chan<Option<CreatureInfo>>] =
-        set.iter().enumerate().transform(|(ii, col)| {
+        set.iter().enumerate().map(|(ii, col)| {
             // create each creature as a listener with a port, and
             // give us a channel to talk to each
             let ii = ii;
index 8c4e9092ce0a6f1d9640ebc9759079cdf3f53fc0..66b9bdc0a42c9626924c5603c6b39c695a667b12 100644 (file)
@@ -75,7 +75,7 @@ fn sortKV<TT:Clone + Ord, UU:Clone + Ord>(orig: ~[(TT,UU)]) -> ~[(TT,UU)] {
        unsafe {
            let b = str::raw::from_bytes(k);
            // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
-           // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+           // to_ascii_move and to_str_move to not do a unnecessary copy.
            buffer.push_str(fmt!("%s %0.3f\n", b.to_ascii().to_upper().to_str_ascii(), v));
        }
    }
@@ -86,7 +86,7 @@ fn sortKV<TT:Clone + Ord, UU:Clone + Ord>(orig: ~[(TT,UU)]) -> ~[(TT,UU)] {
 // given a map, search for the frequency of a pattern
 fn find(mm: &HashMap<~[u8], uint>, key: ~str) -> uint {
    // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
-   // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+   // to_ascii_move and to_str_move to not do a unnecessary copy.
    let key = key.to_ascii().to_lower().to_str_ascii();
    match mm.find_equiv(&key.as_bytes()) {
       option::None      => { return 0u; }
@@ -172,7 +172,7 @@ fn main() {
     let sizes = ~[1u,2,3,4,6,12,18];
     let mut streams = vec::from_fn(sizes.len(), |_| Some(stream::<~str>()));
     let mut from_child = ~[];
-    let to_child   = do sizes.iter().zip(streams.mut_iter()).transform |(sz, stream_ref)| {
+    let to_child   = do sizes.iter().zip(streams.mut_iter()).map |(sz, stream_ref)| {
         let sz = *sz;
         let stream = util::replace(stream_ref, None);
         let (from_child_, to_parent_) = stream.unwrap();
index 7f986eab7893880e5da06bcca47a0245d1caaf11..5efe13f8bca6b1376b8d7f39ec1783db30d46f70 100644 (file)
@@ -28,20 +28,20 @@ fn calc(children: uint, parent_wait_chan: &Chan<Chan<Chan<int>>>) {
     };
 
     let child_start_chans: ~[Chan<Chan<int>>] =
-        wait_ports.consume_iter().transform(|port| port.recv()).collect();
+        wait_ports.move_iter().map(|port| port.recv()).collect();
 
     let (start_port, start_chan) = stream::<Chan<int>>();
     parent_wait_chan.send(start_chan);
     let parent_result_chan: Chan<int> = start_port.recv();
 
     let child_sum_ports: ~[Port<int>] =
-        do child_start_chans.consume_iter().transform |child_start_chan| {
+        do child_start_chans.move_iter().map |child_start_chan| {
             let (child_sum_port, child_sum_chan) = stream::<int>();
             child_start_chan.send(child_sum_chan);
             child_sum_port
     }.collect();
 
-    let sum = child_sum_ports.consume_iter().fold(0, |sum, sum_port| sum + sum_port.recv() );
+    let sum = child_sum_ports.move_iter().fold(0, |sum, sum_port| sum + sum_port.recv() );
 
     parent_result_chan.send(sum + 1);
 }
diff --git a/src/test/codegen/single-return-value.cc b/src/test/codegen/single-return-value.cc
new file mode 100644 (file)
index 0000000..97d80d3
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+extern "C"
+int test() {
+  return 5;
+}
diff --git a/src/test/codegen/single-return-value.rs b/src/test/codegen/single-return-value.rs
new file mode 100644 (file)
index 0000000..e6eb9a2
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+#[no_mangle]
+fn test() -> int {
+    5
+}
index 39a0e585ad2db4b954012097258cdc7fba3e363f..0f67d8a6d0c4bbcd8977cbd510db72ce2c4b0b1d 100644 (file)
@@ -6,7 +6,7 @@ struct Foo {
 }
 
 pub fn main() {
-    let x = [
+    let x = ~[
         Foo { string: ~"foo" },
         Foo { string: ~"bar" },
         Foo { string: ~"baz" }
index 7f98eba599654ca77f708dff46d2ba40362b948b..ca20d68e4cdcbde130e1e448ab4ef9cec03edeab 100644 (file)
@@ -1,5 +1,5 @@
 fn a() -> &[int] {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let tail = match vec {
         [_, ..tail] => tail, //~ ERROR does not live long enough
         _ => fail!("a")
@@ -8,7 +8,7 @@ fn a() -> &[int] {
 }
 
 fn b() -> &[int] {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let init = match vec {
         [..init, _] => init, //~ ERROR does not live long enough
         _ => fail!("b")
@@ -17,7 +17,7 @@ fn b() -> &[int] {
 }
 
 fn c() -> &[int] {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let slice = match vec {
         [_, ..slice, _] => slice, //~ ERROR does not live long enough
         _ => fail!("c")
index 36ae5f88208929397a0c82a73c237f30e15c3186..02ba1b9d2fffb634f41b8336a5aedfc7bbccfe71 100644 (file)
@@ -1,24 +1,24 @@
 fn a() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [~ref _a] => {
-            vec[0] = ~4; //~ ERROR cannot assign to `vec[]` because it is borrowed
+            vec[0] = ~4; //~ ERROR cannot assign to `(*vec)[]` because it is borrowed
         }
         _ => fail!("foo")
     }
 }
 
 fn b() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [.._b] => {
-            vec[0] = ~4; //~ ERROR cannot assign to `vec[]` because it is borrowed
+            vec[0] = ~4; //~ ERROR cannot assign to `(*vec)[]` because it is borrowed
         }
     }
 }
 
 fn c() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [_a, .._b] => {
             //~^ ERROR cannot move out
@@ -35,7 +35,7 @@ fn c() {
 }
 
 fn d() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [.._a, _b] => {
             //~^ ERROR cannot move out
@@ -46,7 +46,7 @@ fn d() {
 }
 
 fn e() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [_a, _b, _c] => {}
         _ => {}
index e3e12a4a4168bc0114229773d134c5d47dab01d2..87511c34172cd16f05203bc8e99df819c27844bd 100644 (file)
@@ -1,5 +1,5 @@
 fn a() -> &int {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let tail = match vec {
         [_a, ..tail] => &tail[0], //~ ERROR borrowed value does not live long enough
         _ => fail!("foo")
diff --git a/src/test/compile-fail/extenv-arg-2-not-string-literal.rs b/src/test/compile-fail/extenv-arg-2-not-string-literal.rs
new file mode 100644 (file)
index 0000000..c236268
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+fn main() { env!("one", 10); } //~ ERROR: expected string literal
index 7ff1357dcf3c90845f777375540918c60710c0c6..afa47dbe744661ca773ba0c271f28eaa5d700c65 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.
 //
@@ -8,6 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: env! takes 1 argument
-
-fn main() { env!(); }
+fn main() { env!(); } //~ ERROR: env! takes 1 or 2 arguments
diff --git a/src/test/compile-fail/extenv-not-defined-custom.rs b/src/test/compile-fail/extenv-not-defined-custom.rs
new file mode 100644 (file)
index 0000000..485b6c0
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } //~ ERROR: my error message
diff --git a/src/test/compile-fail/extenv-not-defined-default.rs b/src/test/compile-fail/extenv-not-defined-default.rs
new file mode 100644 (file)
index 0000000..d7a543c
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+fn main() { env!("__HOPEFULLY_NOT_DEFINED__"); } //~ ERROR: Environment variable __HOPEFULLY_NOT_DEFINED__ not defined
index 3f09f81b85bfd58b6002fe6398ab849d132db0bc..07ce47a14d83d5aa39cc4e33e8abf633a957829d 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.
 //
@@ -8,6 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:requires a string
-
-fn main() { env!(10); }
+fn main() { env!(10, "two"); } //~ ERROR: expected string literal
index b1b2001abc35874dc140d66fb442b5d75968c27a..c6c4f0ec6b8076c8ca0b7320ea175c4abd2d0488 100644 (file)
@@ -8,6 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: env! takes 1 argument
-
-fn main() { env!("one", "two"); }
+fn main() { env!("one", "two", "three"); } //~ ERROR: env! takes 1 or 2 arguments
diff --git a/src/test/compile-fail/extoption_env-no-args.rs b/src/test/compile-fail/extoption_env-no-args.rs
new file mode 100644 (file)
index 0000000..fd56756
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+fn main() { option_env!(); } //~ ERROR: option_env! takes 1 argument
diff --git a/src/test/compile-fail/extoption_env-not-string-literal.rs b/src/test/compile-fail/extoption_env-not-string-literal.rs
new file mode 100644 (file)
index 0000000..10f6c34
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+fn main() { option_env!(10); } //~ ERROR: requires a string
diff --git a/src/test/compile-fail/extoption_env-too-many-args.rs b/src/test/compile-fail/extoption_env-too-many-args.rs
new file mode 100644 (file)
index 0000000..b31e857
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+fn main() { option_env!("one", "two"); } //~ ERROR: option_env! takes 1 argument
diff --git a/src/test/compile-fail/issue-2766-a.rs b/src/test/compile-fail/issue-2766-a.rs
deleted file mode 100644 (file)
index c5d13c8..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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.
-
-pub mod stream {
-    pub enum Stream<T:Send> { send(T, ::stream::server::Stream<T>), }
-    pub mod server {
-        use std::option;
-        use std::pipes;
-
-        impl<T:Send> Stream<T> {
-            pub fn recv() -> extern fn(v: Stream<T>) -> ::stream::Stream<T> {
-              // resolve really should report just one error here.
-              // Change the test case when it changes.
-              pub fn recv(pipe: Stream<T>) -> ::stream::Stream<T> { //~ ERROR attempt to use a type argument out of scope
-                //~^ ERROR use of undeclared type name
-                //~^^ ERROR attempt to use a type argument out of scope
-                //~^^^ ERROR use of undeclared type name
-                    pipes::recv(pipe).unwrap()
-                }
-                recv
-            }
-        }
-
-        pub type Stream<T:Send> = pipes::RecvPacket<::stream::Stream<T>>;
-    }
-}
-
-fn main() {}
diff --git a/src/test/compile-fail/match-vec-fixed.rs b/src/test/compile-fail/match-vec-fixed.rs
new file mode 100644 (file)
index 0000000..b3e1398
--- /dev/null
@@ -0,0 +1,16 @@
+fn a() {
+    let v = [1, 2, 3];
+    match v {
+        [_, _, _] => {}
+        [_, _, _] => {} //~ ERROR unreachable pattern
+    }
+    match v {
+        [_, 1, _] => {}
+        [_, 1, _] => {} //~ ERROR unreachable pattern
+        _ => {}
+    }
+}
+
+fn main() {
+    a();
+}
index 3930e7d219201f0410f60c85861908f9d06ed0f4..b557242af44c12ab592f58c11e3d914e16e81573 100644 (file)
@@ -6,13 +6,13 @@ fn main() {
         _ => ()
     }
 
-    match [~"foo", ~"bar", ~"baz"] {
+    match ~[~"foo", ~"bar", ~"baz"] {
         [a, _, _, .._] => { println(a); }
         [~"foo", ~"bar", ~"baz", ~"foo", ~"bar"] => { } //~ ERROR unreachable pattern
         _ => { }
     }
 
-    match ['a', 'b', 'c'] {
+    match ~['a', 'b', 'c'] {
         ['a', 'b', 'c', .._tail] => {}
         ['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
         _ => {}
diff --git a/src/test/compile-fail/static-slice-not-null-terminated.rs b/src/test/compile-fail/static-slice-not-null-terminated.rs
deleted file mode 100644 (file)
index 3cfaa57..0000000
+++ /dev/null
@@ -1,21 +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.
-
-fn main() {
-    let _ = (~"foo").as_bytes_with_null();
-    let _ = (@"foo").as_bytes_with_null();
-
-    // a plain static slice is null terminated, but such a slice can
-    // be sliced shorter (i.e. become non-null terminated) and still
-    // have the static lifetime
-    let foo: &'static str = "foo";
-    let _ = foo.as_bytes_with_null();
-     //~^ ERROR does not implement any method in scope named `as_bytes_with_null`
-}
index e8777a0a9f256ba5d866b225383b7ed4ed47b98a..8314755af3b3d7195303d6aa1d34248bf0df6e79 100644 (file)
@@ -4,5 +4,13 @@
 extern mod xc_private_method_lib;
 
 fn main() {
-    let _ = xc_private_method_lib::Foo::new();  //~ ERROR function `new` is private
+    // normal method on struct
+    let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();  //~ ERROR method `meth_struct` is private
+    // static method on struct
+    let _ = xc_private_method_lib::Struct::static_meth_struct();  //~ ERROR function `static_meth_struct` is private
+
+    // normal method on enum
+    let _ = xc_private_method_lib::Variant1(20).meth_enum();  //~ ERROR method `meth_enum` is private
+    // static method on enum
+    let _ = xc_private_method_lib::Enum::static_meth_enum();  //~ ERROR function `static_meth_enum` is private
 }
index b360cc7528fde14501ae1c2277c451599c85d07e..4bfdb20d9f2b9f2884ab3e6cde5e826bda1c9b4e 100644 (file)
@@ -81,17 +81,6 @@ fn test_ptr() {
     }
 }
 
-mod test {
-    use std::libc;
-
-    #[abi = "cdecl"]
-    #[nolink]
-    extern {
-        pub fn rust_get_sched_id() -> libc::intptr_t;
-        pub fn get_task_id() -> libc::intptr_t;
-    }
-}
-
 #[deriving(Eq)]
 struct p {
   x: int,
index 7b74d1d314b40c5d1c4f95dca84a02041e731407..aabc005c57fb3af900b02214dcccb8761f8068ed 100644 (file)
@@ -28,7 +28,7 @@ pub fn main() {
     assert!(any_negative);
 
     // Higher precedence than unary operations:
-    let abs_v = do v.iter().transform |e| { e.abs() }.collect::<~[float]>();
+    let abs_v = do v.iter().map |e| { e.abs() }.collect::<~[float]>();
     assert!(do abs_v.iter().all |e| { e.is_positive() });
     assert!(!do abs_v.iter().any |e| { e.is_negative() });
 
index 747066cb4e851cf9a2a0db74fb28ceda4c331e7b..85e22cfecb4286e287be8146243bd0d81de7d7b1 100644 (file)
@@ -15,12 +15,12 @@ mod rustrt {
 
     #[abi = "cdecl"]
     extern {
-        pub fn get_task_id() -> libc::intptr_t;
+        pub fn rust_get_test_int() -> libc::intptr_t;
     }
 }
 
 pub fn main() {
     unsafe {
-        let _foo = rustrt::get_task_id;
+        let _foo = rustrt::rust_get_test_int;
     }
 }
index 9775f1ef45a7475730489d632dffa06984f9f66a..e91c11f5cd0a703eea86f5080aec6051d1c52bf9 100644 (file)
@@ -20,11 +20,11 @@ mod libc {
 }
 
 fn atol(s: ~str) -> int {
-    s.as_imm_buf(|x, _len| unsafe { libc::atol(x) })
+    s.to_c_str().with_ref(|x| unsafe { libc::atol(x as *u8) })
 }
 
 fn atoll(s: ~str) -> i64 {
-    s.as_imm_buf(|x, _len| unsafe { libc::atoll(x) })
+    s.to_c_str().with_ref(|x| unsafe { libc::atoll(x as *u8) })
 }
 
 pub fn main() {
index 2f0cd3c611f620afc8be3bb106e67be3e6b5ae9b..0e7d6d9f16a3c420f080df9a4115d7c09a1d49aa 100644 (file)
 
 use std::str;
 
-static a: [u8, ..3] = ['h' as u8, 'i' as u8, 0 as u8];
-static c: &'static [u8, ..3] = &a;
-static b: *u8 = c as *u8;
+static A: [u8, ..2] = ['h' as u8, 'i' as u8];
+static B: &'static [u8, ..2] = &A;
+static C: *u8 = B as *u8;
 
 pub fn main() {
-    let foo = &a as *u8;
-    assert_eq!(unsafe { str::raw::from_bytes(a) }, ~"hi\x00");
-    assert_eq!(unsafe { str::raw::from_buf(foo) }, ~"hi");
-    assert_eq!(unsafe { str::raw::from_buf(b) }, ~"hi");
-    assert!(unsafe { *b == a[0] });
-    assert!(unsafe { *(&c[0] as *u8) == a[0] });
+    unsafe {
+        let foo = &A as *u8;
+        assert_eq!(str::raw::from_bytes(A), ~"hi");
+        assert_eq!(str::raw::from_buf_len(foo, A.len()), ~"hi");
+        assert_eq!(str::raw::from_buf_len(C, B.len()), ~"hi");
+        assert!(*C == A[0]);
+        assert!(*(&B[0] as *u8) == A[0]);
+
+        let bar = str::raw::from_bytes(A).to_c_str();
+        assert_eq!(bar.with_ref(|buf| str::raw::from_c_str(buf)), ~"hi");
+    }
 }
diff --git a/src/test/run-pass/extern-mod-url.rs b/src/test/run-pass/extern-mod-url.rs
deleted file mode 100644 (file)
index 363c54f..0000000
+++ /dev/null
@@ -1,16 +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.
-
-// Just a test that new-style extern mods parse
-
-// xfail-test FIXME #6407
-extern mod test = "github.com/catamorphism/test-pkg";
-
-fn main() {}
diff --git a/src/test/run-pass/extoption_env-not-defined.rs b/src/test/run-pass/extoption_env-not-defined.rs
new file mode 100644 (file)
index 0000000..412efcc
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+fn main() {
+    let opt: Option<&'static str> = option_env!("__HOPEFULLY_DOESNT_EXIST__");
+    assert!(opt.is_none());
+}
index 38f36dd258b7acde112eb972d96eaebab173f3fc..b5a114ef22364e64dc2bea3f7ccf326b914afa50 100644 (file)
@@ -26,8 +26,9 @@ mod libc {
 fn strlen(str: ~str) -> uint {
     unsafe {
         // C string is terminated with a zero
-        let bytes = str.to_bytes_with_null();
-        return libc::my_strlen(vec::raw::to_ptr(bytes));
+        do str.to_c_str().with_ref |buf| {
+            libc::my_strlen(buf as *u8)
+        }
     }
 }
 
index 546368c8f9a742e4a16a51e1ce71d269193a91a7..a78a10e20e8b0c4d01a99bf535e3ef52df85c4e5 100644 (file)
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[link(name = "get_task_id")];
+#[link(name = "rust_get_test_int")];
 
 mod rustrt {
     use std::libc;
 
     extern {
-        pub fn get_task_id() -> libc::intptr_t;
+        pub fn rust_get_test_int() -> libc::intptr_t;
     }
 }
 
index 2f44f9783e16ab8bf87cf9f2b64a85aaa0d95a32..accf7c4e6cd2d7fc64fb65473ce778302aca1d91 100644 (file)
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::{pipes, io, task, comm};
-
 fn main() {
-    let (port, chan) = comm::stream();
+    let (port, chan) = stream();
 
-    do task::spawn {
-        io::println(port.recv());
+    do spawn {
+        println(port.recv());
     }
 
     chan.send("hello, world");
index 002435fcb36f0c28bdce527c52e92c934b4770e8..8e55ad90c70441bd6091fc36d2b84d50f0cbfe2d 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
-
 enum Enum {
     Foo { foo: uint },
     Bar { bar: uint }
index 77affb5ecf31e5481654971f7977f0e423eb5b2b..2d2a82ddb1b18108f9890de2cf2b77c54c214091 100644 (file)
@@ -174,7 +174,7 @@ pub mod rustrt {
             #[attr];
 
             #[attr]
-            fn get_task_id() -> libc::intptr_t;
+            fn rust_get_test_int() -> libc::intptr_t;
         }
     }
 }
diff --git a/src/test/run-pass/match-enum-struct-0.rs b/src/test/run-pass/match-enum-struct-0.rs
new file mode 100644 (file)
index 0000000..365729e
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+// regression test for issue #5625
+
+enum E {
+    Foo{f : int},
+    Bar
+}
+
+pub fn main() {
+    let e = Bar;
+    match e {
+        Foo{f: _f} => fail!(),
+        _ => (),
+    }
+}
diff --git a/src/test/run-pass/match-enum-struct-1.rs b/src/test/run-pass/match-enum-struct-1.rs
new file mode 100644 (file)
index 0000000..15d24c4
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+enum E {
+    Foo{f : int},
+    Bar
+}
+
+pub fn main() {
+    let e = Foo{f: 1};
+    match e {
+        Foo{_} => (),
+        _ => fail!(),
+    }
+    match e {
+        Foo{f: _f} => (),
+        _ => fail!(),
+    }
+}
diff --git a/src/test/run-pass/match-struct-0.rs b/src/test/run-pass/match-struct-0.rs
new file mode 100644 (file)
index 0000000..67e844c
--- /dev/null
@@ -0,0 +1,29 @@
+// 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.
+
+struct Foo{
+    f : int,
+}
+
+pub fn main() {
+    let f = Foo{f: 1};
+    match f {
+        Foo{f: 0} => fail!(),
+        Foo{_} => (),
+    }
+    match f {
+        Foo{f: 0} => fail!(),
+        Foo{f: _f} => (),
+    }
+    match f {
+        Foo{f: 0} => fail!(),
+        _ => (),
+    }
+}
index 3e4cfdc105cadb966debf83ebfc0cae52902e073..493b810c10488592307665dace81dc2b45a282e5 100644 (file)
@@ -16,7 +16,7 @@
 
 use std::str::StrVector;
 use std::vec::ImmutableVector;
-use std::iterator::IteratorUtil;
+use std::iterator::Iterator;
 use std::int;
 
 trait to_str {
@@ -29,7 +29,7 @@ fn to_str(&self) -> ~str { int::to_str(*self) }
 
 impl<T:to_str> to_str for ~[T] {
     fn to_str(&self) -> ~str {
-        fmt!("[%s]", self.iter().transform(|e| e.to_str()).collect::<~[~str]>().connect(", "))
+        fmt!("[%s]", self.iter().map(|e| e.to_str()).collect::<~[~str]>().connect(", "))
     }
 }
 
diff --git a/src/test/run-pass/vec-matching-fixed.rs b/src/test/run-pass/vec-matching-fixed.rs
new file mode 100644 (file)
index 0000000..234311d
--- /dev/null
@@ -0,0 +1,28 @@
+fn a() {
+    let x = [1, 2, 3];
+    match x {
+        [1, 2, 4] => ::std::util::unreachable(),
+        [0, 2, 3, .._] => ::std::util::unreachable(),
+        [0, .._, 3] => ::std::util::unreachable(),
+        [0, .._] => ::std::util::unreachable(),
+        [1, 2, 3] => (),
+        [_, _, _] => ::std::util::unreachable(),
+    }
+    match x {
+        [.._] => (),
+    }
+    match x {
+        [_, _, _, .._] => (),
+    }
+    match x {
+        [a, b, c] => {
+            assert_eq!(1, a);
+            assert_eq!(2, b);
+            assert_eq!(3, c);
+        }
+    }
+}
+
+pub fn main() {
+    a();
+}
index 5e906fa265994c9efded6eca74817bf84b962c25..fb73c7e097dcf023502c57a29c732196f1bef62a 100644 (file)
@@ -1,5 +1,5 @@
 fn a() {
-    let x = [1];
+    let x = ~[1];
     match x {
         [_, _, _, _, _, .._] => ::std::util::unreachable(),
         [.._, _, _, _, _] => ::std::util::unreachable(),
@@ -13,7 +13,7 @@ fn a() {
 }
 
 fn b() {
-    let x = [1, 2, 3];
+    let x = ~[1, 2, 3];
     match x {
         [a, b, ..c] => {
             assert_eq!(a, 1);
index 27f4fc833511ae7cf49b00e19cec0131e6199782..6a60308f2e70f0efec1e088a98cf925ddc411bb9 100644 (file)
@@ -3,7 +3,7 @@ struct Foo {
 }
 
 pub fn main() {
-    let x = [
+    let x = ~[
         Foo { string: ~"foo" },
         Foo { string: ~"bar" },
         Foo { string: ~"baz" }